LoginSignup
4
4

alt cliツール 紹介 【lsd】【difftastic】【bat】

Last updated at Posted at 2023-12-08

/darallium/です!ご覧いただきありがとうございます. 😊

「CLI初心者でも感動するような,それでいて汎用性・拡張性の高いCLIツール」を紹介する7日間の2日目の記事です 🙇

本日は「CLIツールそのもののの強化」をテーマに,lsd, ripgrep, difftasticを紹介します:relaxed:

lsd

image.png
image.png
lsd とは,Rustで書かれた「lsの完全上位互換」ツールである.一般に,fishを使うかある程度凝らなければいけない.lsのカラーリング,nerdfontなどを用いて視覚的にファイルを管理できる.

installation

dependencies

  • cargo

mac, windows, linux

$ cargo install --git https://github.com/Peltoche/lsd.git --branch master

下記のように公式ドキュメントにはエイリアスを張る例もあるが,筆者はお勧めしない.

alias ls = 'lsd'
alias l='lsd -l'
alias la='lsd -a'
alias lla='lsd -la'
alias lt='lsd --tree'

※注意: 公式のreleaseは古いのでmasterブランチからbuildすること.

できること

とりあえず色んなディレクトリでlsdして遊んでみるとよいだろう.コマンドライン引数はlsと同一なのでいろいろ試してみよう.デフォルトでもnerdfontフォントが貼ってあるので楽しめるだろう.

configをいじってみる

cliツールの醍醐味であるconfigをいじって自分好みのlasを作ってみよう.今回はサンプルを変更する形で自分好みのテーマを作ってみることを目標とする

デフォルトコンフィグを読み込む

以下に公式によるサンプルの改変を添付する.公式サンプルは動かないのである.ファイルの配置先は,linux,macOSユーザーの場合~/.config/lsd/,windowsユーザーの場合%appdata%\lsd\である.ファイル名はすべて固定であることに注意.

config.yaml
# == Classic ==
# This is a shorthand to override some of the options to be backwards compatible
# with `ls`. It affects the "color"->"when", "sorting"->"dir-grouping", "date"
# and "icons"->"when" options.
# Possible values: false, true
classic: false

# == Blocks ==
# This specifies the columns and their order when using the long and the tree
# layout.
# Possible values: permission, user, group, context, size, date, name, inode, links, git
blocks:
  - permission
  - user
  - group
  - size
  - date
  - name

# == Color ==
# This has various color options. (Will be expanded in the future.)
color:
  # When to colorize the output.
  # When "classic" is set, this is set to "never".
  # Possible values: never, auto, always
  when: auto
  # How to colorize the output.
  # When "classic" is set, this is set to "no-color".
  # Possible values: default, custom
  # When "custom" is set, lsd will look in the config directory for `colors.yaml`.
  theme: custom

# == Date ==
# This specifies the date format for the date column. The freeform format
# accepts a strftime like string.
# When "classic" is set, this is set to "date".
# Possible values: date, relative, '+<date_format>'
# `date_format` will be a `strftime` formatted value. e.g. `date: '+%d %b %y %X'` will give you a date like this: 17 Jun 21 20:14:55
date: date

# == Dereference ==
# Whether to dereference symbolic links.
# Possible values: false, true
dereference: false

# == Display ==
# What items to display. Do not specify this for the default behavior.
# Possible values: all, almost-all, directory-only
# display: all

# == Icons ==
icons:
  # When to use icons.
  # When "classic" is set, this is set to "never".
  # Possible values: always, auto, never
  when: always
  # Which icon theme to use.
  # Possible values: fancy, unicode
  theme: fancy
  # Separator between icon and the name
  # Default to 1 space
  separator: " "

# == Ignore Globs ==
# A list of globs to ignore when listing.
# ignore-globs:
#   - .git

# == Indicators ==
# Whether to add indicator characters to certain listed files.
# Possible values: false, true
indicators: false

# == Layout ==
# Which layout to use. "oneline" might be a bit confusing here and should be
# called "one-per-line". It might be changed in the future.
# Possible values: grid, tree, oneline
layout: grid

# == Recursion ==
recursion:
  # Whether to enable recursion.
  # Possible values: false, true
  enabled: false
  # How deep the recursion should go. This has to be a positive integer. Leave
  # it unspecified for (virtually) infinite.
  # depth: 3

# == Size ==
# Specifies the format of the size column.
# Possible values: default, short, bytes
size: default

# == Permission ==
# Specify the format of the permission column
# Possible value: rwx, octal
permission: rwx

# == Sorting ==
sorting:
  # Specify what to sort by.
  # Possible values: extension, name, time, size, version
  column: name
  # Whether to reverse the sorting.
  # Possible values: false, true
  reverse: false
  # Whether to group directories together and where.
  # When "classic" is set, this is set to "none".
  # Possible values: first, last, none
  dir-grouping: none

# == No Symlink ==
# Whether to omit showing symlink targets
# Possible values: false, true
no-symlink: false

# == Total size ==
# Whether to display the total size of directories.
# Possible values: false, true
total-size: false

# == Hyperlink ==
# Attach hyperlink to filenames
# Possible values: always, auto, never
hyperlink: never

# == Symlink arrow ==
# Specifies how the symlink arrow display, chars in both ascii and utf8
symlink-arrow: 

# == Header ==
# Whether to display block headers.
# Possible values: false, true
header: false

# == Literal ==
# Whether to show quotes on filenames.
# Possible values: false, true
literal: false

# == Truncate owner ==
# How to truncate the username and group names for a file if they exceed a certain
# number of characters.
truncate-owner:
  # Number of characters to keep. By default, no truncation is done (empty value).
  after:
  # String to be appended to a name if truncated.
  marker: ""
colors.yaml
user: 230
group: 187
permission:
  read: dark_green
  write: dark_yellow
  exec: dark_red
  exec-sticky: 5
  no-access: 245
  octal: 6
  acl: dark_cyan
  context: cyan
date:
  hour-old: 40
  day-old: 42
  older: 36
size:
  none: 245
  small: 229
  medium: 216
  large: 172
inode:
  valid: 13
  invalid: 245
links:
  valid: 13
  invalid: 245
tree-edge: 245
git-status:
  default: 245
  unmodified: 245
  ignored: 245
  new-in-index: dark_green
  new-in-workdir: dark_green
  typechange: dark_yellow
  deleted: dark_red
  renamed: dark_green
  modified: dark_yellow
  conflicted: dark_red
icons.yaml
name:
  a.out: 
  Api: 󰒍
  .asoundrc: 
  .atom: 
  .ash: 
  .ash_history: 
  authorized_keys: 
  assets: 
  .android: 
  .audacity-data: 
  backups: 󰁯
  .bash_history: 󱆃
  .bash_logout: 󱆃
  .bash_profile: 󱆃
  .bashrc: 󱆃
  bin: 
  .bpython_history: 
  build: 
  bspwmrc: 
  build.ninja: 
  .cache: 󰃨
  cache: 󰃨
  cargo.lock: 
  cargo.toml: 
  .cargo: 
  .ccls-cache: 󰃨
  changelog: 
  .clang-format: 
  composer.json: 
  composer.lock: 
  conf.d: 
  config.ac: 
  config.el: 
  config.mk: 
  .config: 
  config: 
  configure: 
  content: 
  contributing: 
  copyright: 
  cron.daily: 
  cron.d: 
  cron.deny: 
  cron.hourly: 
  cron.monthly: 
  crontab: 
  cron.weekly: 
  crypttab: 
  .cshrc: 󱆃
  csh.cshrc: 󱆃
  csh.login: 󱆃
  csh.logout: 󱆃
  css: 
  custom.el: 
  .dbus: 
  desktop: 
  docker-compose.yml: 
  dockerfile: 
  doc: 
  dist: 
  documents: 
  .doom.d: 
  downloads: 󰉍
  .ds_store: 
  .editorconfig: 
  .electron-gyp: 
  .emacs.d: 
  .env: 
  environment: 
  .eslintrc.json: 
  .eslintrc.js: 
  .eslintrc.yml: 
  etc: 
  favicon.ico: 
  favicons: 
  fstab: 
  .fastboot: 
  .gitattributes: 
  .gitconfig: 
  .git-credentials: 
  .github: 
  gitignore_global: 
  .gitignore: 
  .gitlab-ci.yml: 
  .gitmodules: 
  .git: 
  .gnupg: 󰢬
  go.mod: 
  go.sum: 
  go.work: 
  gradle: 
  gradle.properties: 
  gradlew: 
  gradlew.bat: 
  group: 
  gruntfile.coffee: 
  gruntfile.js: 
  gruntfile.ls: 
  gshadow: 
  gulpfile.coffee: 
  gulpfile.js: 
  gulpfile.ls: 
  heroku.yml: 
  hidden: 
  home: 
  hostname: 
  hosts: 󰀂
  .htaccess: 
  htoprc: 
  .htpasswd: 
  .icons: 
  icons: 
  id_dsa: 󰷖
  id_ecdsa: 󰷖
  id_rsa: 󰷖
  .idlerc: 
  img: 
  include: 
  init.el: 
  .inputrc: 
  inputrc: 
  .java: 
  jenkinsfile: 
  js: 
  .jupyter: 
  kbuild: 
  kconfig: 
  kdeglobals: 
  kdenliverc: 
  known_hosts: 
  .kshrc: 
  libexec: 
  lib32: 
  lib64: 
  lib: 
  license.md: 
  licenses: 
  license.txt: 
  license: 
  localized: 
  lsb-release: 
  .lynxrc: 
  .mailcap: 󰇰
  mail: 󰇰
  magic: 
  maintainers: 
  makefile.ac: 
  makefile: 
  manifest: 
  md5sum: 󰕥
  meson.build: 
  metadata: 
  metadata.xml: 
  media: 
  .mime.types: 󰙅
  mime.types: 󰙅
  module.symvers: 
  .mozilla: 
  music: 󱍙
  muttrc: 
  .muttrc: 
  .mutt: 
  .mypy_cache: 󰃨
  neomuttrc: 
  .neomuttrc: 
  netlify.toml: 
  .nix-channels: 
  .nix-defexpr: 
  .node-gyp: 
  node_modules: 
  .node_repl_history: 
  npmignore: 
  .npm: 
  nvim: 
  obj: 
  os-release: 
  package.json: 
  package-lock.json: 
  packages.el: 
  pam.d: 󰢬
  passwd: 
  pictures: 󰉏
  pkgbuild: 
  .pki: 
  portage: 
  profile: 
  .profile: 
  public: 
  __pycache__: 
  pyproject.toml: 
  .python_history: 
  .pypirc: 
  rc.lua: 
  readme: 
  .release.toml: 
  requirements.txt: 󰌠
  robots.txt: 󰚩
  root: 󰉐
  rubydoc: 
  runtime.txt: 󰌠
  .rustup: 
  rustfmt.toml: 
  .rvm: 
  sass: 
  sbin: 
  scripts: 
  scss: 
  sha256sum: 󰕥
  shadow: 
  share: 
  .shellcheckrc: 
  shells: 
  .spacemacs: 
  .sqlite_history: 
  src: 󱧼
  .ssh: 󰢬
  static: 
  std: 󰅱
  styles: 
  subgid: 
  subuid: 
  sudoers: 
  sxhkdrc: 
  template: 
  tests: 󰙨
  tigrc: 
  timezone: 
  tox.ini: 
  .trash: 
  ts: 
  .tox: 
  unlicense: 
  url: 
  user-dirs.dirs: 
  vagrantfile: 
  vendor: 󰫦
  venv: 󰌠
  videos: 
  .viminfo: 
  .vimrc: 
  vimrc: 
  .vim: 
  vim: 
  .vscode: 
  webpack.config.js: 󰜫
  .wgetrc: 
  wgetrc: 
  .xauthority: 
  .Xauthority: 
  xbps.d: 
  xbps-src: 
  .xinitrc: 
  .xmodmap: 
  .Xmodmap: 
  xmonad.hs: 
  xorg.conf.d: 
  .xprofile: 
  .Xprofile: 
  .xresources: 
  .yarnrc: 
  yarn.lock: 
  zathurarc: 
  .zcompdump: 
  .zlogin: 󱆃
  .zlogout: 󱆃
  .zprofile: 󱆃
  .zsh_history: 󱆃
  .zshrc: 󱆃
  .trash: 
  .cargo: 
  .emacs.d: 
  a.out: 
extension:
  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  7z: 
  8: 
  a: 
  ai: 
  ape: 
  apk: 
  ar: 
  asc: 󰦝
  asm: 
  asp: 
  avi: 
  avro: 
  awk: 
  bak: 󰁯
  bash_history: 
  bash_profile: 
  bashrc: 
  bash: 
  bat: 
  bin: 
  bio: 󰐑
  bmp: 
  bz2: 
  cc: 
  cfg: 
  cjs: 
  class: 
  cljs: 
  clj: 
  cls: 
  cl: 󰅲
  coffee: 
  conf: 
  cpp: 
  cp: 
  cshtml: 
  csh: 
  csproj: 󰌛
  css: 
  cs: 󰌛
  csv: 
  csx: 󰌛
  cts: 
  c++: 
  c: 
  cue: 
  cxx: 
  cypher: 
  dart: 
  dat: 
  db: 
  deb: 
  desktop: 
  diff: 
  dll: 
  dockerfile: 
  doc: 
  docx: 
  download: 
  ds_store: 
  dump: 
  ebook: 
  ebuild: 
  eclass: 
  editorconfig: 
  egg-info: 
  ejs: 
  elc: 󰅲
  elf: 
  elm: 
  el: 󰅲
  env: 
  eot: 
  epub: 
  erb: 
  erl: 
  exe: 
  exs: 
  ex: 
  fish: 
  flac: 
  flv: 
  font: 
  fpl: 󰐑
  fsi: 
  fs: 
  fsx: 
  gdoc: 
  gemfile: 
  gemspec: 
  gform: 
  gif: 
  git: 
  go: 
  gradle: 
  gsheet: 
  gslides: 
  guardfile: 
  gv: 󱁉
  gz: 
  hbs: 
  heic: 
  heif: 
  heix: 
  hh: 
  hpp: 
  hs: 
  html: 
  htm: 
  h: 
  hxx: 
  ico: 
  image: 
  img: 
  iml: 
  info: 
  in: 
  ini: 
  ipynb: 
  iso: 
  j2: 
  jar: 
  java: 
  jinja: 
  jl: 
  jpeg: 
  jpg: 
  jsonc: 
  json: 
  js: 
  jsx: 
  key: 󰌆
  ksh: 
  kt: 
  kts: 
  kusto: 
  ldb: 
  ld: 
  less: 
  lhs: 
  license: 
  lisp: 󰅲
  list: 
  localized: 
  lock: 
  log: 
  lss: 
  lua: 
  lz: 
  mgc: 
  m3u8: 󰐑
  m3u: 󰐑
  m4a: 
  m4v: 
  magnet: 
  malloy: 
  man: 
  markdown: 
  md: 
  mjs: 
  mkd: 
  mk: 
  mkv: 
  ml: 
  mli: 
  mll: 
  mly: 
  mobi: 
  mov: 
  mp3: 
  mp4: 
  msi: 
  mts: 
  mustache: 
  nix: 
  npmignore: 
  odp: 
  ods: 
  odt: 
  ogg: 
  ogv: 
  old: 󰁯
  opus: 
  orig: 󰁯
  org: 
  otf: 
  o: 
  part: 
  patch: 
  pdb: 󰪪
  pdf: 
  pem: 󰌆
  phar: 
  php: 
  pkg: 
  pl: 
  plist: 
  pls: 󰐑
  plx: 
  pm: 
  png: 
  pod: 
  pp: 
  ppt: 
  pptx: 
  procfile: 
  properties: 
  prql: 
  ps1: 
  psd: 
  pub: 󰌆
  slt: 󰈡
  pxm: 
  pyc: 
  py: 
  rakefile: 
  rar: 
  razor: 
  rb: 
  rdata: 󰟔
  rdb: 
  rdoc: 
  rds: 󰟔
  readme: 
  rlib: 
  rl: 
  rmd: 
  rmeta: 
  rpm: 
  rproj: 󰗆
  rq: 
  rspec_parallel: 
  rspec_status: 
  rspec: 
  rss: 
  rs: 
  rtf: 
  rubydoc: 
  r: 󰟔
  ru: 
  sass: 
  scala: 
  scpt: 
  scss: 
  shell: 
  sh: 
  sig: 
  slim: 
  sln: 
  so: 
  sqlite3: 
  sql: 
  srt: 󰨖
  styl: 
  stylus: 
  sublime-menu: 
  sublime-package: 
  sublime-project: 
  sublime-session: 
  sub: 󰨖
  s: 
  svg: 
  svelte: 
  swift: 
  swp: 
  sym: 
  tar: 
  taz: 
  tbz: 
  tbz2: 
  tex: 
  tgz: 
  tiff: 
  timestamp: 
  toml: 
  torrent: 󰒍
  trash: 
  ts: 
  tsx: 
  ttc: 
  ttf: 
  t: 
  twig: 
  txt: 
  unity: 
  unity32: 
  video: 
  vim: 
  vlc: 󰐑
  vue: 󰡄
  wav: 
  webm: 
  webp: 
  whl: 
  windows: 
  wma: 
  wmv: 
  woff2: 
  woff: 
  wpl: 󰐑
  xbps: 
  xcf: 
  xls: 
  xlsx: 
  xml: 
  xul: 
  xz: 
  yaml: y
  yml: y
  zip: 
  zig: 
  zshrc: 
  zsh-theme: 
  zsh: 
  zst: 
filetype:
  dir: 
  file: 
  pipe: 󰈲
  socket: 󰆨
  executable: 
  symlink_dir: 
  symlink_file: 
  device_char: 
  device_block: 󰜫
  special: 

改変してみる

image.png
image.png

上記になることを目標として遊んでみよう.

手始めにgitステータスを表示してみよう.config.yamlblocksgitを追加してみよう.config.yamlblocks節の順序が表示順序に作用するため,お好みの位置に挿入してみよう.
次に,日付の表示を変えてみよう.デフォのlsは冗長というか,日本人フレンドリーではないと感じたことはないだろうか? その場合はconfig.yamldate+%m/%d %yth %Tにしてみると良いのではないだろうか.また,時間の差分が必要だと思う人がいるかもしれない.その場合はdaterelativeにするとよい.
他に,config.yamllayouttreeにすると階層表示してくれる.その場合は参照する階層の上限を定めてみるとよいだろう.recursionenabledtrueにしてdepth3だか 2だかにしてみるとどうだろうか.

アイコンを変えてみよう.icons.yamlで設定できる.name``filetype``extensionの3項目でアイコンを設定できる.
filetypeは,/dev/sdaやフォルダなど特殊なものを設定できる.name固有な名前を設定できる..bashrcなどが該当するだろう.extensionは拡張子だ..yaml( 一一)を割り当ててみるとyamlを眺める顔が毎日見られるだろう.個人的なおすすめは,ジャンルごとにアイコンを設定し,それがそれとわかるアルファベットを先頭につけることだ.例えばdocxをdx📝にしている.人によってはpowerlineなどを使って遊んでみても楽しいだろう.

ここまでは表示するものを選択してきたが,ここからは表示様式を選んでみよう.カラースキームである.colors.yamlをいじいじして遊ぼう.githubでlsd colors.yamlで検索してみるとわかるが,このツールのカラースキームはほとんど存在しない.以下によさげなのがあったので添付しておく.ぜひ読者諸君の中にカラースキーム職人がいることを願う..
https://github.com/dna5rm/dna5rm/blob/master/.config/lsd/colors.yaml

difftastic

image.png

difftastic とは,Rustで書かれた「diffの完全上位互換」ツールである.diffコマンドには行ごとにしか比較できないという弱点がある.difftasticはそこに注目し,言語のsyntaxを考慮して差分を表示する
残念ながら設定できる項目はまだ多くないが,alt cliツールという趣旨のもと紹介させていただく.

installation

dependencies

  • cargo

mac

$ brew install difftastic

windows

linux

$ cargo install --locked difftastic

チュートリアル

gitでコンフリクトを起こしたファイルにdifft <file>2つのファイルをdifft <fileA> <fileB>,2つの似通ったフォルダにdifft dirA/ dirB/してみよう.

外部ツールとの連携

difftasticはdiffの強化版であるから,git diffの差分表示ツールとして使用すると強力なのは容易に推察できるだろう.

$ git config --global -e

でgitのconfigureを開き,以下を追記しよう.

[diff]
 tool = difftastic
[difftool "difftastic"]
 cmd = difft "$LOCAL" "$REMOTE"
[difftool]
 prompt = false

これでgit diftoolでdifftasticが開く.

bat

image.png

bat とは,Rustで書かれた「catの人にやさしい版」ツールである.catコマンドはお手軽に扱えるが,シンタックスハイライトもないため若干見づらい.長いファイルだと結局lessに頼ることにもなる.これらの問題点を解決するのがbatだ.

dependencies

  • cargo
  • [windows] Visual C++ Redistributable windows
  • [windows] Chocolatey

installation

linux/macOS

$ <yarn/apt/apk/pacman/yarn/etc/etc.,> install bat

※aptやapk, pacman, yarnなどたくさんのパッケージマネージャから導入できるが,batコマンドは名前が衝突しやすいためbatcatという名前に変更されることがある.困ったら,batcatでインストールされてしまう問題は,エイリアスを張って解決しよう.
※,cargo install推奨しないcargo installはLinux OSバージョンの相性に関係なくインストールする.一部のコマンドが動かなくなるのだ.

windows

choco install bat

wingetでもbatはインストールすることができるが,lessが存在しないのでページャー機能が使えない.これでbatの機能がほとんど使えないので,lessが存在するchocolatelyからインストールしよう.Git for windowsを入れるなどして,lessが存在する場合はwinget install batでも問題はない.

チュートリアル

色んなファイルをbatしてみよう.

表示を調整しよう

image.png

batコマンドは,設定に依ってかなり使用感が変わる.例えばファイル名を表示しなかったり,ページャーを使用したり…
まずは,batコマンドのデフォルト設定をいじることから始めよう.

$ bat --generate-config-file

をすることで,親切なことにコンフィグファイルを生成することができる.linuxでは~/.config/bat/config windowsでは %appdata%\bat\configに生成されるだろう.

生成されたコンフィグファイルを開くと,すべてコメントアウトされているのに気づくだろう.このコマンドでは,必要な部分を設定すれば残りはビルトイン設定が反映される.設定項目は,コマンドライン引数を指定すればよい.

--style="numbers,changes,grid,snip,header"を指定することで,上記の画像と同じ見た目にできる.

カラーテーマをいじってみよう

image.png

batはユーザが非常に多く,またthemeが多く公開されている.今回は自分でカラーテーマを作成するのではなく,カラーテーマを導入することを目的としてみる.

今回インストールするカラーテーマは筆者が大好きなcatppucinからお借りさせていただく.batのテーマは,windowsは%appdata%\bat\theme\,linuxは~/.config/bat/theme/であるから,Catppuccin-macchiato.tmThemeを配置しよう.

$ bat cache --build

を実行して,キャッシュをbatに組み込もう.
configファイルのthemeにCatppuccin-macchiatoを指定すれば,デフォルトテーマの設定ができる.

あとがき

lsdはlsを人が見やすい形に成形することができる.difftasticは,diffを文法ベースで差分を解析することができる.batはファイルを人が見やすい形にハイライトすることができる.これらのツールは必ずないとこまるツール群ではないが,導入することで圧倒的に作業効率を上げてくれるものだ.これらを組み合わせることで,「エディタを開くほどでもないけど...」「わざわざエクスプローラを開くのはめんどうだが...」「結局何が違うのかは,本文を読まなければいけない」など,タスクをこなすには過剰なソフトウェアを起動することを減らせるだろう.

最近のトレンドとして複雑なツールをRust製TUIに置き換えるというものがある.今回は「結局シェルって不便じゃないか」という問題の解決の一つとして「今までよりも強力なシェルツール」を紹介した.読者の皆様方も良ければ環境ガチャガチャの喜びを楽しんでほしい.

ここまでお読み頂きありがとうございました。

references

https://github.com/sharkdp/bat/tree/master
https://difftastic.wilfred.me.uk/
https://github.com/lsd-rs/lsd/

4
4
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
4
4