はじめに
batコマンドという高級なcatコマンドのようなものを普段使っているのですが
オプションについて変更したい点がいくつかあったので、オプション部分の実装を見ると同時に変更を加えてみました。
batとは
batとはcatコマンドにsyntax highlighting機能やlessコマンドに備わっているpaging機能を追加したコマンド
です。
https://github.com/sharkdp/bat
bat src/index.html
変更した箇所
batコマンドはファイルが大きい場合、pagingというファイルの一部だけを表示し、jで下へ、kで上へスクロー ルするモードに入ります。
ですが私としては、ファイルが大きい場合でもpagingモードに入らずに全てを表示してほしいです。
batコマンドでは-Pオプションを付与することでそれを行えます。
ですが、デフォルトでpagingをオフにし、-Pオプションを指定した時にだけpagingモードに入るようにしたいです。
ということでソースコードを変更し、それを実現させていきます。
コード解析および変更
オプションの定義はsrc/bat/bin/clap_app.rs
にあります。
このファイルの319~346行にpagingオプションの定義があります。
.arg(
Arg::new("paging")
.long("paging")
.overrides_with("paging")
.overrides_with("no-paging")
.value_name("when")
.value_parser(["auto", "never", "always"])
.default_value("auto")
.hide_default_value(true)
.help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).")
.long_help(
"Specify when to use the pager. To disable the pager, use \
--paging=never' or its alias,'-P'. To disable the pager permanently, \
set BAT_PAGING to 'never'. To control which pager is used, see the \
'--pager' option. Possible values: *auto*, never, always."
),
)
.arg(
Arg::new("no-paging")
.short('P')
.long("no-paging")
.alias("no-pager")
.action(ArgAction::SetTrue)
.overrides_with("no-paging")
.hide(true)
.hide_short_help(true)
.help("Alias for '--paging=never'")
)
これを見るとpagingにはauto、always、neverの3種類がある用です。
そしてデフォルトではautoになっています。
autoということはファイルの大きさでpagingモードに入るか入らないかを決めているのだと推測できます。
default_valueをneverにすればオプションを指定しなければpagingモードに入ることができないようにできそうです。
次にno-pagingですが、これはこのオプションを指定した際に--paging=never
としてくれるオプションの 用です。
これを少し改良し、--paging=always
とすることで、オプションを指定した時にのみpagingモードに入れ るようにできます。
これにはsrc/bin/bat/app.rs
の方も変更する必要があるのですが、一旦オプション定義の方だけ以下のように変更します。
.arg(
Arg::new("paging")
.long("paging")
.overrides_with("paging")
.overrides_with("allow-paging")
.value_name("when")
.value_parser(["auto", "never", "always"])
.default_value("never")
.hide_default_value(true)
.help("Specify when to use the pager, or use `-P` to disable (*auto*, never, always).")
.long_help(
"Specify when to use the pager. To disable the pager, use \
--paging=never' or its alias,'-P'. To disable the pager permanently, \
set BAT_PAGING to 'never'. To control which pager is used, see the \
'--pager' option. Possible values: *auto*, never, always."
),
)
.arg(
Arg::new("allow-paging")
.short('P')
.long("allow-paging")
.alias("allow-pager")
.action(ArgAction::SetTrue)
.overrides_with("allow-paging")
.hide(true)
.hide_short_help(true)
.help("Alias for '--paging=never'")
)
no-pagingに関してはallow-pagingに名前を変更しています。
ですが、名前を変更しただけでは--paging=neverと指定するという機能を変更できないので、次は先ほど言ったapp.rsに変更を加えます。
Some("never") => {
PagingMode::Never
}
Some("auto") | None => {
if extra_plain || self.matches.get_flag("no-paging") {
PagingMode::Never
} else if inputs.iter().any(Input::is_stdin) {
*/
if inputs.iter().any(Input::is_stdin) {
...
98行目のconfig関数でオプションを基にpagingモードをonかoffどちらにするかを決めています。
--paging=autoだと--no-pagingオプションが指定されている場合はpagingモードがoffになります。
ここを以下のように変更します。
Some("never") => {
if self.matches.get_flag("allow-paging") {
PagingMode::Always
} else {
PagingMode::Never
}
}
Some("auto") | None => {
// If we have -pp as an option when in auto mode, the pager should be disabled.
/*
if extra_plain || self.matches.get_flag("no-paging") {
PagingMode::Never
} else if inputs.iter().any(Input::is_stdin) {
*/
if inputs.iter().any(Input::is_stdin) {
...
no-pagingオプションはもう無いので、そこの処理は消します。
その代わり--paging=neverとなっていた場合の処理に、--allow-pagingオプションが指定されていた場合はpagingをonにする処理を追加します。
ビルド
上記の変更を行った上で以下のコマンドでビルドします。
README.mdが置かれているディレクトリで実行します。
ビルドされた実行ファイルは$HOME/.cargo/binに置かれます。
cargo install --path . --locked
検証
適当なファイルに対し以下のコマンドを実行し、変更が反映されているか確認してみてください。
1つ目のコマンドではファイルが大きいにも関わらずpagingモードがonになりません。
2つ目のコマンドでは-Pオプションを指定することにより手動でpagingモードに入れます。
bat src/bat/bin/app.rs
bat -P src/bat/bin/app.rs
さいごに
今回改造したものは私のgithubレポジトリに公開しておきます。
気になった方は上記のコマンドでビルドして使ってみてください。
https://github.com/sota70/bat