Sublime Text 4で追加された設定など

昨日 (2021/05/21)、Sublime TextのメジャーアップデートであるSublime Text 4がリリースされました。

www.sublimetext.com forest.watch.impress.co.jp

デフォルトのカラースキームがMonokaiからMarianaに変わったり、Open GLによるGPUアクセラレーションが有効になったりしましたが、 他にもちょっとした設定項目の追加などがあったため、便利だと感じたものを紹介します。

目次

互換性

Sublime Text 4は、メジャーアップデートではあるものの設定ファイルやパッケージなどの互換性は維持されています。 私のインストールしている以下のようなパッケージは特に問題なく動作しています。

{
    "bootstrapped": true,
    "in_process_packages":
    [
    ],
    "installed_packages":
    [
        "A File Icon",
        "AdvancedNewFile",
        "All Autocomplete",
        "BracketHighlighter",
        "Case Conversion",
        "Clang Format",
        "CMake",
        "DoxyDoxygen",
        "EditorConfig",
        "FindKeyConflicts",
        "Git",
        "GitGutter",
        "Increment Decrement",
        "Increment Selection",
        "LSP",
        "Origami",
        "Package Control",
        "PackageResourceViewer",
        "ProjectManager",
        "SideBarEnhancements",
        "Smart Delete",
        "Sublime Files",
        "SublimeGHQ",
        "SyncedSideBar",
        "TodoReview",
        "TOML"
    ],
    "repositories":
    [
        "https://github.com/Ryooooooga/SublimeGHQ"
    ],
}

また、macOSの場合設定ファイルの保存先は ~/Library/Application Support/Sublime Text 3/ から ~/Library/Application Support/Sublime Text/ に変更されました。 ただし、~/Library/Application Support/Sublime Text/ が存在しない場合は ~/Library/Application Support/Sublime Text 3/ 以下の設定が読み込まれるため、 移行にあたっての対応は特に必要ありません。

オートコンプリートの強化

オートコンプリート機能の刷新に伴ってオートコンプリートに関する設定項目が複数追加されました。

f:id:Ryooooooga:20210522134143p:plain
Sublime Text 4の補完候補リスト

使用感としてはSublime Text 3とほぼ変わりがないものの、補完候補の種類 (スニペット、関数、型など) に対応したアイコンが表示されるようになり、単純にわかりやすくなりました。 また、補完候補の定義へのジャンプなどが可能になりました。

f:id:Ryooooooga:20210522135214p:plain
Sublime Text 3の補完候補リスト

便利な設定の追加

Sublime Text 4になり、いくつか設定項目が追加されました。 うち、特に便利だと感じたものを紹介します。

draw_white_space のカスタマイズ性の向上

draw_white_space は空白文字の可視性を設定するための項目です。

draw_white_space 自体は Sublime Text 3から存在していましたが、以下の3種類の設定のいずれかしか指定できませんでした。

  • "none": 空白文字を表示しない
  • "all": すべての空白文字を常に可視化する
  • "selection": 選択範囲のみ空白文字を可視化する

Sublime Text 4 ではより複雑な可視性の制御が行えるようになりました。

Sublime Text 4のデフォルトのdraw_white_space

  // Controls when white space is drawn. Any of the following options may be
  // combined:
  // - "selection": Draw white space under the current selection.
  // - "leading": Draw any white space between the beginning of a line and the
  //              first character.
  // - "enclosed": Draw white space enclosed by other characters.
  // - "trailing": Draw white space following the last character on a line.
  // - "isolated": Draw white space on lines containing no other characters.
  // - "all": All of the above, ie. always draw white space.
  //
  // These options may be further refined by appending any of the following
  // separated by an underscore:
  // - "none": Don't draw this kind of white space.
  // - "tabs": Only draw tabs here.
  // - "spaces": Only draw spaces here.
  // - "mixed": Only draw white space that does not match the indentation
  //            style. For example if "translate_tabs_to_spaces" is true only
  //            draw tabs.
  // - "mixed_tabs": Like "mixed" but only draw tabs.
  // - "mixed_spaces": Like "mixed" but only draw spaces.
  // - "all": Draw both tabs and spaces. This is the default.
  //
  // Note that options are applied in sequence. So a later option may override
  // an earlier one.
  //
  // Examples:
  // - ["selection", "trailing", "isolated"]:
  //     Draw white space at the end of any lines and under the selection.
  //
  // - ["all_tabs", "selection"]:
  //     Draw tabs anywhere and any white space under the selection.
  //
  // - ["all_mixed"]:
  //     Draw any white space that does not match the indentation style.
  //
  // - ["leading_mixed", "isolated_mixed"]:
  //     Draw any indentation that does not match the indentation style.
  //
  // - ["selection_mixed_tabs"]:
  //     Draw only tabs under the selection and only if the indentation style
  //     is spaces.
  //
  // - ["all_tabs", "selection"]:
  //     Draw all tabs and any white space under the selection.
  //
  // - ["all", "selection_none"]:
  //     Inverse of the default. Draw white space everywhere except under the
  //     selection.
  "draw_white_space": ["selection"],

例えば、私の場合は以下のように設定しています。

   "draw_white_space": [
        "all_tabs",  // すべてのタブ文字を表示する
        "selection", // 選択範囲の空白文字を可視化する
        "trailing",  // 行末の空白文字を可視化する
    ],

ただし、設定の記述順によって表示が変わったり、そもそもの指定方法がわかりにくかったりとなかなかに難解です。(ちょっとだめなところがSublime Textっぽくてかわいいね)

"ignored_snippets" の追加

"ignored_snippets"Sublime Text 4から追加された、スニペットを無効化するための項目です。

Sublime Text 4のignored_snippets

   // A list of wildcard patterns specifying which snippet files to ignore.
    // For example, to ignore all the default C++ snippets, set this to
    // ["C++/*"]
    "ignored_snippets": [],

Sublime Text 3でデフォルトで組み込まれているパッケージ (C++パッケージなど) のスニペットを無効化したい場合、 PackageResourceViewer などを使ってデフォルトスニペットファイルを抽出し、 それらのスニペットファイルの中身を削除する などの作業が必要でした。

Sublime Text 4では、"ignored_snippets"スニペットのファイル名を追加することで無効化できるようになりました。(なにげにこれが一番うれしかった)

   // デフォルトのC++スニペットをすべて無効化する
    "ignored_snippets": [
        "C++/*",
    ],

"hardware_acceleration" の追加

"hardware_acceleration"GPUによるハードウェアアクセラレーションの有効化に関する設定項目です。 デフォルトではmacOSでのみOpenGLによるハードウェアアクセラレーションが有効になっています。 

Sublime Text 4のhardware_acceleration

   // Enables hardware accelerated rendering. This moves rendering to your GPU,
    // allowing for faster rendering at higher resolutions. Changing this
    // setting requires an application restart to take effect.
    // - "none": Performs CPU rendering.
    // - "opengl": Uses OpenGL for rendering. Minimum required version is 4.1
    //
    // On Mac, this value is overridden in the platform specific settings.
    "hardware_acceleration": "none",

"relative_line_numbers" の追加

"relative_line_numbers"true に設定すると、行番号が相対表示になります。 (Vimset relativenumber のような感じ)

Sublime Text 4のrelative_line_numbers

   // relative_line_numbers will draw each line number as the distance from
    // the current line. Useful in conjunction with Vintage.
    "relative_line_numbers": false,

ST4のbeta版を使っていた身としては正式リリースは嬉しい限りですが、いくらなんでも遅すぎませんかね? 日本でSublime Text使ってる人はもはや私しかおらないぞ。 

Dockerでカスタムsubcommandをあれする

Gitでは git-foo のような名前のスクリプトファイルを PATH の通っている位置に置いておくと、 git foo とするだけで呼び出せる便利な仕組みがあります。

本記事の趣旨はDockerでもそんな感じのことをしたいよね。というあれです。

実装

で、以下のような関数を .zshrc なりに書いて置くとGitのような感じでsubcommandを探索してくれます。

docker() {
    if [ "$#" -eq 0 ] || ! command -v "docker-$1" > /dev/null; then
        command docker "$@"
    elif (( ${+aliases[docker-$1]} )); then
        eval "${aliases[docker-$1]} ${(q)@:2}"
    else
        "docker-$1" "${@:2}"
    fi
}

この関数 docker を用いて docker foo のようにサブコマンドを呼び出した場合、

  • docker-foo」のようなコマンドやエイリアスが存在していない場合は生のdocker コマンドに引数を渡す
  • docker-foo というエイリアスが存在していれば docker-foo に残りの引数を渡す1
  • docker-foo というスクリプトか関数が存在していれば docker-foo に残りの引数を渡す

というような感じであれしてくれます。

自分は以下のようなエイリアスを使っています。

# docker run のエイリアス 
alias docker-ri='command docker run -it'
alias docker-rrm='command docker run --rm'
alias docker-rrmi='command docker run --rm -it'

# exitedなプロセスを全部 rm する
docker-clean() {
    command docker ps -aqf status=exited | xargs -r docker rm --
}
# タグ付けされていないイメージを全部 rmi する
docker-cleani() {
    command docker images -qf dangling=true | xargs -r docker rmi --
}

# 引数なしで docker rm すると削除するプロセスを fzf で選択できる
docker-rm() {
    if [ "$#" -eq 0 ]; then
        command docker ps -a | fzf --exit-0 --multi --header-lines=1 | awk '{ print $1 }' | xargs -r docker rm --
    else
        command docker rm "$@"
    fi
}

# 引数なしで docker rmi すると削除するイメージを fzf で選択できる
docker-rmi() {
    if [ "$#" -eq 0 ]; then
        command docker images | fzf --exit-0 --multi --header-lines=1 | awk '{ print $3 }' | xargs -r docker rmi --
    else
        command docker rmi "$@"
    fi
}

余談

それでいいのか?


  1. git はシェルエイリアスの探索はしてくれませんが、git config alias.foo の代替みたいな気持ちです

テンプレートから新規ファイルを作成するCLIツール zouch を作った

例えば新しいプロジェクトを作成するとき、何かと新しいファイルを作成する必要があります。

README.md, LICENSE, .editorconfig, あるいはC/C++ならCMakeLists.txtやmain.cppなどをプロジェクトに含める必要があるでしょうが、 そのうちいくつかは毎度似たようなファイルを「お約束」として用意することでしょう。

私の場合はそれらを既存のプロジェクトからコピーしてきたり、もしくは touch で空のファイルを作成したあとにVSCodeSublime Textといったエディタのスニペット機能を用いて中身を入力することが多いです。

しかし、touch して〜、エディタで開いて〜、というのも結構めんどくさいので touch した時点でファイルの中身も自動生成してくれればなにかと便利そうです。

そこで、zouchというCLIツールを作成しました。

github.com

これはなに

zouchを使用すると、予め登録しておいたテンプレートからファイルを作成できます。

$ cat LICENSE.md
cat: LICENSE.md: No such file or directory

$ zouch LICENSE.md

$ cat LICENSE.md
# MIT License (MIT)

Copyright (c) 2021 Ryooooooga

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
...

上のようなMITライセンスのテキストファイルは、~/.config/zouch/templates に配置された以下のようなテンプレートから作成されます。

# MIT License (MIT)

Copyright (c) {{Now.Year}} {{Shell `git config user.name`}}

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
...

zouchではGo言語のテンプレートエンジンである text/template の記法を用いて出力内容をある程度動的に変更できるようになっています。 上の例で言うと {{ ... }} に囲まれている部分 (西暦N年、ユーザ名) が出力時にはいい感じに展開されているのがわかると思います。

また、touch 本来の機能であるタイムスタンプの更新もできるようになっています。1

テンプレートファイルの探索

zouchでは /path/to/foo.txt というファイルを生成する際にまず ~/.config/zouch/templates/foo.txt というファイルを探し、 これが存在していればそれをテンプレートファイルとして用います。

foo.txt~/.config/zouch/templates/ 以下に存在しないときは、代わりに _.txt という名前のファイルを探し、これを代わりにテンプレートファイルとして用います。

これによって、"特定の拡張子のファイルはすべて同じテンプレートから生成したい" という要求を解決します。 以下に例として、.goファイルのテンプレートを示します。

{{ if HasSuffix .Filename "_test.go" -}}
package {{.Filename | Abs | Dir | Base}}_test

import (
    "testing"
)

func Test{{RegexReplaceAll .Filename `_test\.go$` "" | Base | UpperCamelCase}}(t *testing.T) {
}
{{ else -}}
package {{.Filename | Abs | Dir | Base}}
{{ end -}}

_.go の例

このテンプレートは、foo/bar.go というファイルを生成しようとした場合は

package foo

というファイルを、foo/bar_test.go というファイルを生成しようとした場合は

package foo_test

import (
    "testing"
)

func TestBar(t *testing.T) {
}

というファイルをそれぞれ出力します。

インストール方法

  • go get
$ go get github.com/Ryooooooga/zouch
  • zinit (プリビルトバイナリのダウンロード)
# ~/.zshrc
zinit ice lucid wait"0" as"program" from"gh-r" \
    pick"zouch*/zouch"
zinit light 'Ryooooooga/zouch'

類似のツール

類似のツールに touch-alttouch_erb があります。

touch-alt

github.com

qiita.com

touch-alt は Node.js 製のCLIツールです。 テンプレートエンジンなどは使用せず、単にテンプレートファイルをコピーしてくるだけのシンプルなツールです。

touch_erb

github.com

touch_erb は Ruby 製のCLIツールです。 ERBを採用することで柔軟なファイルの生成が可能になっています。

zouchはこのtouch_erbから着想を得て (というか丸パクし) 作成しました。

touch_erbを用いず、わざわざ自作したのは以下のような理由のためです。

  • dotfilesRubyのインストールを前提としていない
  • 宗教的な問題でグローバルに gem install したくない2

zouch の作成にあたって

zouchの実装言語にはGoを選択しました。 以下のような言語も選択肢には入っていましたが、シングルバイナリにコンパイルできること、 テンプレートエンジンの言語標準として text/template ライブラリが存在していることが選定の決め手となりました。3

  • Shellスクリプト: 処理系のインストールが不要 / 書くのが辛い
  • Perl: 処理系のインストールが不要 / わからない
  • Node.js: dotfiles内でインストールしている / npm i -gしたくない
  • Python: dotfiles内でインストールしている / pip install したくない, 書きたくない
  • C++ (+ Luaなどの組み込みスクリプト): シングルバイナリにコンパイルできる / 実装コストが重い
  • Rust: シングルバイナリにコンパイルできる / テンプレートエンジンとして標準的なものが存在しない

一方、テンプレート内で任意のRubyスクリプトを書けるERBとは違い、 Goのtext/templateの表現力は極めて限定的です。 例えば、テンプレート内で使用できる関数は (素朴な実装に於いては) コンパイル時に登録されたものに限られます。

そこで、Shell関数を通じて任意のシェルスクリプトを実行できるようにすることで表現力の低さを補うことにしました。


テストを書きやすいようにパッケージの分割を工夫したりはしたものの、この手のCLIツールはテストを書くのがすごく面倒です。 あとドキュメントを書くのも面倒。

それからGoの time.Time.Format() の仕様を考えた人は早く謝罪の言葉を考えたほうがいい。


  1. touchに付いているオプションなどは実装していないため完全な上位互換として用いることはできませんが、大雑把な方なら alias touch=zouch してもある程度大丈夫だと思います。多分。

  2. pip installもしたくない。npm install -g もできればしたくない。

  3. 個人的にGo言語は好きでない。 (C言語を書いている気持ちになるため)

fzf+pmyでzshの補完をカスタマイズする

最近 relastle/pmy というツールにハマっています。

Zshの補完機能の欠点

zshの補完機能は強力ですが、カスタマイズ性や拡張の容易さに難があります。

また、やろうとおもえば補完関数内でfzfなどのFuzzy Finderを用いてインタラクティブな補完を実現できますが、fzfの--multiオプションなどを用いた複数結果の展開などはできません。

デフォルトの補完機能 (ZLEのexpand-or-complete)を上書きするような形でそれらも実現はできますが、やはり記述の複雑さや保守性の面からつらいものがあります。

そこで、pmyというCLIツールとfzfを組み合わせてインタラクティブな補完を実現しました。 利用時の様子は上のツイートのとおりです。

fzf

fzfはGo製のFuzzy Finderです。

github.com

日本では同じくGo製のFuzzy Finderであるpecoの方が知名度が高い印象がありますが、preview windowはpecoにはない魅力です。

f:id:Ryooooooga:20201231130448p:plain
fzfのpreview window

preview windowは、任意のコマンドなどを用いて検索候補のプレビューを表示できる機能です。 上の図ではbatを用いてシンタックスハイライト付きでファイルの中身を表示しています。他にもlstreeのようなコマンドを使ってディレクトリの構造を表示する、あるいはgit showでコミットの情報を表示するなど、用途の幅が広い便利な機能です。

私の場合は以下のような用途にfzfを用いていました。

  1. historyを使ったコマンドヒストリーの検索
  2. chpwd_recent_dirsを使ったディレクトリ移動履歴の検索
  3. ghqを使ったリポジトリ間の移動
  4. テキストエディタを開く際のファイルの選択
  5. docker rmdocker rmiの際に削除するイメージの選択

1 ~ 3 はFuzzy Finderの利用例で頻繁に挙げられる用途なので特筆すべきことはありません。

4 に関しては以下のような$EDITOR (私の場合はnvim) のラッパー関数 e を用意していました。

e() {
    if [ $# -eq 0 ]; then
        local selected="$(fd --hidden --color=always --exclude='.git' --type=f  | fzf --exit-0 --multi --preview="fzf-preview-file '{}'" --preview-window="right:60%")"
        [ -n "$selected" ] && "$EDITOR" -- ${(f)selected}
    else
        command "$EDITOR" "$@"
    fi
}

これは、eに引数が指定されていた場合は通常通りに $EDITOR を起動し、引数なしで呼び出された場合にはカレントディレクトリ以下のファイルから fzf で選択したものを $EDITOR の引数に与えるものです (かなり便利)。

これまでの不満点

上のような fzf の活用は、実際に便利で重宝していたのですが、若干の物足りなさを感じていました。 具体的には以下のような点です。

  • e で選択したファイルがコマンドヒストリーに記録されない

    上の関数ではどのようなファイルを選択してもコマンドヒストリーに e しか残りません。 そのため、以前に開いたファイルを再び開こうと思った場合にも再度検索を行わなければならず、煩わしさを感じていました。

  • git switch などの既存のコマンドの補完にfzfを用いたい

    Gitなどの既存のコマンドやそのサブコマンドの補完にfzfを用いたい場合、逐一ラッパースクリプトを用意しなければならず面倒でした。

余談

fzfには補完用のスクリプトが用意されており、これを使用することでfzfを使った補完が可能になっていました。

参考: https://github.com/junegunn/fzf#fuzzy-completion-for-bash-and-zsh

また、この機構を利用してGitなどの補完を実現したプロジェクトに chitoku-k/fzf-zsh-completions があります。

github.com

今回、これらのような既存のものを利用しなかったのは以下の理由のためです。

  • 自分用の環境に合わせてカスタマイズするのが面倒
  • 補完のトリガーである**<TAB>というシーケンスに慣れない

pmy

というわけで本題です。

pmyはFuzzy Finderを用いたzshの補完を実現するためのCLIツールです。

github.com qiita.com

YAML (もしくはJSON) で設定ファイルを書くことにより、冒頭で示したようなfuzzyな検索と補完が可能になります。

インストール方法

  • go get を用いたビルド方法
$ go get -u github.com/relastle/pmy
$ eval "$(pmy init)"
  • zinit を用いたプリビルドバイナリのダウンロード
zinit ice lucid wait"0" as"program" from"gh-r" \
    pick"pmy*/pmy" \
    atload'eval "$(pmy init)"'
zinit light 'relastle/pmy'

設定ファイルの編集

pmyは、デフォルトでは ~/.pmy/rules 以下に配置された設定ファイルを参照します。 例えば、冒頭のツイートのような補完は下の設定で再現できます。

# ~/.pmy/rules/_.yaml
- description: editor
  regexp-left: ^\s*(?P<cmd>(nvim|vim|vi))\s+(?P<args>\S+\s+)*)(?P<query>\S*)$
  cmd-groups:
    - stmt: fd --color=always --hidden --type=f
      after: paste -s -d ' ' -
  fuzzy-finder-cmd: fzf --multi --preview="bat {}" --query=<query>
  buffer-left: '<cmd> <args>'
  buffer-right: '[]'

f:id:Ryooooooga:20201231173125p:plain
pmyによるファイル名補完の例

上の場合、ファイルパスやその一部を雑に入力しただけで候補に出現するため、通常のzsh補完よりも効率的に目的のファイルにたどり着けます。

他にも以下のような設定でpmyを運用しています。

https://github.com/Ryooooooga/dotfiles/tree/main/config/pmy/rules

f:id:Ryooooooga:20201231173324p:plain
pmyによるGitサブコマンド補完の例

設定ファイルの参照ディレクトリなどの変更

pmy はデフォルトでは ~/.pmy 以下を作業ディレクトリとして用います。 しかし、私はホームディレクトリが雑多なdotfilesで汚れることをあまり好ましく思っていません。

幸いにも、pmyは環境変数によって作業ディレクトリを変えられるため、XDG風のファイルの配置に変更しました。 また、補完のトリガーになるキー(デフォルトではCtrl+Space)も変えられます。

# 補完のトリガーを変更 (Ctrl+P)
export PMY_TRIGGER_KEY="^P"

# ルールファイルの参照先を変更
export PMY_RULE_PATH="$XDG_CONFIG_HOME/pmy/rules"
export PMY_SNIPPET_PATH="$XDG_CONFIG_HOME/pmy/snippets"
# ログファイルの出力先を変更
export PMY_LOG_PATH="$XDG_CACHE_HOME/pmy/log.txt"

eval "$(pmy init)"

pmyの利点

pmyを利用することには以下のような利点があります。

  • コマンドやサブコマンドなどのコンテキストごとに補完の候補を柔軟に変えられる
  • YAMLなのでShellスクリプトに比べカスタマイズが容易
  • 補完結果がコマンドヒストリーに残る

pmyの欠点

一方で、pmyもまた万能ではありません。 しばらく利用してみて感じた欠点を以下に挙げます。

  • ルールのマッチングのための正規表現を書くのがつらい
    • 空白や引用符などを考慮した正規表現を書こうとすると大変
    • オプションやフラグごとの補完候補の変更など、あまり複雑なことをしようとすると正規表現が爆発する
  • ルールのマッチングは上から順に判定されるため、設定の記述順序が重要になる
  • エスケープシーケンス周りの動作が怪しい
    • PRを投げて幾分かはマシになった

pmyはかなり独特でおもしろいツールなので、fzfがすきなzshユーザの方は一回試してみるといいんじゃないでしょうか。

Sublime Text 3からghqで管理されたリポジトリを開くプラグインを書いた

Sublime Text 3 から x-motemen/ghq で管理されたリポジトリを開くプラグインを書きました。

github.com

なぜいま Sublime Text 3

高機能テキストエディタ Sublime Text が Atom と覇権を競い合ったのも今は昔、 ご存知の通りいまやGUIテキストエディタ界は Visual Studio Code の一強状態です。

その勢いたるや凄まじく、[VisualStudio なんとかかんとか][検索] してもVSではなくVSCodeの情報がヒットする始末。

かたや、

  • 有料で
  • クローズドソースで
  • 日本語入力があやしく
  • デフォルトの機能がVSCodeに劣っている

Sublime Text 3の人気はもはや風前の灯火、Sublimerは地下深くに隠れ潜み、諦観とともにその再起を祈っている昨今です。

実際私も2年ほど前に、長らく使っていたSublime Text 3 から VSCode に宗旨変えをしました。

しかしながら、ネイティブアプリ特有の素早い起動や、サクサクとした軽快な動作はElectron製エディタにはない魅力です。 というわけでメインのエディタには VSCode を使いつつ、軽い用途や大きいファイルの取り扱いには Sublime Text 3 といった風に使い分けていくことにしました。

ghqとは

ghq はGoで書かれたリポジトリ管理のためのCLIツールです。

github.com

プラグイン

VSCode の場合には vscode-ghq 拡張機能によって、簡単にワークスペース間の移動が行えるのですが、 Sublime Text 3 にはそのようなプラグインが存在していません。

今回はプラグインを自作することで、vscode-ghqライクなワークスペース間の移動を可能にしました。

f:id:Ryooooooga:20200816143359p:plain

インストール方法

ghqのインストール方法

プラグインの動作にはghqが必要になります。(ghqのインストール方法)

プラグインのインストール方法

  1. Package Control をインストールする
  2. コマンドパレットから Package Control: Add Repository を選択し、https://github.com/Ryooooooga/SublimeGHQ と入力する
  3. コマンドパレットから Package Control: Install Package を選択し、SublimeGHQ をインストールする

操作方法

コマンドパレットから GHQ: Open Repository... を選択するとすべての ghq root からリポジトリの一覧が表示されます。

キーバインドを登録しておけばより便利です。

// Default (<OS>).sublime-keymap
[
    ...

    // キーバインドの設定例
    // Ctrl + Alt + P
    { "keys": ["ctrl+alt+p"], "command": "ghq_open_repository" }
]

x64セルフホスティングCコンパイラを書いた

前回:

ryooooooga.hateblo.jp

はじめに

セルフホスト(自分自身をビルド)できるCコンパイラmoccを書きました。

github.com

前回はバックエンドをLLVMに頼っていたため、今回はx86_64向けのアセンブリを吐くようにしました。 基本的な設計はほぼ前回と同じですが、コードは全て新しく書き直しました。

例によって@rui314さんの低レイヤを知りたい人のためのCコンパイラ作成入門を参考にしています。

工夫した点

基本的な点は、前回とほぼ同じなので上記の記事を参照してください。

前回に比べ、拡張性や規格準拠性を意識して構文木の構造を一部変更しましたが、 結局セルフホストに必要な最小限の機能のみを実装したため、使える言語機能は下記を除けば前回のものと大差ありません。

新しく使えるようにした機能:

  • 列挙体
  • 変数の宣言時初期化
  • 複数の変数の同時宣言

GitHub Actionsを用いたテストの自動化

前回は面倒がっていたテストの自動化を行いました。

GitHub Actionsはお手軽でいいですね。

まとめ

前回のCコンパイラはバックエンドをLLVMに頼っていたため、 x86_64向けのアセンブリを吐くCコンパイラを作成しました。

出力コードの効率などは度外視していたためひどく非効率的なコードが出力されますが、 バックエンドを含め実装することができました。

出力コードの最適化は今後の課題です。

Almel v1.1.3 をリリースした

ryooooooga.hateblo.jp

自作shellテーマ、Almel を更新しました。

v1.0.xとの変更点は以下の通りです。

  • コードを全部書き直した
  • コンフィグファイルの構造を変えた
  • fish, bashに対応した
  • 現在時刻を表示する time セグメントを追加
  • 直前に実行されたコマンドの実行時間を表示する duration セグメントの追加
  • シェルごとに異なる内容を表示できる shell セグメントを追加

コンフィグファイル (~/.config/almel/almel.yaml) に互換性がないため、エラーが発生する場合には一度コンフィグファイルを削除してください。

コードの全リライトの副作用として若干実行速度がはやくなりました。

また、GitHub Actionsを使って x86_64 環境向けのバイナリ (Windows, mac, Linux) を自動的に用意するようにしました。

v1.1.3 のデフォルトの見た目は次のようになります。

f:id:Ryooooooga:20191107092344p:plain
デフォルトの見た目

全部盛りのため結構うるさいです。 コンフィグファイルの segments 項目で表示するセグメントとその表示順を変更できます。

以下に自分用の設定を晒します。

os:
  linux:
    background: 33
  mac:
    background: 33
  windows:
    background: 33

git_user:
  background: 75

time:
  format: "\uf017 %H:%M:%S"

duration:
  background: 242

segments:
  - - os
    - user
    - directory
    - git_repo
    - git_user
  - - duration
    - status

f:id:Ryooooooga:20191107092355p:plain
上記設定時の見た目