この間の三島Haskellで@karky7にcscopeを教えてもらったので、朝からいじっていたのだけどetagsとの違いがよく分からなかった。規模がでかいとこっちのほうがいいのだろうけど、.emacsにいちいち書かないといけないのが面倒くさそうだなと思ったが、virtualenvで作った仮想環境のlibを登録してしまえばいいのかなぁ。
Sass+Comapss用にEmacsをいじっていった結果、Flymakeによるリアルタイム構文チェックまでたどり着いて快適になった。livereloadを組み合わせるとさらによい。
更新を検知してリアルタイムに上のチェック、エラーがあれば該当行が赤く染まる。カーソルを該当行にのせると何がいけないのかがミニバッファに表示されるのでエラーが把握しやすい。
ちなみに下のスクリーンショットでは29行目にカーソルを合わせていて、「セレクタは一行に一つづつ書きなさい」とpythonのimportみたいなことを言われている。
こんな感じだったと思う。
gem install sass gem install compass gem install scss-lint
scss --checkとscss-lintを実行するスクリプトを用意する。ついでにflymake-cursorに対応させるために出力をいじるが、scss --checkの場合は--traceをつけると偶然にもflymake-cursorの書式に対応するので必要な一行目だけを出力させている。
#!/usr/bin/env python from subprocess import Popen, PIPE import sys for arg in sys.argv[1:]: if arg.endswith(".scss"): file = arg p1 = Popen(["scss", "--compass", "--trace", "--check", file], stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr = p1.communicate() print stderr.split("\n")[0] p2 = Popen(["scss-lint", file], stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr = p2.communicate() print stdout.replace(" - ", ": ")
scssコマンドをscsscheckersコマンドに変更するためにscss-sass-commandを上書きする。
;;; http://d.hatena.ne.jp/CortYuming/20120110/p1#20120110f1 (defun my-css-electric-pair-brace () (interactive) (insert "{")(newline-and-indent) (newline-and-indent) (insert "}") (indent-for-tab-command) (previous-line)(indent-for-tab-command) ) (defun my-semicolon-ret () (interactive) (insert ";") (newline-and-indent)) (add-to-list 'auto-mode-alist '("\\.\\(scss\\|css\\)\\'" . scss-mode)) (add-hook 'scss-mode-hook 'ac-css-mode-setup) (add-hook 'scss-mode-hook (lambda () (define-key scss-mode-map "\M-{" 'my-css-electric-pair-brace) (define-key scss-mode-map ";" 'my-semicolon-ret) (setq css-indent-offset 2) (setq scss-sass-command "~/bin/scsscheckers") (setq scss-compile-at-save nil) )) (load-library "flymake-cursor")
ここ二週間くらい試したこと
Flask+Sass-bootsrap+Coffeescriptなサイトを作っていて、Python,CoffeeScript,Sass全てに対してFlymakeがサポートしてくれるのでつまんないtypoとかのミスで時間をムダにすることがなくなった。
これを機会にWebデザイナー系のヒトもEmacsに入門すると楽しいと思いますよ!
こまるわーとか書いたんだけど、別件でscssのオプション調べてたら--compassっていうcompass用のオプション見つけたので、これを加えればいける。
scss-modeのソース調べたらscss-sass-optionsにオプション渡せばいいっぽいので、setqした。
(add-hook 'scss-mode-hook (lambda () (define-key scss-mode-map "\M-{" 'my-css-electric-pair-brace) (define-key scss-mode-map ";" 'my-semicolon-ret) (setq css-indent-offset 2) (setq scss-sass-options '("--compass")) (setq scss-compile-at-save nil) (flymake-mode t) ))
あとはConfigulation Errorでしょっちゅう死ぬので以下の設定は追加しておいたほうがよい。
(defadvice flymake-post-syntax-check (before flymake-force-check-was-interrupted) (setq flymake-check-was-interrupted t)) (ad-activate 'flymake-post-syntax-check)
インストールは普通にlist-packageで。
設定はscss-mode設定 / 牌語備忘録を参考にして、rbenvで入れたscssにパスを通しておいた。
scssを普通に使っているぶんにはなかなか快適だけど、Compassと一緒に使うと困る。
例えばcompassのblueprintを使いたい場合、importのところでコケる。
自分でscss叩いてみると
$ scss --check sass/screen.scss
Syntax error: File to import not found or unreadable: blueprint/reset.
importできてないっていうエラー。まぁcompassで挿入されるから実体がないのはしょうがないけど、scss --checkでエラーが発生したところで終了するのも困る。全てのエラーを補足するようになっていればいいのにと思ったりもするが。flymakeの意味無いじゃん。
compassコマンドのほうに構文チェック用のオプションないかなぁと見てみても、作成されたcssのバリデーターくらいしか用意されていないみたいだ。createした時にファイルを用意してくれるオプションでもいいんだけど。
というわけで、他のCompass使いの人達はどうやって構文チェックしているんだろうか?
検索かけてもほとんどヒットしないんだよなぁ
10022013 Emacs
etagsに再帰的に探索するオプションがないので面倒くさかったんだが、eshellを使えば解決することが分かって快適になった。
例えばFlaskだったらM-x eshellでeshellを立ちあげて、flaskのディレクトリで
etags **/*.py
と打てばよい。
eshellは常に一つ立ちあげておこうかな。
@karky7に教えてもらったEmacsのタグジャンプでRedmineの中を探索するのが楽になったが、etagsはHaskell対応していない。
これは困ったとフグったところ、hasktagsをみつけて解決。
hakyllのソースで
hasktags -e .
ってやってTAGSファイルを作ったら、Emacsでタグジャンプできる。
25112012 Emacs
昨日Gentoo Linuxの布教活動に来ていた@karky7にEmacsのタグジャンプの便利さを教えてもらったので、僕もちょっと使ってみようかなと。
ちょうどredmineの中を読んでいるのでappディレクトリで
etags */*.rb */*/*.rb
と打つとTAGSファイルができて(etags -f rb -Rとか叩けないんだろうか?)タグジャンプができるようになるのでM-.で探索しつつM-*で元の場所に戻るということが簡単にできるようになっていい感じ。
RoRみたいなフレームワークは行きつ戻りつすることが多いのでタグジャンプを使えばコードを追いかける効率が上がりそうだ。anythingとかhelmでも使えるようなのであとで設定してみる。
19112012 Emacs
Emacs RocksのEpisode 01: From var to thisを見ていて、C-sすると自動的に検索開始時点の位置がマークされることを知った。
ということはC-x C-xで戻れるってことじゃないかと。
他にはexpand-regionってのが便利そうだったので、入れた(list-packagesで選択できる)。
18112012 javascript Emacs coffeescript Ti
犬が早朝から吠えたので4時に叩き起こされたが、タイムラインを追いかけていたらAlloy with CoffeeScript のお誘いというこれは!というエントリがあがっていたので、早速誘われてみた。尚、jsとcoffeeは一緒のディレクトリに置いておくのが好みなので@k0sukeyのオリジナルなjmkに変更をくわえてあります。
Titanium Mobile iPhone/Androidアプリ開発入門のストップウォッチを参考にしました。
本書ではui.jsという1つのファイルで完結していますがAlloyのようなMVCフレームワークを使ったほうがコードの見通しは良くなると思います。
$ titanium create stopwatch # 対話でターゲットデバイスやapp-id設定 $ cd stopwatch $ alloy new # alloyのひな形作成 $ alloy generate jmk
stopwatch/app/alloy.jmkを以下のように書きなおす。これでapp/controller のcoffeeファイルはalloy compileでコンパイルされるようになります。
task("pre:compile", function(event,logger) { var wrench = require("wrench"), fs = require("fs"), path = require("path"), controller_root = event.dir.controllers, coffee = require("coffee-script"); wrench.readdirSyncRecursive(controller_root).forEach(function(controller){ if (controller.match("coffee$")) { fs.writeFileSync( path.join(controller_root,controller.replace("coffee", "js")), coffee.compile( fs.readFileSync(path.join(controller_root, controller)).toString(), { bare: true })); } }); }); task("post:compile",function(event,logger){ });
あとは普通に。
app/views/index.xml
<Alloy> <TabGroup> <Tab id="tab1" icon="dark_clock.png" title="ストップウォッチ"> <Window id="window1" title="ストップウォッチ"> <Label id="label"> 00:00:00.000 </Label> <Button id="button"> Start </Button> </Window> </Tab> <Tab id="tab2" icon="dark_info.png" title="使い方"> <Window id="window2" title="使い方"> <WebView url="howto.html"> </WebView> </Window> </Tab> </TabGroup> </Alloy>
/app/styles/index.tss
{"Window": { "barColor": "#000", "backgroundColor": "#000" }, "Tab": { "backgroundColor": "#000" }, "#label": { "color": "#fff", "width": "auto", "height": "auto", "font": { "fontSize": 40, "fontWeight": "bold" } }, "#button": { "color": "#000", "width": 150, "height": 40, "bottom": 30 }}
webview用のhtmlは /app/assets/iphone/howto.htmlに
<html> <head> <title>使い方</title> </head> <body> <h1>使い方</h1>このサンプル は<a href="http://www.amazon.co.jp/dp/479803231X">Titanium Mobile iPhone/Androidアプリ開発入門</a>のストップウォッチのサンプルをAlloyで 書きなおしてみたものです。 <img src="http://ec2.images-amazon.com/images/I/41jDZ5IY01L._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU09_.jpg"/> </body> 興味を持ったら購入して読んでみるとよいと思いますよ。 </html>
最後にcoffeeをapp/controllers/index.coffeeに
started =false intervalID = null startStopwatch = -> $.label.text = "00:00:00.000" startTime = new Date() _updateTimer = -> u_sec = 1000 u_min = 60 * u_sec u_hour = 60 * u_min now = new Date() diff = now - startTime hour = Math.floor(diff/u_hour) min = Math.floor((diff - hour*u_hour)/u_min) sec = Math.floor((diff - hour*u_hour - min*u_min)/u_sec) msec = diff / u_sec $.label.text = ("0" + hour).slice(-2) + ":" + ("0" + min).slice(-2) + ":" + ("0" + sec).slice(-2) + "." + ("00" + msec).slice(-3) intervalID = setInterval(_updateTimer, 3) return $.button.addEventListener 'click', -> if started clearInterval(intervalID) $.button.title = "Start" started = false else startStopwatch() $.button.title = "Stop" started = true return $.index.open()
$ alloy run
Let's Enjoy!