hotoolong's blog

プログラムのことやエンジニアリングに関することを記事にしています。

Krisp を使ってみた

リモートでの会議が多くなり、Google Meets, Zoom, Discord を使う機会が徐々に増えてきました。 リモートで会議をしながらタイピングをしているケースもあり、 相手のキーボードの打刻音が煩わしく感じたり、 自分の打刻音が相手にどれくらい不快にさせるのかが気になったりしていました。

そこで打刻音などをフィルターしてくれるツールが無いかと調べていたらKrispがありました。

krisp.ai

マイクとスピーカーのノイズのON/OFFを設定することができます。

2週間ほど使っていますが、かなり快適に使えています。 こちらの打刻音もそこまで大きな音にならずに聞こえてるようです。

無料で利用することができるのですが、 1週間120分の制約があり少し試す程度であればいいと思います。

以下のURLから登録すると1ヶ月無料で利用することができます。 https://ref.krisp.ai/u/u098838e52

打ち合わせでタイピングしてもとても快適に参加することができます。 よかったら試してみてください。

よい、リモートライフを!

vimのプラグインマネージャをdein.vimに変更しようとして読み込めないプラグインがある?

イントロ

現在vim-plugを使っています。 プラグインが増えてきて遅延させてロードを対応したこともあったんですけど、 設定が必要なプラグインの場合ロード前に設定がエラーなるようなケースもあり、 deinに乗り換えることにしました。

github.com

以前もdeinを使っていたのですが、vim-plugに移行して、戻ろうとしています。 以前はtomlファイルで管理していなかったのですが、非同期で読み込みませるため、tomlで管理することにしました。

dein.vim の設定

dein.vim は 非同期にプラグインの設定を読み込むことができるのでドキュメントを読みながら設定をしていきました。 以前使っていたときにはtomlファイルで管理していなかったのですが、今回はtomlファイルで管理してみようかと思います。

hookの複数設定

hookを複数設定することはできそうです。 hook_add と hook_source を設定して遅延して読み込みたいものは後で読み込ませることは出来ました。 同じhook(例えば hook_addとhook_add)を設定すると後勝ちになります。 誤って設定して場合には気をつける必要があります。

depends の振る舞い

ドキュメントを確認すると以下のようになっています。

depends      (List or String)
        Specify a list of plugins a plugin depends on.
        List items are '{plugin-name}'.
        Those specified in the list are NOT installed automatically.
        Note: The loading order is not guaranteed in non lazy plugins.

注:レイジーでないプラグインでは、ロード順序は保証されません。 とあります。

tomlファイルをlazy 0と1の2ファイルを用意しました。

私は使わなかったのですが、
ドキュメントを読んでいるとlazyはNumberで設定できるので2以上でも設定できそうです。

以下が用意した設定です。

  call dein#load_toml('dein.toml',      {'lazy': 0})
  call dein#load_toml('dein_lazy.toml', {'lazy': 1})

呼び出すプラグインは dein.tomlにA,Bというプラグインを 呼び出す設定をして hook_add で コメントを出力しました。 上から順番に呼ばれることが予想されるのでB,Aの順にプラグインを記載しています。 同じくdein_lazy.tomlにC,Dというプラグインを呼び出す設定をしてコメントを出力しています。 こちらも同様にD,Cの順に記載しいます。

BのdependsにAを DのdependsにCを設定しました。

この状態でどのような順序で呼ばれるのかを確認してみました。

B hook_add
A hook_add
D hook_add
C hook_add

という順で呼び出されました。 記述順に呼び出されています。 hook_addはdependsに影響しないようです。

AからDのプラグインにhook_sourceを追加してみました。

B hook_add
A hook_add
D hook_add
C hook_add
A hook_source
B hook_source

lazyでないファイルのA,Bはhook_sourceが呼び出されていますが、 lazyなファイルのC,Dは呼び出されませんでした。

ドキュメントを確認すると

dein#end() の後、または VimEnter で autoloadされるようです。

非遅延型プラグインの hook_source は使用できません。
必要に応じてdein#call_hook() で呼び出す必要があります。

ということでした。

dein#call_hook('source')

を明示的にconfigに記載することで呼び出すことができます。 ドキュメントを見ると、 on_eventがあり

on_event (String) or (List)
        dein will call |dein#source()| on the events.

設定することでsourceが呼べるそうです。

先程 呼びだされなかったCとDに

on_event = 'CursorMoved'

を設定してカーソルを移動してみます。

B hook_add
A hook_add
D hook_add
C hook_add
A hook_source
B hook_source
A hook_source
B hook_source
C hook_source
D hook_source

何故かA,Bのhook_sourceが2回呼ばれています。
初回のA,Bのhook_sourceは何も設定しないでdein#end()の後に呼び出されるもので、
その後ろのA,B,C,Dのhook_sourceはカーソル移動させたときによばれるようです。
設定されてるhook_sourceは何度も呼ばれるかもしれないです。
とりあえずこれで設定が呼び出されることはわかりました。

on_ft の振る舞い

次にon_ftです。 ドキュメントを見てみましょう。

on_ft        (List) or (String)
        If it is matched to 'filetype', dein will call
        |dein#source()|.

ファイルタイプを設定することで呼び出されるようです。
先程のA,B,C,Dにon_ftを設定してみます。

今回はrubyを設定してみます。

一旦jsファイルを開いてみます。

B hook_add
A hook_add
D hook_add
C hook_add
A hook_source
B hook_source
A hook_source
B hook_source
C hook_source
D hook_source

すべてのhookが呼び出されました。

rubyファイルを呼び出してみます。

A hook_add
B hook_add
C hook_add
D hook_add

予想では逆の挙動になるかと思ったのですが、
rubyファイルでhook_sourceが呼ばれなくなりました。
lazyではないA,Bのhook_sourceも呼ばれなくなりました。
lazy側のC,Dのon_eventとバッティングしてるのか気になったので一旦外して
再度rubyファイルを確認してみました。

B hook_add
A hook_add
D hook_add
C hook_add
A hook_source
B hook_source

A,Bのhook_sourceは呼ばれるようになりました。 jsファイルも確認してみたのですが同様の結果になりました。
on_ft と on_event で挙動がおかしくなるのかもしれないです。

on_ftを設定している場合はhook_addに設定を記載するほうがいいかもしれないです。

on_idle の振る舞い

先程のon_eventを設定していましたが、 on_idleを設定するのが便利そうです。

on_idle      (Number)
        If set to non-zero, dein will call |dein#source()| on
        |FocusLost| or |CursorHold| autocmd.
        Note: This is deprecated option.  You should use
        |dein-options-on_event| instead.

on_idle を設定すると FocusLost CursorHold のイベントで dein#source() が 呼び出されるようです。 イベントを設定するよりもこのオプションでカバーできそうです。

上手くいかないこと

いろいろ試しながらわかったこともはあるのですが、 スニペットが上手く動かなくなってしましました。 調べてみたのですが、よくわからない状態です。

lazyでのhook_source

lazyに high-moctane/asyncomplete-nextword.vimリポジトリを設定して

[[plugins]]
repo = 'high-moctane/asyncomplete-nextword.vim'
depends = ['asyncomplete.vim']
on_idle = 1
hook_source = '''
call asyncomplete#register_source(asyncomplete#sources#nextword#get_source_options({
  \   'name': 'nextword',
  \   'whitelist': ['*'],
  \   'args': ['-n', '20'],
  \   'completor': function('asyncomplete#sources#nextword#completor')
  \   }))
'''

このような設定をしていたのですが、

[dein] Error occurred while executing hook: asyncomplete-nextword.vim
[dein] Vim(call):E117: 未知の関数です: asyncomplete#sources#nextword#get_source_options

ファイル読み込み時にエラーになってしまいました。 検証していたようにhook_addであれば先に読み込まれるのでhook_source を hook_addに変更してみたのですが、 同様のエラーになりました。 plugins自身のfunctionなのですが、参照出来ない状態になりました。 asyncomplete-nextword.vim は上手く読み込まれないのかもしれないです。

scriptnamesを確認するとasyncomplete-nextword.vimは含まれてなさそうです。

filter /async/ scriptnames

で関連する

'prabirshrestha/asyncomplete.vim'
'prabirshrestha/async.vim'

が読み込まれているか確認してみると

 50: ~/.cache/dein/.cache/init.vim/.dein/plugin/async.vim
 51: ~/.cache/dein/.cache/init.vim/.dein/plugin/asyncomplete-lsp.vim
 52: ~/.cache/dein/.cache/init.vim/.dein/plugin/asyncomplete.vim
167: ~/.cache/dein/.cache/init.vim/.dein/autoload/asyncomplete.vim
168: ~/.cache/dein/.cache/init.vim/.dein/autoload/asyncomplete/utils/_on_change/textchangedp.vim
169: ~/.cache/dein/.cache/init.vim/.dein/autoload/asyncomplete/sources/ale.vim
192: ~/.cache/dein/.cache/init.vim/.dein/autoload/gitgutter/async.vim

と出力されているので関連するプラグインは読み込まれていそうです。
自身のプラグインは読み込まれていないので、何かが起因で読み込まれないのかもしれないです。

同様に

[dein] Error occurred while executing hook: asyncomplete-ultisnips.vim
[dein] Vim:E492: エディタのコマンドではありません: asyncomplete#sources#ultisnips#get_source_options

とエラーになっています。 こちらは関連するプラグインが以下の通りで 'SirVer/ultisnips'
'honza/vim-snippets'

filter /snip/ scriptnames

プラグインが見つからなかったので読み込まれてないようです。

他の影響があるかもしれないので以下のプラグインを読み込むだけの設定ファイルを作ってみました。

[[plugins]]
repo = 'Shougo/dein.vim'

[[plugins]]
repo = 'SirVer/ultisnips'

これをlazy 0 で読み込んで確認してみました。

call dein#load_toml('dein_test.toml', {'lazy': 0})

この設定でファイルを開いて

filter /snip/ scriptnames

再度scriptnamesで確認してみるとプラグインは見つかりませんでした。 読み込まれるプラグインと読み込まれないプラグインがあるかもしれないです。

ちなみにキャッシュファイル配下にはSirVer/ultisnipsのディレクトリは存在しているので読み込みに時に何かあるやもしれません。

*追記* UltiSnips.vimリポジトリ名とvimファイル名が異なっていた為、scriptnamesで確認できました。

~/.cache/dein/.cache/init.vim/.dein/plugin/UltiSnips.vim

まとめ

一旦ここまで移行してきたのですが、
vimデバッグする方法がわからなさすぎるので、どうすればいいかわからない状態です。
解決方法が分からない場合はまたvim-plugに戻して動かそうかとも思います。 私にはdein.vimは早すぎたのか、vimで嵌って時間が取られるケースがとても増えてきているので、VSCodeに移行時期かもしれません。
vimって難しいですね。

*追記*

Shougoさんに確認いただけてプラグインの読みこみはされている状態でした。
現状自分が設定している環境でhook_sourceでプラグインが上手く読み込まれてないことは確認出来ている状態なので、
時間があるときに最小構成で確認していこうかと思います。

参考にしたサイト

https://www.youtube.com/watch?v=B6rhg9uAWi8 https://qiita.com/kawaz/items/ee725f6214f91337b42b https://qiita.com/delphinus/items/cd221a450fd23506e81a

fish shellのprompt_pwdを少し改造する

イントロ

日々fish shellを使っているのですが、
プロントの表示を変更したくなりました。 ただ、単純には変更できなかったのでカスタマイズしてみました。 というお話です。

一般的なやり方

fish shell で プロンプト を変更する場合は以下のコマンドを打ちます。

fish_config

ブラウザが起動して設定を選択することでプロンプトを変更できます。
選択して好きな設定にできます。

fish.rubikitch.com

変更した点

例えば以下のディレクトリで作業していた場合

/Users/hotoolong/.ghq/github.com/hotoolong/translate.nvim

変更前のプロンプトの表示は以下になります。(私の設定の場合)

~/.g/g/h/translate.nvim (master|✔) $ 

これでもいいのですが、 現在作業しているディレクトリと親のディレクトリも省略しないで表示してほしいのです。

なぜなら、githubディレクトリ構造だとオーナー名/リポジトリ名 になっているため、 自分が作業しているディレクトリがどのリポジトリ配下のかというのいちいちチェックしたくなかったからです。

ということで
いろいろ調べてみたのですが、
デフォルトでは省略されている名称のサイズは変更可能なのですが、
ディレクトリだけ省略を変更するようなオプションは見受けられませんでした。

ちなみに 省略名称のサイズを3に変更したい場合はconfigに以下のように設定します。

set -g fish_prompt_pwd_dir_length = 3

こうすることで

~/.ghq/git/hot/translate.nvim (master|✔) $

というように表示されます。
これはこれで便利ですが、やはり親ディレクトリもフルで表示されてほしい。

プロンプトで表示しているディレクトリ情報は prompt_pwd で取得できます。
コードは以下にあります。

https://github.com/fish-shell/fish-shell/blob/master/share/functions/prompt_pwd.fish

prompt_pwd の内容はfish_prompt_pwd_dir_length 以外の 変更できないようです。
そこで関数を上書きしてみました。

最後の処理が省略して表示している処理になります。

string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $tmp

この処理を変更して

set -l folders (string split -rm2 / $tmp)
echo (string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $folders[1]'/')$folders[2]'/'$folders[3]

として/の右2つ分を取得してそれ以前のデータは既存のように省略データにしてつなぎ合わせています。
こうすることで

~/.g/g/hotoolong/translate.nvim (master|✔) $

となりました。 これで少し作業が捗りそうです。

Neovim用の翻訳プラグインを作った

イントロ

DeepLなどで翻訳が比較的簡単にできるようになっているのですが、
vimから離れずに翻訳したいと思いプラグイン入れてみるとNeovimに対応されてなかったのがプラグインを作ろうと思ったきっかけです。

ただ、よく調べると同様のプラグインは既にあり、
それを使えばよかったのですが勉強の為、作ることにしました。

使い方

リポジトリは以下にあり、興味がある方は使ってください。

github.com

訳したい行で以下のコマンドで翻訳してくれます。

:Tranclate

翻訳した範囲を選択しても同様に翻訳できます。

まとめ

完全に個人用に作成していますが、
機能変更なの要望があればお待ちしています。

Ruby 3.0.0 preview1 の インストール

イントロ

Ruby 3.0.0 preview1がリリースされました。

www.ruby-lang.org

RBS、Ractorなど新しい機能が試してみたいところですね。

手順

ruby-build の アップグレード

まずruby-buildのバージョンアップをしましょう。

$ brew upgrade ruby-build

インストール時のメッセージにOpenSSLのバージョンに関して注釈があります。

ruby-build installs a non-Homebrew OpenSSL for each Ruby version installed and these are never upgraded.

To link Rubies to Homebrew's OpenSSL 1.1 (which is upgraded) add the following
to your ~/.config/fish/config.fish:
  export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

簡単に訳すと

ruby-build はインストールされた Ruby のバージョンごとに、Homebrew ではない OpenSSL をインストールしますが、これらは決してアップグレードされません。
RubyをHomebrewのOpenSSL 1.1(アップグレードされている)にリンクさせるには、次のように追加します。

あなたの設定ファイルに:
  export RUBY_CONFIGURE_OPTS="--with-openssl-dir=$(brew --prefix openssl@1.1)"

私の場合はシェルがfishなので
このexportは設定できないのでset -xでglobalに設定します。

set -x RUBY_CONFIGURE_OPTS --with-openssl-dir=(brew --prefix openssl@1.1)

ruby の インストール

install list を確認

rbenv install --list は stable のみが表示されるためまだ3.0は表示されません。

$ rbenv install --list
2.5.8
2.6.6
2.7.1
jruby-9.2.13.0
maglev-1.0.0
mruby-2.1.2
rbx-5.0
truffleruby-20.2.0
truffleruby+graalvm-20.2.0

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all' to show all local versions.

--list-all ですべてが表示されるので3.0.0-preview1が追加されていることを確認しましょう。

ローカルのOpenSSLバージョン確認

ローカルのOpenSSLのバージョンを確認

$ openssl version
OpenSSL 1.1.1g  21 Apr 2020

同じバージョンなので設定したものをつかってもらうことにします。

rbenv install

普通にインストールすると

$ rbenv install 3.0.0-preview1
Downloading openssl-1.1.1g.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
Installing openssl-1.1.1g...

このようにOpenSSLのインストールから開始されます。
先程の RUBY_CONFIGURE_OPTS のオプションを追加しておくと設定されたOpenSSLを使ってもらえます。

 $ rbenv install 3.0.0-preview1
Downloading ruby-3.0.0-preview1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0-preview1.tar.bz2
Installing ruby-3.0.0-preview1...

上記のようにRUBY_CONFIGURE_OPTSを設定しているとrubyのインストールが始まります。 こうすることでインストール時間も節約できますね。

$ rbenv local 3.0.0-preview1
$ ruby -v
ruby 3.0.0preview1 (2020-09-25 master 0096d2b895) [x86_64-darwin19]

Enjoy Ruby life!

RSpec初心者向け勉強会の動画がとても良かった

イントロ

RSpecの初心者向け勉強会が紹介されていました。

blog.jnito.com

勉強会の内容を動画で公開してくれています。
最近RSpecをあまり書いておらずトレンドも追えてなかったのでとても為になる内容でした。

気になった内容

テストの書くべきところ

動画の12:25

システムとして重要な点を書くのは当然なんでしょうが、
System Testに重きをおいて書いていくのがいいという内容でした。

これはよくE2E(End to End)をいかに作っておくかがRailsバージョンアップする際にも鍵になる。
ような話を勉強会に参加したときによく話が盛り上がります。
E2Eを如何に作って置けるかがプロジェクトをうまくすすめる上でも効率がいいですね。

Capybaraの支援ツール

動画の8:10

github.com

を紹介していました。
これはChromeのExtensionでブラウザ操作をCapybaraのコードをジェネレートしてくれます。
これは便利そうですね。

github.com

は知っていたのですが、
それより以前に作らてていますし、
操作ごとに追加されているのを確認できるので使いたいところだけ使うこともできそうです。
これはいいですね。

まとめ

このような勉強会は有意義ですね。とても為になりました。
余談ですが、 最後の方に伊藤さんがイケメンだという話が出てたのがダンディな感じでイケメンですねw

Rubyの継承元のクラスの別メソッドをsuperで呼び出す

イントロ

Rubyの継承先で継承元のメソッドを単純に呼び出すにはsuperを使いますが、
継承元の別メソッドを呼び出したい場合にどうしていいのかわからなかったので調べてみました。

詳細

class A
  def test1(*args)
    puts "A#test1:args(#{args})"
  end

  def test2(*args)
    puts "A#test2:args(#{args})"
  end
end

class B < A
  def test1(*args)
    puts "B#test1:args(#{args})"
  end

  def test2(*args)
    method(:test1).super_method.call(*args)
    puts "B#test2:args(#{args})"
  end
end

B.new.test2('test')
# => A#test1:args(["test"])
# => B#test2:args(["test"])

Aを継承したBのtest2メソッドを呼び出しているのですが、
test2の処理でAクラスのtest1メソッドを呼び出したくなった場合に
以下の処理で呼び出しています。

method(:test1).super_method.call(*args)

method(:test1)でMethodオブジェクトを取り出して
super_methodで親のAクラスのtest1メソッドのMethodオブジェクトを呼びだせます。
これは便利ですね。

参考URL

親クラスの別のメソッドを呼ぶ - Qiita
class Method (Ruby 2.7.0 リファレンスマニュアル)