1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

batコマンド解剖

Last updated at Posted at 2024-12-22

はじめに

batコマンドという高級なcatコマンドのようなものを普段使っているのですが
オプションについて変更したい点がいくつかあったので、オプション部分の実装を見ると同時に変更を加えてみました。

batとは

batとはcatコマンドにsyntax highlighting機能やlessコマンドに備わっているpaging機能を追加したコマンド
です。
https://github.com/sharkdp/bat

bat src/index.html

alt text

変更した箇所

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

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?