emacsでコード読んでるときに「現在いる行が含まれたプルリク」に飛びたいを見れるようにした
これ見て hub browse -- commit/<commit-id>
でcommitに飛べることを知ったので、それを使って emacsでコード読んでるときに「現在いる行が含まれたプルリク」に飛びたいを見れるようにした。
このスクリプトも元ブログと一緒でプルリクのページではなくコミットページを開くところで終わってますが。
(defun open-github-commit () (interactive) (let* ((cmd1 "git blame -l -L %s,+1 %s | cut -d ' ' -f 1") (cmd2 "hub browse -- commit/%s") (zero "0000000000000000000000000000000000000000") (commit-id (shell-command-to-string (format cmd1 (line-number-at-pos) buffer-file-name)))) (if (string= zero commit-id) (message "This line is not commited") (shell-command (format cmd2 commit-id))))) (global-set-key (kbd "M-g o") 'open-github-commit)
hub browse -- commit/<commit-id> でいけるのか昔自分の書いた軟弱な正規表現を修正しなくて済みそう最高
— がんま (@ganmacs) 2017年2月9日
さよならgheに対応してないelisp君 GitHub - ganmacs/emacs-github-open: Open a commit url in github.com
Treasure Data インターンで最高の夏過ごしてきた #td_intern
8月1日から9月30日の間,Treasure Data Summer Intern 2016に参加していました. 他のインターン生2人からの強烈なプレッシャー (強烈なプレッシャー1,強烈なプレッシャー2)に負けたので僕もインターンブログを書きます.
tl;dr
すごいメンターの元 Fluentd の開発してると何故かめっちゃお金がもらえるインターンでとにかく最高
なにやってたの?
キュートなロゴ
Fluentd というソフトウェアの v0.14 向けの機能を,メンターの @tagomoris さんの元,開発しました.具体的に行ったことは以下のようになります(スライドからそのまま持ってきただけですが).
- 6 features
- 2 enhancements
- Optimizing multiple filter calls
- Add event size to options in a forward protocol
- Some small tasks
インターン期間は2ヶ月あったので,最初の1ヶ月は Fluentd の開発スタイルに慣れようということで小さめの機能(Counter API以外のタスク)をいくつかをやって,最後の1ヶ月で大きい機能(Counter API)を1つ をやりました.
一応雑に機能を紹介すると,
Counter API
マルチプロセスでfluentd動かしたとき,メトリクスとるのに使えるやつ
Data compression in buffer plugins and forward plugins
データを圧縮して操作できるようになり何かとリソースを節約できるやつ
New out_file plugin only for
secondary セクションのみで使えるシンプルな out_file
プラグイン
A CLI tool to read dumped event data
送信に失敗してダンプされた MessagePack形式のデータを読めるようなるやつ
Log rotation
Fluentd で log rotation できるようになるやつ
filter_with_time method in filter plugins
filter pluginで time をいじれるようにするやつ
Optimizing multiple filter calls
複数filter使用したときに高速化するやつ
Add event size to options in a forward protocol
eventのサイズつかって,内部の無駄な処理最適化するやつ
それぞれの説明を詳しく書いてもいいんですが長くなりすぎて誰も読まなくなると思うので,興味のある人は僕に会ったときにでも聞いてください(スライドを読んでもいいですが説明がアレ).
以下が最終発表スライドです.発表は英語でするはずだったんですが,僕のときだけUSの人たちがいなくて日本語で発表OKだったので,日本語が使えることに感謝しながら日本語で発表しました.
感想は?
まずは,Fluentd がいろいろ大変でした(語彙力).そもそも1回くらいしか Fluentd 使ったことなかったのでどうやって使われているか調べるところからはじまり,「あれ,これやばくない???」とか思いながらインターン初日を過ごしていました. @tagmorisさんのスライドにも書いてありますが,Rubyの黒魔術をふんだんに使って書かれていたので非常に読み応えがありました. コードを読む上で,Fluentd ソースコード完全解説 は参考になりました.結構古いので変わってしまったところもありますが,全体の流れを見るにはちょうどよかったです. キッっと睨んでるとわかってきたので大変なのは慣れることだなって感想になりました.
あとは,一番大きい機能の Counter API を merge まで持っていけなかったことが心残りです. 設計をしてレビューのフェーズで大量に時間を使ってしまったのがよくなかったなって感じです. 今の自分ができることと,できないことがはっきりしたのでそういう意味では良かったかなとおもっています.
前々から興味のあったミドルウェア開発を経験できたことは(しかもFluentdで,しかもTDで)とても幸運で,最高の経験だったと思っています. 開催されるかしらないですが,もし来年も開催されならとりあえず出してみると意外とインターン行けるかもしれないので,来年も学生の皆様はぜひ.
まとめ
特にまとめることもないですが,とても刺激的なインターンだったということが伝われば幸いです. 周りは全員超すごい人ばかりだったので,「(業務中自分の力の無さに)おちこんだりもしたけれど、私はげんきです。」という感じです. 社員のみなさん,同期の2人にはとてもお世話になりました.ありがとうございました.
付録1(愉快な仲間たち)
僕の他に2人,インターン同期がいました. 彼らが先に書いたブログがあって僕のより数倍いいのでそちらもぜひ.
@amay382 iPhone7とiOSのことをめちゃくちゃ煽る人(年下なのに優秀でつらい)
トレジャーデータでインターンしてた話 #td_intern - 水底
@takuti オタクかヤンキーかで言えばオタクの人(英語が引くほどうまい)
Treasure Dataインターンにみる機械学習のリアル #td_intern | takuti.me
2人とも機械学習(系?っていうの?あってる?)をやってたので,「インターンでは何やるの?」って聞いたんですけど,丁寧に教えてもらった割に何言ってるよくわからず「すごそう」くらいしか感想がなかったのできっとすごいんだろうなって思ってました.
付録2(食)
牡蠣が苦手だった僕も牡蠣が食べられるようになりました。
#td_intern 最高で具体的には苦手だった牡蠣が食べられるようになるくらい最高 https://t.co/K0BVQ8sfAN
— がんま (@ganmacs) 2016年9月30日
以下、 ログの重要性について真面目にディスカッションしていたときの図です!!!!
高速にメモをとるためのOrg Capture
Org Capture とはOrg-Modeのメモ取りツール(わかりやすく書いてある -> 色々 Org Capture する | Amrta )
以下のように書いておくと(キーバインドはなんだっていい)
(setq org-capture-templates '(("t" "Task" entry (file (expand-file-name (concat org-directory "/task.org"))) "* TODO %?\n %i\n %a\n %T") ("n" "note" entry (file (expand-file-name (concat org-directory "/notes.org"))) "* %?\n %a\n %T") ("r" "reading" entry (file (expand-file-name (concat org-directory "/reading.org"))) "* %?\n %a\n %T"))) (global-set-key (kbd "C-c C-q") 'org-capture)
C-c C-q
と押した時に以下のようなバッファが現れどれかを選択するとメモが簡単に書ける
Select a capture template ========================= [t] Task [n] note [r] reading ------------------------------------------------------------------------------- [C] Customize org-capture-templates [q] Abort
ただ問題があって,たかがメモをとるためにC-c C-q n
とおさないとメモを取れないのはだるすぎる(C-c C-q
の部分は好きに設定できるが最小でも2回必要.しかも画面が勝手に開いて視点がコロコロ変わり本当にだるい)
そこで以下のような関数を作った.これでC-M-=
を一度押せばいきなりメモをかけるようになった.
org-captureの第二引数を上記で記述したorg-capture-templates
のt
(Task)かn
(note)かr
(reading)にすることで指定のテンプレートを使用できる.
(defun org/note-right-now (content) (interactive "sContent: ") (org-capture nil "n") (insert content) (org-capture-finalize)) (global-set-key (kbd "C-M-=") 'org/note-right-now)
Dired でバイナリファイルを開くときに本当に開くか確認する何か
環境
動機
diredでバイナリとか開くときに本当に開いていいか確認してくれる何かが欲しい
— がんま (@ganmacs) 2015, 9月 24
Emacsでは写真やらPDFやらをEmacs内で見れるイッてる機能があります.
しかし,写真やらPDF開こうとすると数秒かかって非常に辛いです.
さらに,Diredを使っているとよく押し間違えてPDFを開いてしまい,数秒待ったあとkill-bufferするみたいなことによくなります.
これが非常に辛いのでなんとかしたいということで書きました.
実際
(defun util/same-ext? (file-path ext) "Check same exntion or not." (let ((file-ext (file-name-extension file-path))) (if file-ext (string= (downcase file-ext) ext)))) (defun util/chomp (str) (replace-regexp-in-string "[\n\r]" "" str)) (setq dired-open-whitelist '("c" "coffee" "clj" "el" "ex" "exs" "go" "h" "hs" "html" "js" "ml" "md" "rb" "yml" "scala" "slim" "scss")) (defun dired/binary? () (let ((cmd (format "nkf -g %s" (dired/filename-at-point)))) (string= "BINARY" (util/chomp (shell-command-to-string cmd))))) (defun dired/filename-at-point () (car (dired-get-marked-files 'no-dir))) (defun dired/directory? () (file-directory-p (car (dired-get-marked-files)))) (defun dired/include-whitelist? (filename whitelist) (if whitelist (or (util/same-ext? filename (car whitelist)) (dired/include-whitelist? filename (cdr whitelist))))) (defun dired-file-open-or-not () "File open if file type is directory or file exntion is in whitelist or file is not binary." (interactive) (let ((ext-lst dired-open-whitelist) (filename (dired/filename-at-point))) (if (or (dired/directory?) (dired/include-whitelist? filename ext-lst) (not (dired/binary?))) (dired-find-file) (if (yes-or-no-p (format "Do you really open? %s" filename)) (dired-find-file)))))
後は
(define-key dired-mode-map (kbd "C-f") 'dired-file-open-or-not)
何をしたか
開くのに時間がかかりそうなファイルを開いていいかどうかを聞くようにしました.
ファイルがBINARYかどうかをnkf
で確認してます.
しかし,毎回nkf
を叩くのは辛いので以下の条件の時はnkf
を叩かずそのままファイルを開いています.
- ディレクトリの時
- whitelistで定義された拡張子のファイルの時
感想
これを書いてたら何故か時間が消えていったが後悔はしていない
emacsからalcでの単語検索を楽にする
環境
コード
(defsubst marked-input () (when (use-region-p) (buffer-substring-no-properties (region-beginning) (region-end)))) (defun search-word-in-alc () (interactive) (let* ((cmd "open \"%s\"") (url (format "http://eow.alc.co.jp/search?q=%s" (or (marked-input) (read-shell-command "word: "))))) (shell-command-to-string (format cmd url)))) (global-set-key (kbd "s-E") 'search-word-in-alc)
ちなみにzshバージョンもある
function search-word-in-alc() { url="http://eow.alc.co.jp/search?q=" open "${url}$1" } alias e='search-word-in-alc'
エスケープ処理とか全くしてないので動きが怪しいこともある気がするけどそこそこ便利!!!
RubyでDSLを書く
Rackのコードを読んでたらDSL使ってたのでその部分.
instance_eval
を使ってBuilder
クラス内でblock
を実行するようにしている.
つまり以下のプログラムは,Builderのインスタンス内で呼ばれたことになってる.
map '/' do { 'Content-Type' => 'text/plain', 'status' => 200, 'body' => 'this is root!' } end
class Builder def initialize(&block) instance_eval(&block) if block_given? end def map(path, &block) set(:get, path, block) end def get(path) key = [:get, path] route_table[key].call end private def set(name, path, block) key = [name, path] route_table[key] = block end def route_table @route_table ||= {} end end app = Builder.new do map '/' do { 'Content-Type' => 'text/plain', 'status' => 200, 'body' => 'this is root!' } end end p app.get('/') # => {"Content-Type"=>"text/plain", "status"=>200, "body"=>"this is root!"}
まとめ
最高の夏
参考
Rubyでプラグイン機構を作る
rack/rack · GitHub のコード読んでてプラグイン(Rackの場合はバックエンドにどのサーバを使うか)の処理があったので取り出して書いてみた.
Rubyではクラスは定数なのでHandler
っていう名前空間の中の定数を探すだけでいい.
# sample1.rb module Handler class Base def call run end def run raise NotImplementedError end end class PlugA < Base def run p "called in A" end end end # sample2.rb module Handler class PlugB < Base def run p "called in B" end end end # runner.rb require_relative './sample1.rb' require_relative './sample2.rb' def run(class_name) klass = Handler.const_get(class_name) klass.new.call end ['PlugA', 'PlugB'].each do |e| run e end # => "called in A" # => "called in B"
githubの分割バージョンがある
感想
研究室にyogiboがあってそれに乗っかりながらだらだら読んでて、夏休みの朝に再放送のアニメ見てる感じだった