ノート PC の設定してた

(last update: 2018/01/22)

しばらく書いてなかったな。

先週末にノート PC の OS をインストールしなおしたのでセットアップしてた。 少し前に OS を high Sierra にアップデートしてみたら、Haskell の管理ツール stack が動かなくなったみたいで、これもよいきっかけと思いクリーンインストールしなおすことにした。

数年前から各種設定ファイルは ~/dotfiles にまとめて Github で管理しているので、ここから引っ張ってきてちょこちょこと作業すればいいのだけれど、今回は少し変更したいところもあったので設定ファイルを作り直すことにした。

変更したかったのは

  1. Cask での Emacs パッケージ管理をやめる
  2. Emacs の設定ファイル init.el を分割する
  3. $GOPATH$HOME/go ではなく $HOME にする
  4. zsh はもう使わない、fish だけでよい
  5. Ruby のインストールもいらないかな

などなど。

Emacs のパッケージ管理

これまでは Cask を使っていた。~/.emacs.d/Cask というファイルに使いたいパッケージを記入しておくと $ cask install とコマンド実行するだけで全部インストールしてくれるもの。

これはこれで便利だったけれど、use-package というパッケージを使えば、elisp のみでパッケージのインストールとその設定をまとめて記述することができて、外部コマンドを導入する必要もなくすっきりするので、変更してみたくなった。

use-package のいいところ

  • require したパッケージが入っていなかった場合でも init.el の読み込み自体はエラーにならない。
  • :ensure t と書いておくとそのパッケージをインストールしてくれる
  • key-bind や add-hook なども簡潔に記述できる

こんな感じ。

;; https://github.com/benma/visual-regexp.el
(use-package visual-regexp
  :ensure t
  :bind (("M-%" . vr/query-replace))
  )

Emacs の設定ファイル分割

分割をやめた方の話も一応。

ag とか ripgrep とか

grep の代替となる高速検索ツール、ag とか名前は聞いたことがあったけれど使っていなかったので今後は活用してみたい。そもそも grep すらあまり使っていないので何かと効率悪いことをしていると思われる。

anything と組み合わせて便利な感じになったりするんだと思う。多分。もしかしたら helm じゃないとだめなのかな。

何ならもう一回、rubikitch 先生の有料メルマガを購読して質問してみるのがいいかもしれない。

ripgrep 入れようとしたら

ripgrep 入れようとしたらスムーズにいかなかくて yak shaving 感あったと tweet したら作者の方からバイナリあるよ、とリプライいただいてびっくりした。

素直にダウンロードして /usr/local/bin に置いておいた。まだ使いこなせていないけれどせっかくだから使いたい。

Go の TOML ライブラリの作者として認識していた。すごい人はいろいろすごい。

fish の設定

昨年使い始めてから、もう二度と zshbash には戻れないと思わせる、とても便利なシェル fish。

今回は、使いたい関数は config.fish に直接書けばいいかなと思い、プラグインマネージャー fisherman は入れなかった。実際、ヒストリ検索と ghq 管理下のリポジトリcd するやつの 2 つがあれば満足かなと。

って思っていたのだけれど、z という最近 cd したディレクトリを列挙してくれるツールが快適そうに思えてきて、やっぱり fisherman 入れようかなと少し揺れているところ。

一回使ってみようかしらん。

そんなこんなで

設定ファイル init.el の内容を見直しつつ、分割して、書き直していった。一つ一つ調べながらやっていたら、結局一週間かかった。

Github にある既存のリポジトリをいずれ差し替えたいのだけれど、Git の操作に疎いのでひとまず bitbucket に置いた。(公開設定がプライベートになっていたので修正した)

README.md の更新もだいたい落ち着いたのでようやく一息つけるわ。

OCaml モジュールとシグネチャ

OCaml モジュールとシグネチャ

ソースファイル .mlコンパイルするとオブジェクトファイル .cmo.cmx .o と同時にインターフェイスファイル .cmi が生成される。

この .cmi について調べてみた。理解してしまえば何ということはないのだけれど、少し時間がかかった。

  • .mliコンパイルすると .cmi が生成される。
  • .mli がない場合は .ml から .cmi が生成される。

では .mli とは何だろう。

ではモジュールとは、シグネチャとは何だろう。

モジュールとは

詳細な解説は以下の記事、資料を読むとよさそう。

ただ、一度に全部を理解しようとするのはかなり困難だったので、ひとまずは「関連する処理やデータなどのまとまり」くらいの理解でよいと思う。Python や Go でいうパッケージと同じようなものだと考えればよいだろう。

OCaml では一つのファイルを一つのモジュールとするそう。前回書いた、階乗を求める処理でもモジュールとして扱っていた。

fact.mlFact モジュールとなる。

(* fact.ml *)

let rec fact n =
  if n = 0 then
    1
  else
    n * fact (n - 1)

利用する側からは open で読み込む。

(* main.ml *)

open Fact
let () = print_int (fact 10); print_newline()

もしくは、モジュール名.関数 の形でドット . をつけてモジュール内の関数を利用する。

(* main.ml *)

let () = print_int (Fact.fact 10); print_newline()

モジュールに別名をつけて読み込む

Pythonas で別名をつけて import するのと同じように

import numpy as np

以下の書き方で別名をつけて open することができる。

module F = Fact
let () = print_int (F.fact 10); print_newline()
  • この場合 open というキーワードは使わない。
  • 別名 F の部分は大文字で始める必要あり。

シグネチャとは

モジュールについては他の言語でも似たような仕組みはあるので、何となくではあるけれどわかった。次はシグネチャである。

OCaml におけるシグネチャは、モジュールの中身に対するアクセスの可否を制御する仕組みで、個々の関数には private とか public とかつけずに別途まとめて管理できるようになっている。

今まで触ったことのある言語(Python, Go, JavaScript あたり)ではこれに該当するものはなかったと思われ、新鮮に感じた。言語によっては、関数の仮引数や戻り値の型、アクセス修飾子などのことを指してシグネチャと呼ぶ場合があるみたいだけれど。

Python だと名前の頭にアンダースコア ___ をつけることで private 扱いになり、Go だと名前の頭文字が大文字なら外部からアクセス可能で小文字だとアクセス不可、という仕様になっている。

で、OCaml の場合。

Fact モジュールを少し拡張して試してみる。階乗 n! のバリエーションとして多重階乗というものがあるらしい。二重階乗 n!! であれば一つ飛ばしで積をとる。

5!! = 5 * 3 * 1
10!! = 10 * 8 * 6 * 4 * 2

この多重階乗を求める関数 multifact を書いてみた。

(* fact.ml *)

let rec fact n =
  if n = 0 then
    1
  else
    n * fact (n - 1)

let rec multifact x n =
  match n with
  | 0 -> 1
  | 1 -> 1
  | _ -> if x > n then
      n
    else
      n * multifact x (n - x)

let doublefact = multifact 2

モジュールを利用する側のコード。

(* main.ml *)

open Fact
let () =
  print_int (fact 10); print_newline ();
  print_int (multifact 2 10); print_newline ();
  print_int (doublefact 10); print_newline ();
;;

実行結果はこうなる。

# コンパイルして
$ ocamlc -o fact10 fact.ml main.ml

# 実行する
$ ./fact10
3628800 # fact 10
3840    # multifact 2 10
3840    # doublefact 10

シグネチャ*.mli に書く

次に Fact モジュールのシグネチャfact.mli に書く。公開するものだけを書き、シグネチャに書かれていないものは外部からアクセスできなくなる。

試しに multifact は非公開としてみる。

(* fact.mli *)

val fact : int -> int
val doublefact : int -> int

このシグネチャの書式はコンパイラ-i オプションをつけて当該ファイルを渡すと確認できる。-i オプションのみの場合は実際のコンパイルはしない(.cmo ファイルは生成されない)。

$ ocamlc -i fact.ml
val fact : int -> int
val multifact : int -> int -> int
val doublefact : int -> int

*.mli にリダイレクトして、公開したくないものを削除すればよい。

$ ocamlc -i fact.ml > fact.mli

ファイル *.mli が存在する場合は、*.ml よりも先にコンパイルしないとエラーになる。

$ ocamlc -c fact.ml
File "fact.ml", line 1:
Error: Could not find the .cmi file for interface fact.mli.

fact.mliコンパイルして、

$ ocamlc -c fact.mli # fact.cmi が生成される

fact.mlコンパイルして、

$ ocamlc -c fact.ml # fact.cmo が生成される

main.mlコンパイルしようとすると、エラー!

$ ocamlc -c main.ml
File "main.ml", line 4, characters 13-22:
Error: Unbound value multifact

ふむふむ。

それでは修正してみよう。main.ml から multifact を呼ぼうとしている箇所をコメントアウトして、

(* main.ml *)

open Fact
let () =
  print_int (fact 10); print_newline ();
  (* print_int (multifact 2 10); print_newline (); *)
  print_int (doublefact 10); print_newline ();
;;

コンパイルすると、今度は無事通った。

$ ocamlc -c main.ml # main.cmo が生成される
$ ls
. .. fact.cmi fact.cmo fact.ml fact.mli main.cmi main.cmo main.ml

これで必要なファイルが揃ったので、以下のように -o オプションで実行ファイルを出力する。

$ ocamlc -o fact10 fact.cmo main.cmo
$ ./fact10
3628800
3840

あるいは、以下のようにして最初から実行ファイルを出力することも可能。この場合もコンパイラには *.mli を先に渡す必要あり。

$ ocamlc -o fact10 fact.mli fact.ml main.ml

シグネチャを書かない場合は全て公開される

先のエントリで見たようにシグネチャを書かなくても *.ml から *.cmi が生成されていた。この場合は、モジュールの中身は全て公開されることになる。

まぁ OCaml プログラマが意図的にシグネチャを書かないというケースはなさそう(想像)だから、気にしなくていいんじゃないかな。

参照

OCaml コンパイルの続き

(last update: 2017/09/23)

前回の続き。

$ ocamlc -o fact10 fact.ml main.ml

コンパイラ ocamlcocamlopt-o オプションで実行ファイル名を指定してソース・ファイル .ml を渡すと実行ファイルが出力される。また .cmo.cmi などのファイルも生成される。

で、これは恐らく手順をスキップしているというか、コンパイラがよしなにやってくれている。順をおって一手ずつ進めるとしたらこうなる。

まずソースファイル .ml だけの状態から

$ ls
. .. fact.ml main.ml

fact.mlコンパイルする。(-c オプションを指定すると実行ファイルを作らずコンパイルだけする)

$ ocamlc -c fact.ml

$ ls
. .. fact.cmi fact.cmo fact.ml main.ml

次に main.mlコンパイルする。

$ ocamlc -c main.ml

$ ls
. .. fact.cmi fact.cmo fact.ml main.cmi main.cmo main.ml

このように 1 つずつコンパイルする場合も main.ml から先にコンパイルしようとするとエラーになった。依存される側(参照される側)から先にコンパイルする必要がある。

File "main.ml", line 1, characters 5-9:
Error: Unbound module Fact

で、オブジェクトファイル .cmoコンパイラに渡して実行ファイルを出力する。

$ ocamlc -o fact10 fact.cmo main.cmo

$ ls
. .. fact.cmi fact.cmo fact.ml fact10 main.cmi main.cmo main.ml

$ ./fact10
3628800

ちなみに .cmo を渡す場合も依存関係を無視してはいけない。main.cmo を先にするとエラーになる。

$ ocamlc -o fact10 main.cmo fact.cmo
File "_none_", line 1:
Error: Required module `Fact' is unavailable

コンパイラは賢いから人間がソースファイルを渡して「実行ファイルを作って」とお願いしてもやってくれるけれど、ソースファイルからオブジェクトファイルを生成して、それを結合して実行ファイルを作成するというのが本来の手順なのだろう。

でも、同じ結果が得られるなら最初から実行ファイルを作成した方が早いだろうし -c オプションはいつ使うのかという疑問がわく。

それは恐らく、もっと大きくて複雑なソフトウェアを作る場合には全体をパーツごとに分解して作っていくので、そういうときには、

ある部分は既にコンパイル済みの状態(オブジェクトファイル)で、 一部分だけコンパイル(ソースファイル -> オブジェクトファイル)し直して、 既にあるオブジェクトファイルと組み合わせて実行ファイルを作成する

という使い方をしたりするので必要、というか必須なのだと思う。(想像)

(追記 2017/09/23)

上記ではバイトコードコンパイラ ocamlc での結果を書いたが、ネイティブコードコンパイラ ocamlopt で試した場合も同様の結果になった。

参照

OCaml プログラムをコンパイルする

インストールとか環境構築については今度書くとして、今日はコンパイルについて。

バイトコードとネイティブコード

OCaml をインストールすると標準で 2 種類のコンパイラがついてくる。

バイトコード

ネイティブコード

  • コンパイルしたプログラムは機種(ハードウェア・OS)に依存する
  • コンパイルした環境と異なる環境では動かない場合がある
  • インタプリタは不要でハードウェアから直接実行できる
  • ネイティブコードの方が実行速度は速い

コンパイルしてみる

サンプルとして階乗を求める関数 fact と、

(* fact.ml *)

let rec fact n =
  if n = 0 then
    1
  else
    n * fact (n - 1)

それに引数 10 を渡して実行した結果を表示するプログラムを書く。

(* main.ml *)

open Fact
let () = print_int (fact 10); print_newline()

ocamlc でコンパイル

コンパイルして実行ファイルを作成するには以下のように入力する。-o オプションで実行ファイルの名前を指定する。

$ ocamlc -o fact10 fact.ml main.ml

コンパイルすると実行ファイル fact10fact.cmi, fact.cmo, main.cmi, main.cmo というファイルが生成され、fact10 を実行すると結果が表示される。

$ ./fact10
3628800

しかし、ocamlc に渡す順番を逆にするとエラーになる。

$ ocamlc -o fact10 main.ml fact.ml
File "main.ml", line 1, characters 5-9:
Error: Unbound module Fact

これは main.ml の中で fact.ml で定義されている関数 fact を参照している、つまり main.mlfact.ml に依存しているからである。

ocamlopt でコンパイル

ocamlc と同様に -o で出力するファイル名を指定する。

$ ocamlopt -o fact10 fact.ml main.ml

実行ファイルの他に生成されるファイルが ocamlc の場合とは一部異なった。

ocamlc では fact.ml から fact.cmi, fact.cmo が生成されたのに対して、fact.cmi は同じで、fact.cmo の代わりに fact.cmxfact.o が生成されていた。

この *.cmi, *.cmo, *.cmx, *.o とやらは何だろうか。こういう普段見慣れないファイル形式が一度に複数出てくると、ウッてなるんだよね。落ち着いてマニュアルを見てみる。

.cmi とは

.cmo とは

.o とは

.cmx とは

参照

ネイティブコードにコンパイルされたコンパイラ

上述の ocamlcocamloptバイトコードコンパイルされたコンパイラのようで、ネイティブコードでコンパイルされたものもあり、通常はこちらを使うらしい。

  • ocamlc.opt
  • ocamlopt.opt

ネイティブコード にコンパイルされた バイトコード および ネイティブコード コンパイラ。 ネイティブコード コンパイルが可能な環境では通常このコンパイラを使う。

OCaml コンパイラソースで make opt の後に make opt.opt を行うと作成される。 通常の ocamlc, ocamlopt は バイトコード で実行されるが、 *.opt コンパイラはネイティブコードに コンパイルされているため ocamlc, ocamlopt よりコンパイル速度が早い。 (バイトコードコンパイラがひどく遅いわけではないが。)

ocamlc, ocamlopt 以外の OCaml のツールにも、.opt の suffix がついた ネイティブコードバージョンが存在するのでそちらを使ったほうがよい。

OCaml に再入門( 3 年ぶり 2 回目)

最近、OCaml に再度入門しようとしている。前に触ってみたのは 3 年前くらいだろうか。書籍『プログラミングの基礎』を読み進めながら一部を自分でも書いて動かして、という感じで途中までやっていた。

最後までやらずにやめてしまったのは何故だったか、あまり覚えていないけれど

  • より優先順位の高いプロジェクトがあり、そちらに取り組むことにしたから
  • OCamlPythonJavaScript などと比べると日本語の情報が少なく、敷居が高く感じたから
  • Emacs の中で対話環境を動かして、バッファの内容を即実行させることができたのだが、実行結果が少しずれて表示されてしまい、その直し方がわからず、何だか気持ちが悪いなという思いがつきまとっていたから

という感じだった気がする。まぁ結局のところ、必要に迫られていたわけでもないから、ということだろう。

その後、Go を少し勉強した。仕事で使う小さなツールを 2, 3 個書いて、それらは毎日のように使っているので Go は手を出してよかったと思う。仕事で使うツールを書くなら Go で書くのがよさそうだと思うが、今は仕事で使うツールを書くために週末の自分の時間を使いたいとは思わなくなったので、Go 自体の勉強もストップしている。

しばらく触らないと忘れて、忘れるとまた調べ直すために時間がかかることが億劫に感じられて触らなくなる、という疎遠ループ。

で、しばらくプログラミングとは関係ないことに取り組んでいてそちらはそちらで引き続きやっているのだけど、気分転換も兼ねてまたプログラミングに関する何かを勉強しようかなと思っていた。

そしたら、たまたま読んだ以下の記事で『プログラミング in OCaml』が紹介されていたので OCaml を再び触り始めた次第。

この本は、OCaml を使うつもりがとくにない人でも、独力でプログラミングを学んできたような人であれば、読むといいことがたくさん書いてあると思っています。 具体的には、OCaml というプログラミング言語でのプログラムの書き方だけでなく、どうしてそういう機構になっているのかがいちいち詳しく解説されており、プログラミング言語の理論についても味見できるようになっています。

やはり強静的型付けで、コンパイラがしっかりチェックしてくれる言語の方が、堅牢なプログラムを書きやすいのではないかと思っている。プロじゃないからこそ、言語の機能に頼りたいというか。

学習コストもかかるだろうが、期限がある話ではないので今後の人生を考えると長期的には十分回収できるはず。

というわけで、ゆっくり少しずつでも積み上げていけたらと思うので、調べたことをここにも書いていこうかなと。

千葉で温泉

先週の話。

  • 木曜にクロサワから連絡をもらって飯田橋で軽く飲んだ。
  • 家族が帰省中で暇してるということで週末にどこかに行こうということになった。
  • 金曜にいろいろ調べて千葉にある温泉施設、いわゆるスーパー銭湯的なところに行くことにした。
  • クロサワが車を出してくれて、まさかの朝 9 時集合で千葉までドライブ

岩盤浴が最高

  • 岩盤浴がとても気持ちよかった。
  • サウナと違って湿度が高いのであまり辛くなく、じわ〜っと汗をかく感じ。
  • フロントで専用のウェアを受け取って、それに着替えて岩盤の上に大判のバスタオルを敷いて寝そべる。
  • しばらくすると全身から汗が出てくるのでほどほどのところで一旦退室し、隣りにある涼むための部屋(エアコンががっつり効いている)に入る。
  • そして水分補給してまた岩盤の上に戻る、という感じ。
  • 以前 YZ に連れて行ってもらった板橋にあるさやの湯処もよかったな、そういえば。
    • 板橋なら岩盤浴のためだけに、月 1 回くらいのペースで通ってもいいかもしれない。

全般的に最高だった

  • 気の置けない友人と他愛もない話をしながらゆっくり風呂につかったり、岩盤浴で寝そべったり、ジンギスカンを食べたりして過ごすのはとても楽しかった。
  • 行き帰りの運転もぜんぶおまかせだったのでただ乗ってるだけという気楽さ。
  • いろいろ話が聞けて面白かった。
  • 大企業には大企業の悩みというか、いろいろとアレなところもあるのだなぁと思ったり。

東京に戻って

  • 最後は車を置いてから木場のもつ焼き屋さんで軽く飲んで解散。
  • クロサワはもともとあまりたくさん食べる感じではなかったけれど二人とも食べる量が減った気がする。
  • 少量で少しずつ食べたら満足してしまう。
  • でも活気があってよいお店だった。

log を残していこう

  • しばらくご無沙汰してたなーと思ってはいたけれど 1 月から書いてなかったのか、と少しびっくりした。
  • 何かしらちょいちょい書いていくと自分でも生活を振り返ることができて有益だし、家族にもこちらの様子が伝わるし、よいのではないか。
  • あと、ずっと文章を書かないでいると、そのうち書けなくなりそうな気もする。
  • 東京は少し暑くなってきたけれど引き続きがんばろう。

JavaScript, Node.js を始める

JavaScript 熱の高まりというか、やっぱり使えたらいろいろ便利そうだな*1と思い、昨年末あたりから少しずつ調べたりまとめたりしていたので、こちらにも書いておこう。

Node.js をインストール

公式サイトからインストールしてもいいけれど、入れ直したりバージョンを上げたりをやりやすくするためツール経由で入れるほうがよさそうなので nodebrew を使う。

curl でインストール。

$ curl -L git.io/nodebrew | perl - setup

PATH を通しておく。

$ export PATH=$HOME/.nodebrew/current/bin:$PATH

nodebrew 使い方

バイナリを入れるやり方でいいと思う。

# すでにインストールしていた場合
$ nodebrew selfupdate

# インストール可能なバージョンを列挙する
$ nodebrew ls-remote

# バイナリを入れる場合
$ nodebrew install-binary <version>
# ソースからコンパイルする場合
$ nodebrew install <version>

とりあえず stable を指定したら v7.2.1 が入った。

# <version> の代わりに stable や latest という指定が可能
$ nodebrew install-binary stable

# インストール済のバージョンを表示
$ nodebrew ls

# 使用するバージョンを指定
$ nodebrew use stable

# アンインストールする場合
$ nodebrew uninstall <version>

パッケージマネージャ npm について

Node.js をインストールすると npm コマンドが使えるようになる。パッケージマネージャと書いたけれど、備えている機能はもう少し幅広いようだ。

Node.js で開発する、プロジェクトを作るには以下のコマンドから始める。

$ npm init

プロジェクト名とか作者名とかいろいろ質問されるのでそれに答えていくとそれらの情報を含んだ package.json が作成される。

npm init の際にオプション --yes をつけると全てデフォルトで進めてくれる。

package.json にはインストールしたパッケージの情報を記載しておけば、そのプロダクトを別な環境でインストールする際に npm install とするだけで依存するパッケージをインストールしてくれる。

link

npm でパッケージをインストール

npm install <package_name> でインストールする。

オプション --save or --save-dev をつけるとインストールと同時に package.json にも記載される。

--save は実行時に必要なパッケージとして "dependencies:" に記載される。

--save-dev は開発時に必要なパッケージとして "devDependencies:" に記載される。

$ npm install <package_name> --save
$ npm install <package_name> --save-dev

オプション

  • npm inpm install と等価
  • -D--save-dev と等価
  • -S--save と等価
  • -g--global と等価

以下のようにも書ける

$ npm i -D <package_name>

link

インストールしたパッケージを確認する

# ローカルのパッケージを確認
$ npm list # or ls
# グローバルのパッケージを確認
$ npm list --global # or -g

ただ、上記のコマンドだと大量のパッケージが表示されるので以下のようにオプションを指定するのがよい。

$ npm list --depth=0

パッケージのインストール先

ローカルにインストールするとプロジェクトディレクトリ内の node_modules/ に入る。

グローバルにインストールすると <prefix>/lib/node_modules/ に入る。 <prefix> を確認するコマンドは以下の通り。

$ npm config get prefix

ローカルにインストールしたパッケージを使うために PATH を通す。

$ export PATH=$(npm bin):$PATH

その他

インストールしたパッケージのアップデート

この記事が参考になりそう。まだ必要に迫られていないので試したりしていない。

インストールするパッケージのバージョンを指定

package.json にはそのパッケージのバージョン番号も指定される。書式については以下の記事が参考になる。

ローカルのパッケージを Git の管理対象から除外

.gitignorenode_modules/ と書いておこう。

*1:GoogleAppsScript とか Electron とかを用いて生活および仕事のタスクを処理する便利な何かを作れるのではないか的な

fish を導入

(last update: 2017/02/21)

少し気になっていたモダンなシェル fish 、実家の兄も使っていていろいろ見せてもらったらやっぱり便利そうだったので導入してみた。

MacPorts でインストール。Homebrew 派の人は $ brew install fish で。

$ sudo port install fish
$ fish_config # ブラウザで設定画面が開く

fish をデフォルトのシェルに設定する。まず fish がインストールされているパスを確認して、 /etc/shells を編集する。その上で、 chsh コマンドで切り替えれば OK

$ which fish # -> /opt/local/bin/fish
$ sudo emacs /etc/shells # 上記 fish のパスを追加
$ chsh -s /opt/local/bin/fish

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

oh-my-fish のメンテナの方が作っているというプラグインマネージャ fisherman をインストール

$ curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman

peco 関連のプラグインをインストール。 peco 自体は以前に go get でインストールしていた。

$ fisher omf/plugin-peco
$ fisher yoshiori/fish-peco_select_ghq_repository

fish-peco_select_ghq_repositoryghq で管理しているレポジトリを peco で検索して cd する拡張。 C-r でのヒストリ検索に peco を使うように、ghq のやつは C-o にそれぞれ設定しておく。

function fish_user_key_bindings
  bind \cr peco_select_history
  bind \co peco_select_ghq_repository
end

参考

fish-mode をインストール

Emacs で fish スクリプト(設定)を編集するための fish-mode をインストールする。 ~/.emacs.d/Cask(depends-on "fish-mode") を追加して以下のように実行すれば OK.

$ cd ~/.emacs.d/
$ cask install

設定ファイルは zshbash とはことなり .fishrc ではなく ~/.config/fish/config.fish となる。

PATH の設定

.zshrc とは構文が異なる。以下のような感じ。

# PATH
set -x PATH /opt/local/bin /opt/local/sbin $PATH
set -x PATH $HOME/bin $HOME/.cask/bin $HOME/py35/bin $PATH

# Go
set -x GOROOT (go env GOROOT)
set -x GOPATH $HOME/go
set -x PATH $GOPATH/bin $GOROOT/bin $PATH

# nodebrew
set -x PATH $HOME/.nodebrew/current/bin $PATH

alias の設定など

alias は zsh と同じ書式でもいけるという話もあったかもしれない。

# alias
alias rm "rm -i"
alias cp "cp -i"
alias mv "mv -i"
alias mkdir "mkdir -p"

alias find "gfind"
alias xargs "gxargs"

# alias for git
alias gst "git status"
alias gdif "git diff"
alias gdifc "git diff --cached"

# alias for Mac
alias ql "qlmanage -p $argv[1]"

# user defined functions
function cd
  builtin cd $argv
  ls -a
end

function fish_user_key_bindings
  bind \cr peco_select_history
end

補完候補の拡充

以下のコマンドで man などから補完候補を追加してくれるそうな。頼もしい話である。

$ fish_update_completions

現時点の config.fish

Good Bye, 2016

年末年始ということで実家に帰省している。毎年同じことを書いていると思うが、 2016 年もあっという間に過ぎていったように感じている。

学生時代に家庭教師のアルバイトで関わった生徒さんから年賀状をもらって嬉しかったのが 2016 年の 1 月で、そこからいろいろやっていたらもう 12 月。はー、速い。 結局その生徒さんには年賀状は返信して「今度食事でも」と伝えたのだけれど、結局連絡先がわからなくて連絡しないままになっていた。 12 月に入ってから手紙を書いたけれど、「もう知らね」と言われてもまぁ仕方ない。もうちょっと早めにアクションすべきだったな。

速い?早い?

関係ないけれど「時間が経つのがはやい」というときに「早い」か「速い」のどちらなのか、いつも迷う。時間が過ぎていくスピードのことを言うのだから「速い」ではないかと思っていたが、必ずしもそう考える人だけではないようだ。

この説明で納得しかけたけれども、時間の進むスピードが変化したわけではないということは十分承知の上で、「はやい、と感じる」ということを言っているのでやはり「速い」で間違ってはいないような気もする。

振り返り

  • 昨年から取り組み始めたとあることは細々と続けられている。まだ実を結んではいないが、いずれよい結果に繋げられると思う。
  • 軽い運動(腕立て伏せとスクワットなど)をする習慣もだいぶ定着してきた。

  • 英語の勉強はあまり進んでいなかった。最後に受けた TOEIC で 820 点くらい取れて嬉しかったのだけれど、確認したら 2014 年の話だった。寝る前に DUO 3.0 を開いて例文をシャドウイングすることを毎日の習慣にしたい。

  • 数学の勉強(確率、微分積分線形代数など)はあまり進められなかった。

  • Python はあまり書かなかったのでだいぶ忘れてしまった。

  • 夏頃に支出管理シートを作るため GoogleAppsScript (JavaScript) を(自分にしては)たくさん書いた。 TypeScript を使ってみたいと思いつつ環境構築の段階で躓いている。
  • Go を使ってみようと思ったのはいつからだったっけ。夏の前くらいかな?「スターティング Go 言語」を枕元に置いてちょいちょい読んだり、 A Tour of GoGo by Example を写経してみたりしたけれど、ちゃんと書くことなく時間が過ぎていった。 12 月下旬に仕事で使えそうなツールを思いつき、 Go で書いてみた。 100 行くらい。今後はもっと使えるようになりたい。

  • blog を全然書かなくなった。 Markdown で書けるようにとはてなダイアリーからはてなブログへ移行したのだけれど、あまり書かないままだった。

  • これからはもっと気軽に駄文を書き散らかしていきたい。何か書いていないと、文章を書く力が落ちると実感し始めた。他の人はどうか知らないが、少なくとも自分に限ってはそのように感じている。

そういや、 Markdown で改行のために行末にスペースを 2 つ入れる仕様って結構一般的な話なの?兄と話していて聞いたんだけど全然知らなかった。 Emacs で保存時に行末のスペースを削除する設定にしているので、全然使えないというか、相容れない感じがする。

;; 保存時に行末のスペースを削除
(add-hook 'before-save-hook 'delete-trailing-whitespace)

スターティングGo言語

スターティングGo言語