Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

TrueColor対応のはなし(端末、シェル、tmux、vim)

TrueColorで表示するのは、わりかし対応がめんどうです。なぜなら、Vim、tmux、zsh、ターミナル全てで対応しなければならないからです。今回はそれぞれどういった対応をすればいいのか紹介します。

まず: TrueColor に対応できているか確認する

TrueColor 対応をする前に、そもそも今対応できているかチェックしましょう。以下のコマンドを実行してください。

$ curl -s https://gist.githubusercontent.com/lifepillar/09a44b8cf0f9397465614e622979107f/raw/24-bit-color.sh | bash

このように継ぎ目がなければOKです。↓

下のように階段状になっていたら対応できていません。↓

上でもかなり明白に違いますが、NeoVimでTrueColor対応できていないと更に明らかになります。

TrueColor非対応
TrueColor対応

TrueColor対応をしたあと、ちゃんと反映できているか上のコマンドで確認してください。

余談: ターミナルの色の種類

まず、ターミナルの色には2種類あります。

TrueColor
いわゆる#ffffff。RGBそれぞれ8ビットを用いて表現します。24ビットカラー(RGB)と、さらに透明度8ビットを合わせた32ビットカラー(RGBA)が存在します。
8-bit color
256色まで表せる方式。256までの数字のみを用います。xtermやscreenなど、それぞれで色の割り当てが異なっています。

TrueColor に対応できていない場合、8-bit color で表示されます。8-bit color は256色しか表示できないので、当然表現力はガクッと落ちます。

続きを読む

tcomment_vimをドットリピートできるようにする

repeat.vimを併用することで対応させます。

# dein.toml
[[plugins]]
repo = 'tpope/vim-repeat'

[[plugins]]
repo = 'tomtom/tcomment_vim'
hook_add = '''
au MyAutoCmd VimEnter * nnoremap <silent> <Plug>RepeatTComment :TComment<Bar>
            \ silent! call repeat#set("\<Plug>RepeatTComment")<CR>
au MyAutoCmd VimEnter * nmap <c-_><c-_> <Plug>RepeatTComment
'''

解説

根幹となるのは「nnoremap <silent> <Plug>RepeatTComment」と「nmap <c-_><c-_> <Plug>RepeatTComment」の部分です。

前者は<Plug>RepeatTComment:TComment <Bar> ...を割り当てています。:TCommentを実行したあとにsilent! call repeat#set("\<Plug>RepeatTComment")<CR>を実行しているだけです。repeat.vimはドットを押すと、repeat#setで登録したコマンドが実行されるようになっているので、<Plug>RepeatTCommentが呼ばれた直後にrepeat#setで登録することで繰り返しを実現します。

これが大まかな部分で、残りのコード(au MyAutoCmd VimEnter *など)は読み込むタイミングを制御しているだけです。

注意

上のコードではaugroup MyAutoCmdを行っています。詳しい解説はこの記事ではしないので、以下の参考リンクなどをお読みください。

参考

競プロで使うBashテク

スペース -> 改行

  • | xargs -n1
  • | tr ' ' '\n'
  • | tr \ \\n (上のものをエスケープしたもの)

改行 -> スペース

  • | xargs
  • | tr '\n' ' '
  • | tr \\n \

行数カウント

  • | wc -l
  • | awk 'END{print NR}'
  • | awk '$0=NR' | tail -n1

これはwc -lだけで十分ですね

先頭1行だけ取り出す

  • | head -n1
  • | awk 'NR==1'

head -n1はかなり使えるのでよく覚えましょう

先頭1行だけ削除

  • read _ で受け取ってしまう
  • | tail -n +1
  • | sed -e '1d'
  • | awk 'NR!=1'

末尾1行だけ取り出す

  • | tail -n1
  • | sed -e '$p;d'
  • | awk 'END{print $0}'

sedとawkは末尾n行に対応できていないので、tailさえ覚えておけば事足りると思います

末尾1行だけ削除

これはそこそこレアケースな気がする(なぜなら上3つでだいたい事足りるため)

  • | head -n -1
  • | sed -e '$d'

重複をカウント

  • | sort | uniq -c

各行をトリムする

  • | sed -e 's/^\s*//'
  • | sed -e 's/^\s*\|\s*$//'

後ろ側のトリムが必要になることはあまりないです。

ソート関連

  • | sort -n 辞書順ではなく数値とみなして比較
  • | sort -nk1 キー指定
  • | sort -nr 降順

あまり使えないテク

  • echo {A..Z}' 半角のアルファベットを列挙する
  • zsh -c 'echo {A..Z}|tr -d " "' 全角のアルファベットを列挙する。bashはこのブレース展開をしてくれないので、zshで行う
  • ruby -ne 'puts $_.tr("0-9a-zA-Z","0-9a-zA-Z")' Rubyが使えるなら、これで全角→半角変換ができる

Vimでbashコマンドを併用するとできること7選

Vimはexコマンド(:q:w)だけでなく、シェルコマンドを実行することができます。今回はシェルコマンドをつかってもっと便利に編集をしようという記事です。

基本: コマンドを実行したい行を指定

Vimのコマンドは、実行したい範囲を決めることができます。

  • :%!sort バッファ全体をソートする
  • :'<,'>!sed -e 'y/123/ABC/' 選択範囲でsedを実行する
  • :.!tr -d ' ' 現在の行の空白を削除する

一番前にある記号(%.'<,'>)がコマンドの実行範囲を表します。たとえば%ならバッファ全体、'<,'>なら選択範囲といった具合です。そのほかに行数を使った範囲指定などもありますが、主に使うのは上の3つだと思います。

基本: 外部のコマンドを実行する

外部のコマンドの実行結果を今のカーソル位置に挿入するには、!!と入力してからコマンドを指定するとできます。たとえば!!lsならカレントディレクトリのファイルを表示します。

範囲を指定する場合は、:(範囲)!(外部コマンド)とします。

1. 連番の作成

コマンド実行結果
!!seq 100 | tr '\n' ' '1 2 3 ... 99 100
!!seq 1001
2
...
100
!!echo {1..100}1 2 3 ... 99 100

ぼくは!!seq 100を実行してJで連結しています。

2. アルファベット26文字を列挙

コマンド実行結果
!!echo {a..z} | tr -d ' 'abcdefghijklmnopqrstuvwxyz
!!for i in {a..z}; do echo -n $i; done(同上)
!!echo {a..z}a b c d e f g h i j k l m n o p q r s t u v w x y z

僕はよく!!echo {a..z}を実行したあとに:s/ //gで空白を削除しています。

3. Awk

Awkが使えると選択範囲の総和といった操作がカンタンにできるようになります。

コマンド実行結果
:'<,'>!awk '{sum+=$0}END{print sum}'選択範囲の総和
続きを読む

ABCのA問題で二度とWAしないためのツールを作りました

github.com

その名も「失敗は死(Failure is Death)」です。たぶん英語としては間違えてますが、カッコイイのでこのままで。

機能

AtCoderのコードテストをちょっと強くしたものになります。複数のテストケースを同時に試せるので、コードの書き換えをしたあとの検証などで利用できます。A問題でいちいち準備したりするのが億劫だったのでこのような形式になりました。

たとえばこの問題の場合は次のような感じで試すことができます(この問題が結構すき)。

f:id:panda_noir:20190821203109p:plain

execを押すと、以下のようにテストケースそれぞれの出力を表示します。 f:id:panda_noir:20190821203118p:plain

内部としては

  1. コードとテストケースを受け取る
  2. 外部コマンド(sedなりRubyなり)を呼び出す
  3. 実行結果を表示する

となっているので、たとえばRubyでジャッジしたい場合はあらかじめRubyを入れる必要があります。

開発の流れ

今回はRustを使って作ってみました。GUIの開発だったので、Gtkを使いました。

作ってて思ったことをいくつか。まず、入力フォーム一つ作るのに非常に苦労しました。まず、どれがフォームを指しているのかを調べるところから始まりました。結論としてはEntryが1行のみの入力フォーム、TextViewが複数行のフォームのようです。ただし、これらはundoすらできないので、SourceViewというところのViewを使うのをおすすめします。

また、テキストボックスのサイズの設定が未だにわかりません。どうすればいいのやら…

参考資料