フリーの OPC UA クライアント Jupiter を作りました
DockerでWindowsコンテナを起動する為に必要な設定
Docker for Windows では、 Windows コンテナが起動できるようになっています。
開発者に朗報! Windows 10でWindows Serverコンテナが実行可能に (1/2):企業ユーザーに贈るWindows 10への乗り換え案内(42) - @IT
https://hub.docker.com/_/microsoft-windows
ただ、私の環境では公式のドキュメントに書いてある通りに docker run mcr.microsoft.com/windows:1903
を実行すると no matching manifest for unknown in the manifest list entries.
と表示され起動できない。
Windows コンテナは Docker を Windows コンテナ用に設定する必要があるみたい。
常駐タスクアイコンの中から、 docker for windows
を右クリックして Switch to windows containers
を選択しておくこと。
あと、 エクスペリメンタル機能を有効にしておく必要がある。
同じように docker for windows
のアイコンを右クリックして Settings
から Daemon
を選択して Experimental features
のチェックを入れる。
いろんなサイトではこれで有効になるようだが、私の環境では無理だった。
私の場合は、エクスペリメンタル機能を有効にするために、%USERPROFILE%
の下にある .docker/config.json
の中に "experimental": "enabled"
を追加した。
あと、Windows コンテナは ホストの Windows OS と同じ環境で動作するため ホストのOSをゲストのOSと同じにしておく必要があるようだ。
私の環境は WIndows 10 Pro 1803 だったため、ちゃんと起動できなかった。 Windows Update を行って Windows 10 Pro 1903 にしておく必要がある。
これらをすべて実行し、 docker for windows
を再起動したのち、再度 docker run mcr.microsoft.com/windows:1903
を実行すると実行できる。
ただ、実行してもすぐに終了してしまうので、以下のようにインタラクティブモードにしたほうがいい。
docker run -it --name wincont01 --isolation=hyperv mcr.microsoft.com/windows:1903 cmd
空白区切りの文字列をそれぞれのワードで括る簡単なやり方
vim-jp の slack で以下のような質問をした
すると、すぐに数人の方からレスポンスをいただいた。
置換を使う方法や
ciw と ドットオペレーションと組み合わせてやる方法
マクロを使うことを提案していただいたりもした。
置換を使う方法で、 &
が 使われていて、私はこの記号を使ったことがなかったので勉強になった。おそらく、 検索文字全体を表す記号
なんだとおもう。
また、ciw と ドットオペレーションを組わせてやる方法では、 <C-R><C-O>
でレジスタの中身を挿入することでドットオペレーションで繰り返しても問題なく動作するようにするテクニックが使われており、色々と勉強になった。
ciwとドットオペレーションの繰り返しでは、<C-R>
でやる方法ではうまくいかない。
理由は以下の通り、<C-R>
ではドットレジスタに挿入後の値が入ってしまうため、繰り返しても期待した動作にならない。 <C-R><C-O>
は ドットレジスタに <C-R><C-O
がそのまま積まれるので、繰り返しても都度レジスタの内容が展開され、問題なく動作するということのようだ。
結論
Vim は奥が深い!!
vaffle.vim から netrw にお試しで移行してみた
今まで、vimのファイラとして vaffle.vim を使ってきた。正確な使用期間は思い出せないが私がvimを使い始めてから結構な期間使っていたと思う。
ただ、vaffle.vim は buftype を nofile に設定している関係上、 grep をしたときに閉じずに残ってしまうという現象が発生する。これは、dirvish でも同じ現象になるので、vaffle.vim だけの問題ではなさそうだった。自前でファイラを作ってしまおうか?とも思ったが、調べていく途中で、netrwでは発生しない問題だということに気いたので、netrwをカスタマイズして使えるようにすれば解決するのではないか?という思いから、vaffle.vim をやめてnetrw に移行することにした。
最近、Vim界隈で有名なゴリラさんもnetrwをお勧めされているようで、以下に記事がある。それを参考にしつつ私のvimrcもいじってみた。
以下が私のnetrwの設定である。
" バナーを非表示 let g:netrw_banner=0 " ファイル/ディレクトリ名のみ表示(日付等は表示しない) let g:netrw_liststyle=0 " プレビューは縦分割する(使うことはあまりなさそう?) let g:netrw_preview=1 " デフォルト表示をドットファイル非表示に設定 let g:netrw_hide=1 " g:netrw_hide で非表示にするファイルの設定. " これがないとちゃんと非表示にならない let g:netrw_list_hide='\(^\|\s\s\)\zs\.\S\+' augroup NetrwKeyMap au! " 親ディレクトリに移動する (h) au FileType netrw nmap <buffer> h - " ファイルを開く、ディレクトリ移動 (l) au FileType netrw nmap <buffer> l <CR> " ウィンドウ移動 (s) // デフォルト動作はソートの種類変更 " (あまりつかわないかなぁという理由でつぶす) au FileType netrw nmap <buffer> s <C-W> " ドットファイルの表示/非表示切り替え " vaffle.vim に挙動を合わせる au FileType netrw nmap <buffer> . gh augroup END
とりあえずはこの設定でやってみようと思う。懸念点としては、今まで i
でファイルを作成していたがそれができなくなったことくらいかなぁと思っている。netrwのいい点は、デフォルトで x
で関連付けられたプログラムでファイルを表示することができることや、 c
で表示中のディレクトリをカレントディレクトリにすることができること。vaffle.vim ではシンプルさを追求しているため、このあたりの動作は実装されていなかったので自前で拡張する必要があったが、netrwはその必要がないので、vimrcがすっきりしそうだなぁという感覚がある。
vim の :rubyfile は rb_load を使うが ruby の load は rb_f_load を使う
事の発端
if_ruby を使って何かしたいなぁということで :rubyfile test.rb
を実行したが、LoadError: cannot load such file -- test.rb
となって実行できなかった。ただ、:ruby load "test.rb"
は実行できるので、何が違うのか?という疑問が事の発端
vim-jp の slack で質問
slack で質問してみると :rubyfile
は rubyの公開APIの rb_load()
を呼んでいるだけとのこと。また、ruby load
は Kernel.#load‘ を使用しているが、なぜ
:rubyfile` のほうが動かないのかはわからないとのことで原因を追究してみたくなった。
Kernel.#load は rb_load
を実行しているのか?
2.6のブランチの load.c
を見ると、 load
は rb_f_load()
をコールしているようです。
https://github.com/ruby/ruby/blob/ruby_2_6/load.c#L1233
rb_load
も load.c
に実装があり、単に rb_load_internal()
をコールしているのみとなっているようです。
https://github.com/ruby/ruby/blob/ruby_2_6/load.c#L659
rb_f_load()
の中でも rb_load_internal()
をコールしていますが、前処理がいくつか入っているため、その部分に今回の原因がありそう?
rb_f_load の前処理を追う
追うといっても前処理で生成されている文字列を一個一個printfで出力してみるというだけのことをしました。
static VALUE rb_f_load(int argc, VALUE *argv) { printf("rb_f_load start\n"); // 追加 VALUE fname, wrap, path, orig_fname; rb_scan_args(argc, argv, "11", &fname, &wrap); printf("fname(1): %s\n", StringValueCStr(fname)); // 追加 file_to_load(fname); orig_fname = rb_get_path_check_to_string(fname, rb_safe_level()); printf("orig_fname:%s\n", StringValueCStr(orig_fname)); // 追加 fname = rb_str_encode_ospath(orig_fname); printf("fname(2): %s\n", StringValueCStr(fname)); // 追加 RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname)); path = rb_find_file(fname); if (!path) { printf("path is null?? \n"); // 追加 if (!rb_file_load_ok(RSTRING_PTR(fname))) load_failed(orig_fname); path = fname; } printf("path: %s\n", StringValueCStr(path)); // 追加 printf("wrap: %d\n", RTEST(wrap)); // 追加 rb_load_internal(path, RTEST(wrap)); RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname)); printf("rb_f_load start\n"); // 追加 return Qtrue; }
結果的には、load "foo.rb"
のようなスクリプトで文字列が変化することはなく。rb_load_internal()
には foo.rb
という文字列がそのまま渡されているようでした。wrap
の値が怪しいのかな?とも思って見てみましたが、それも if_ruby の値と同じでした。
rb_load の実装を見てみる
rb_load()
はrb_load_internal()
をコールしているだけといいましたが、実際には引数で渡ってきたパスを一旦file_to_load()
関数に渡していました。
void rb_load(VALUE fname, int wrap) { rb_load_internal(file_to_load(fname), wrap); }
file_to_load()
の実装は以下の通りです。FilePathValue()
ではエラーになってなかったっぽいので、rb_find_file()
でエラーになって返り値が0になるため、load_failed()
が呼ばれてしまうようです。
static VALUE file_to_load(VALUE fname) { VALUE tmp = rb_find_file(FilePathValue(fname)); if (!tmp) load_failed(fname); return tmp; }
rb_find_file
は rb_f_load()
の中でも使われており、返り値が0の場合の処理が rb_load()
とは異なっているようです。
path = rb_find_file(fname); if (!path) { if (!rb_file_load_ok(RSTRING_PTR(fname))) load_failed(orig_fname); path = fname; }
rb_file_load_ok()
という関数がキモな気がしてきました。
rb_file_load_ok()
は file.c
内に定義されています。ただ、内容を見た感じ、fdを取得して内部でロード可能かを判断しているだけのようなので、特別何があるというわけでもなさそう。カレントディレクトリにロード対象のファイルがあれば、それをちゃんとロード可能だと判断してくれそうな気がします。というかしてくれます。
結論
Kernel.#load
は rb_f_load()
を呼んでいて、vimの:rubyfile
はrb_load()
を呼んでいる。rb_load()
の中では file_to_load()
が使われていて、この関数の中のrb_find_file()
が返り値0を返すためロードエラーとなっている。rb_f_load()
でも同関数が使われている。ただ、一度ロードには失敗するが、そのあとの処理でrb_file_load_ok()
でロード可能と判断されるため正常にロードされる。
なぜ、このような違いがあるのかまでは今回は追えなかったが、一応 :rubyfile
が ruby load
と異なる動作をする理由がわかったので今回は終了とする。
if_ruby 付き vim を使って ruby を実行するには PATHに ruby_builtin_dlls も足す必要がある
Could not load library msvcrt-ruby240.dll · Issue #2660 · vim/vim · GitHub
毎日ビルドしている Vim に if_ruby を足したのだが、 :ruby print "Hello"
をしても dllが見つからない旨のエラーが発生してしまってなんでだ?と思っていたら、上のサイトで示されている通り、ruby_builtin_dlls
を 環境変数の PATHに設定する必要があるとのこと。昔はそれでもよかったっぽいけど、ruby 2.4 以降からは必要らしい。日本語の説明記事がなかったので、メモとして書いた。
WEB上で打刻できるタイムカードサービスを作った
タイトルで落ちてるんですが、WEB上で打刻できるタイムカードサービスを作りました。
アクセスすると、ログインダイアログが表示されます。
Sign-Up
ボタンを押すと、ユーザー登録画面になります。
ユーザー登録してもらうと、仮登録状態になります。
登録したメール宛にメールが送信されるのでメール上のリンクを 押してもらって、本登録を完了してください。
リンクをクリックすると、以下のページが表示されます。 このページはこれ以上なにも起こらないので閉じてください。
上記のページが表示されると、ユーザー検証中のページが以下のページに遷移します。
名前を入れてもらうと、タイムカードページになります。
オレンジのボタンを押してもらうと、出社状態になります。
退社ボタンで退社します。
はい、それだけです。
時間が自動で計算されたりもしないし、管理者モードみたいなものもないので使い勝手は微妙ですが、もしよかったら使ってみてください。
ソースは こちら にありますので、PRもお待ちしております。