自作シェルの進捗とBashの細かい話(2024年6月2日)

Sun Jun 2 18:45:30 JST 2024 (modified: Sun Jun 2 21:48:52 JST 2024)
views: 1777, keywords:自作シェル, 寿司シェル, sush

 自作シェルの開発が暴走気味なのでドキュメントを残すための記事です。普段使いするようになって、自分を楽させるために大量の時間をつぎ込んでます。怠惰はプログラマーのなんとかですね・・・。

補完機能の強化その1

 こんなふうにタブ2回で出した補完の候補を、そのままタブや矢印キーで選択できるようにしました。

補完機能の強化その2

 gitのサブコマンドで補完候補を変える機能を少し実装しました。 といってもシェル側の対応は少しで、 .bashrcに相当する.sushrcに補完用の関数を書きました。 いま使っている.sushrcを示します。このなかの_git_compが補完用の関数です。 関数のあんまりきれいでないif文については、読み方を https://blog.cybozu.io/entry/2016/09/26/080000 に丸投げします。


   🍣 cat ~/.sushrc
   case $- in
       *i*) ;;
         *) return ;;
   esac
   
   PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;36m\]\b\[\033[00m\]\[\033[01;35m\]\w\[\033[00m\]🍣 '
   PS2='> '
   alias ls='ls --color=auto'
   
   alias git-writing='git add -A ; git commit -m Writing; git push'
   
   _git_comp () {   #これ以下がgitに対する補完の仕掛け
       if [ "$COMP_CWORD" = 1 ] ; then #git と打った後にサブコマンドを打つ前か打っている途中
           CANDS=( $( git |& grep '^  *[a-z]' | awk '{print $1}') ) #ヘルプからサブコマンドのリストを作る
           COMPREPLY=( $(compgen -W "${CANDS[@]}" -- "${cur}") )    # ${cur}(打っている途中の文字列)と一致するものを補完候補に
       elif [ "$COMP_CWORD" = 2 -a "$prev" = switch ] ; then #git switchのとき
           COMPREPLY=( $(compgen -W "$( git branch | tr -d '*' )" -- "${cur}" ) ) #ブランチの一覧を${cur}でフィルタをかけて補完候補に
       elif [ "$COMP_CWORD" = 2 -a "$prev" = merge ] ; then  #git mergeのとき
           COMPREPLY=( $(compgen -W "$( git branch | tr -d '*' )" -- "${cur}" ) ) #同上
           elif [ "$COMP_CWORD" = 2 -a "$prev" = diff ] ; then  #git diffのとき
                   COMPREPLY=( $(compgen -W "$(compgen -f) $( git branch | tr -d '*' )"  -- "${cur}" ) )  #ファイルとブランチの両方を補完候補に
       fi #ほんとはもっと分岐する 
   } && complete -F _git_comp git  #関数の定義がうまくいったらgitの補完関数として_git_compを登録

 これで、次のように状況に応じて補完候補が切り替わります(候補が1つしかないときは補完されます)。


   ### git <tab><tab>と打ったとき ###
   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 git
   clone   add     restore bisect  grep    show    branch  merge   reset   tag     pull
   init    mv      rm      diff    log     status  commit  rebase  switch  fetch   push
   ### git r<tab><tab>と打ったとき ###
   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 git r 
   restore rm      rebase  reset
   ### git switch <tab><tab>と打ったとき ###
   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 git switch
   dev-completion sd/202407_5    sd/202411_1    sd/202502_1    sd/202504_5    terminal_13
   main           sd/202408_0    sd/202411_2    sd/202502_2    sd/202504_ref  terminal_14
   prepare_1      sd/202408_1    sd/202411_3    sd/202502_3    sd/202505_0    terminal_15
   (以下略)
   ### git switch <tab><tab>と打ったとき(ブランチの他、ファイルも補完候補に) ###
   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 git diff 
   .git              sd/202405_2       sd/202409_3       sd/202501_1       sd/202504_1       terminal_11       
   .github           sd/202405_3       sd/202409_4       sd/202501_2       sd/202504_2       terminal_12       
   .gitignore        sd/202406_0       sd/202410_0       sd/202501_3       sd/202504_3       terminal_13 
   (以下略)

仕事しながらもうちょっと~/.sushrcを充実させてみようと思います。

SIGPIPEとPIPESTATUSへの対応

 しました。パイプが詰まるとコマンドが終了ステータス141を出します。いままでの実装だとSIGPIPEをシェルが受け取ってコマンドに行かないという現象が見られたので、寿司シェル側ではSIGPIPEを無視するようにしました。サブシェルでは無視しないように設定を戻します。


   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 seq 10 | true
   Pid: Pid(296910), Signal: SIGPIPE
   ueda@uedaP1g6:main🌵~/GIT/rusty_bash🍣 echo ${PIPESTATUS[@]}
   141 0

まだまだBashに比べると機能が少ないのですが、普段使う分にはいい感じになってきました。

 現場からは以上です。

ノート   このエントリーをはてなブックマークに追加 
 

prev:自作シェルの進捗とBashの細かい話(2024年5月26日) next:自作シェルの進捗とBashの細かい話(2024年6月9日)

やり散らかし一覧

記事いろいろ