zshのプロンプトでコマンド実行開始/終了時刻を出力する

October 26, 2020

さっきのコマンドいつ実行してどのくらい時間かかったっけ?がわりと頻繁に気になるので、コマンドの実行開始時刻と終了時刻をプロンプトに出力するようにしている。
少しググった感じRPROMPT(画面右端)に時刻を出している方はいらっしゃるのですが、それだと操作ログを取ったりslackにコピペしたりした時にレイアウトが崩れるのが個人的に気になる。

そのため以下のように左側に出力している。

具体的には、もともとPreztoでkylewestというテーマを使っていたのでそれを改造している。
いろいろ書いてあるが基本はkylewestの実装ベースで、今回の内容に関係するのはハイライト部分のみ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
export LASTCMD_END_TIME

function prompt_kylewest_mod_precmd {
  setopt LOCAL_OPTIONS
  unsetopt XTRACE KSH_ARRAYS

  # Get Git repository information.
  if (( $+functions[git-info] )); then
    git-info
  fi

  # Get Ruby information.
  if (( $+functions[ruby-info] )); then
    ruby-info
  fi

  LASTCMD_END_TIME=$(date "+%H:%M:%S")
}

function prompt_kylewest_mod_setup {
  setopt LOCAL_OPTIONS
  unsetopt XTRACE KSH_ARRAYS
  prompt_opts=(cr percent sp subst)

  # Load required functions.
  autoload -Uz add-zsh-hook

  # Add hook for calling git-info before each command.
  add-zsh-hook precmd prompt_kylewest_mod_precmd

  # Set editor-info parameters.
  zstyle ':prezto:module:editor:info:completing' format '%B%F{red}...%f%b'
  zstyle ':prezto:module:editor:info:keymap:primary' format "%B%F{green}❯%f%b"
  zstyle ':prezto:module:editor:info:keymap:alternate' format "%B%F{magenta}❮%f%b"

  # Set git-info parameters.
  zstyle ':prezto:module:git:info' verbose 'no'
  zstyle ':prezto:module:git:info:branch' format '%F{yellow}%b%f'
  zstyle ':prezto:module:git:info:dirty' format '%B%F{red}!%f%b'
  zstyle ':prezto:module:git:info:indexed' format ' '
  zstyle ':prezto:module:git:info:unindexed' format ' '
  zstyle ':prezto:module:git:info:untracked' format ' '
  zstyle ':prezto:module:git:info:keys' format 'prompt' '- %b%D '

  # Set ruby-info parameters.
  zstyle ':prezto:module:ruby:info:version' format '%F{blue}[%v]%f'

  # Define prompts.
  PROMPT_TOP='%F{243}-> ${LASTCMD_END_TIME}%f'$'\n'
  PROMPT_MIDDLE='%F{243}%D{%Y-%m-%d %H:%M:%S}%f %F{cyan}%c%f ${git_info:+${(e)git_info[prompt]}}${editor_info[keymap]} '
  PROMPT="${PROMPT_TOP}${PROMPT_MIDDLE}"
  RPROMPT='${ruby_info[version]}'
}

prompt_kylewest_mod_setup "$@"

LASTCMD_END_TIME にプロンプト表示直前、つまり一つ前のコマンド終了時刻を保存しておく(本文末尾のブログ記事を参考にさせて頂いた)。
%D というzshのエスケープシーケンスを使うとプロンプト更新時の時刻が表示される、つまりコマンド開始時刻が表示される。
両者をまとめてPROMPTに、2行に分けて設定している。

欠点としてどこまでがコマンド実行結果でどこからがプロンプトなのか一見さんには分からないので、ひとまずうっすらした文字色に変更して区別できるようにしている。でも結局slackにコピペしたら分からない。。
時刻ではなくて、実行時間sec、msecなどを計算してもいいかなと思ったのだけど、そうしたらどこに表示するのがしっくりくるか思いつかなかった。

もっと気のきいた方法をご存知の方いたら教えてください。

参考
zshの右プロンプトにコマンド開始終了時刻を表示 - 余白の書きなぐり

@j_untanaka on Twitter

zsh