2011/11/28

2011/11/28

プロシュート兄貴

「書いてみたい」…そんな言葉は使う必要がねーんだ。                                                                                                                        
なぜなら、プログラマや、プログラマの仲間は、
その言葉を頭の中に思い浮かべた時には!
実際にプログラムを書いちまって、もうすでに終わってるからだッ!
だから使った事がねェーッ。

オマエもそうなるよなァ~~~、プログラマなら…
わかるか?オレの言ってる事…え?

『書いてみた』なら、使ってもいいッ!


これを読んでプロシュート兄貴を思い出したので。
「興味がある」「勉強したい」「作ろうと思ってる」。ぐずぐず言う前(もしくは言った後)に、ハローワールドからでいいから、コードをひとつ書いて公開すればいい。
プロシュート兄貴の言う通りにやるのはハードルたけぇーなー。

ジョジョの奇妙な冒険 52 (ジャンプ・コミックス)

terminalから輝度を調節

ubuntu 11.10, thinkpad x1
% brightness 10
ソースはこちら
#!/bin/sh
if [ $# -eq 0 ]; then
echo 'Usage: brightness <num 1 - 15>' 1>&2
exit 1
fi
sudo su -c "echo $1 > /sys/class/backlight/acpi_video0/brightness"
view raw brightness.sh hosted with ❤ by GitHub




詳解 シェルスクリプト

2011/11/27

2011/11/27

明日早起きなのに。。

terminalから音量調節(ubuntu, amixer)

% amixer set Master 60%
ubuntu11.10のunityだとthinkpad x1のキーボードの右側にある音量調節ボタンで調節できた。けど、stumpwmだとmute、unmuteしかできなかったので調べた。

コマンドにしとく。ソースはこちら
% volume 70
#!/bin/sh
if [ $# -eq 0 ]; then
echo 'Usage: volume <num 0 - 100>' 1>&2
exit 1
fi
amixer set Master on "$1"%
view raw volume.sh hosted with ❤ by GitHub


参考



2011/11/26

2011/11/26

2011/11/22

2011/11/20

2011/11/20

シェルスクリプトで適当なcsvを作る

いつもはgoshで作るけど、シェルスクリプトで簡単に作れた話。
for i in {1..12}
do
  echo '' > hoge$i.csv
  for j in {1..30}
  do
    echo $i$j','`uuidgen`','$RANDOM'\n' | sed 's/ //g' | sed '/^$/d' >> hoge$i.csv
  done
done


UNIXという考え方―その設計思想と哲学

cygwinでwindowsのアプリケーションを実行する

昔きくちゃん先生に書いてもらったヤツ。
$ start doc/hoge.pdf
# adobe reader でPDFが開く
とか
$ start .
# explorerが開く
$ start pic/fuga.png
# 画像ビューワで画像が開く
といった感じ。
で、そのstartってのはこれ。
 #!/bin/sh
`cygpath -S -u`/cmd /c start `echo "$*" | xargs -n 1 cygpath -w`
「それcygstartでできるよ」って言われそうだけど、なぜか会社のPCでcygstartが動かない、

関連



UNIXという考え方―その設計思想と哲学

vimで選択範囲の文字数

:'<,'>s/./&/gn
メモ

Vimテクニックバイブル ~作業効率をカイゼンする150の技

git

仕事でもプライベートでも使ってきたけどなかなかちゃんと使いこなせない。
それでもすごく便利。
これ知らんかったなー。
--no-ff フラグは、たとえマージがfast-forwardで実行できるとしても、新しいコミットオブジェクトを作成する。これは、履歴にフィーチャーブランチが存在したという情報を失うの\ を避けるのと、機能の追加に使った全てのコミットをひとまとめにしておける。


追記



Gitによるバージョン管理

.stumpwmrcさらし

StumpWMは入れただけでほとんど使っていなかった。
しばらく使ってみたら快適だったので気になるところだけ.stumpwmrcを書いてみた。
今後活躍の機会が増えるかも。ソースはこちら
(in-package :stumpwm)
;;
;; settings
;;
(set-focus-color "DarkRed")
(set-unfocus-color "black")
(set-win-bg-color "black")
(set-fg-color "white")
(set-bg-color "black")
(set-border-color "DarkRed")
(set-normal-gravity :center)
(set-prefix-key (kbd "C-q"))
(setf *startup-message* nil
*input-window-gravity* :center
*time-format-string-default* "%Y/%m/%d(%a) %H:%M"
*message-window-timer* 1
*mouse-focus-policy* :sloppy
*normal-border-width* 0
*maxsize-border-width* 0
*transient-border-width* 1
*window-border-style* :thick)
(define-stumpwm-type :password (input prompt)
(let ((history *input-history*)
(arg (argument-pop input))
(fn (symbol-function 'draw-input-bucket)))
(unless arg
(unwind-protect
(setf (symbol-function 'draw-input-bucket)
(lambda (screen prompt input &optional errorp)
(let ((i (copy-structure input)))
(setf (input-line-string i)
(make-string (length (input-line-string i))
:initial-element #\*))
(funcall fn screen prompt i)))
arg (read-one-line (current-screen) prompt))
(setf (symbol-function 'draw-input-bucket) fn
*input-history* history))
arg)))
(defmacro define-sudo-command (name command &key output)
(let ((cmd (gensym)))
`(defcommand ,name (password) ((:password "sudo password: "))
(let ((,cmd (concat "echo '" password "' | sudo -S " ,command)))
,(if output
`(run-prog-collect-output *shell-program* "-c" ,cmd)
`(run-prog *shell-program* :args (list "-c" ,cmd) :wait nil))))))
;;
;; keys
;;
(define-key *root-map* (kbd "j") "move-focus down")
(define-key *root-map* (kbd "k") "move-focus up")
(define-key *root-map* (kbd "l") "move-focus right")
(define-key *root-map* (kbd "h") "move-focus left")
(define-key *input-map* (kbd "C-i") 'input-complete-forward)
(define-key *input-map* (kbd "C-m") 'input-submit)
(define-key *input-map* (kbd "C-h") 'input-delete-backward-char)
(define-key *input-map* (kbd "M-C-h") 'input-backward-kill-word)
(define-key *root-map* (kbd "M") "mode-line")
(define-key *root-map* (kbd "X") "xlock")
(define-key *root-map* (kbd "B") "battery")
;;
;; commands
;;
(defcommand chrome ()()
"run chromium-browser"
(run-or-raise "chromium-browser" '(:class "chrome")))
(defcommand ichrome ()()
"run chromium-browser"
(run-or-raise "chromium-browser --incognito about:blank" '(:class "chrome")))
(defcommand twicli ()()
"run chromium-browser(twicli)"
(run-or-raise "chromium-browser --app=http://twicli.neocat.jp/oauth/index.html" '(:class "chrome")))
(defcommand reload ()()
"reload rc file"
(stumpwm::load-rc-file))
(defcommand battery ()()
"show battery status"
(echo-string (current-screen)(run-shell-command "/home/valvallow/bin/battery" t)))
(defcommand xlock ()()
"exec xlock"
(run-shell-command "xlock -mode random"))
(define-sudo-command reboot "reboot")
(define-sudo-command shutdown "shutdown -h now")
view raw .stumpwmrc.lisp hosted with ❤ by GitHub




実践Common Lisp

バッテリーの状態を表示するシェルスクリプト(状態、パーセント、残り時間)

[charged|charging|discharging] [parcent] [time]
gnu screenのステータスラインとStumpWMのmode-lineに表示しようかと。
$  battery
discharging 19% 0:44
ソースはこちら
#!/bin/sh
current=`grep "remaining" /proc/acpi/battery/*/state | sed 's/[a-zA-Z: ]//g'`
total=`grep "design capacity:" /proc/acpi/battery/*/info | sed 's/[a-zA-Z: ]//g'`
rate=`grep "present rate:" /proc/acpi/battery/*/state | sed 's/[a-zA-Z: ]//g'`
charging=`grep "charging state:" /proc/acpi/battery/*/state | sed 's/[a-zA-Z ]*:[ ]*//g'`
if [ $rate -eq 0 ]; then
echo $charging
exit 0
fi
percent=`echo "100.0 * $current / (1.0*$total)" | bc`
hours=`echo "(1.0*$current) / $rate" | bc`
minutes=`echo "60.0 * $current / $rate - $hours * 60" | bc`
minutes_0=``
if [ $minutes -lt 10 ]; then
minutes_0=0
fi
echo ''$charging' '$percent'% '$hours':'$minutes_0$minutes
view raw battery.sh hosted with ❤ by GitHub


参考



詳解 シェルスクリプト

2011/11/17

2011/11/17

vimの行番号

行番号を非表示にするにはどうすんのかなーって。
:set number
:set nonumber
これ読んでみてーなー。 あとこっちも欲しい。必要ないかなーなんて思ってたけど、目次見たらすごかった。 ちなみにこれは持ってる。だいぶお世話になった。

Emacs Lispテクニックバイブル

gauche-library-directory探訪001:gauche/macroutil.scm

gaucheのライブラリをのぞいて、目についたものを書いていくシリーズ(謎

前回



gauche/macroutil.scm

前回の方法で移動したディレクトリのgaucheディレクトリから。macroutil.scmという目を引くファイルがあったのでのぞいてみた。xmac, xmac1というマクロが定義されていた。
$ rlwrap gosh
gosh> (gauche-version)
"0.9.2"
gosh> (use gauche.macroutil)
gosh> (xmac (let1 a 1 (print a)))
(let ((a 1)) (print a))
gosh> (xmac (xmac (let1 a 1 (print a))))
(unwrap-syntax (%macroexpand (let1 a 1 (print a))))
見ての通り%macroexpandマクロの結果がunwrap-syntaxに渡されている。こんなマクロがあったなんて知らなかった。ドキュメントを調べてみたらundocumentedだった。

プログラミングGauche

gauche-library-directory探訪000:はじめに

gaucheのライブラリをのぞいて、目についたものを書いていくシリーズ(謎
ライブラリならドキュメントを見れば済むんだけど、今回はライブラリのソースものぞいてみるということで。

準備

gaucheにgauche-library-directoryという手続きがある。 こんな感じ。
$ rlwrap gosh
gosh> (print (gauche-library-directory))
/usr/local/share/gauche-0.9/0.9.2/lib
今後しばらくのぞいていくのは上記のディレクトリ。ということでshellで以下のように移動する。
$ cd `echo '(print (gauche-library-directory))' | gosh`
まずはどこからのぞくか。次回に続く(?)

プログラミングGauche

2011/11/16

2011/11/16

最近の雑多なコマンド(gauche)

某所で見たTwitterのfollow関係を表示するスクリプトのコマンド版。
$ ./twitter-friendship valvallow hoge
#!/usr/local/bin/gosh
(use rfc.json)
(use rfc.http)
(use util.list) ; assoc-ref
(define (call-twitter-api api-uri username)
(receive (status header body)
(http-get "api.twitter.com"
(string-append api-uri username ".json"))
(when (equal? status "404")
(print #`",username not found.")
(exit 1))
(parse-json-string body)))
(define (get-followee-ids username)
(assoc-ref (call-twitter-api "/1/friends/ids/" username) "ids"))
(define (get-user-id username)
(assoc-ref (call-twitter-api "/1/users/show/" username) "id"))
(define (main args)
(let ((args (cdr args)))
(let ((username1 (if (null? args)
(symbol->string (read))
(car args)))
(username2 (if (or (null? args)
(null? (cdr args)))
(symbol->string (read))
(cadr args))))
(let ((uid1 (get-user-id username1))
(uid2 (get-user-id username2))
(ids1 (vector->list (get-followee-ids username1)))
(ids2 (vector->list (get-followee-ids username2))))
(let ((1->2 (find (pa$ = uid2) ids1))
(2->1 (find (pa$ = uid1) ids2)))
(print username1 (cond ((and 1->2 2->1) "<->")
(1->2 "->")
(2->1 "<-")
(else "|"))
username2))))))
プログレス付きのタイマーコマンド。結果はnotify-sendか何かに渡すということで。←変更が必要そう。←プログレスをエラーポートに出力するようにした。
$ ./progress-timer -t hoge -s 10s timer
$ notify-send `progress-timer -s 3s -t hoge fuga`
#!/usr/local/bin/gosh
(use srfi-13)
(use text.progress)
(use gauche.parseopt)
(define (usage)
(print "Usage: progress-timer [options ...] message")
(print " - t|title : default empty")
(print " - s|sleep : 3m = 3 minutes")
(print " 3s = 3 seconds")
(print " 3 = 3 milliseconds")
(print " defualt 0")
(print " - h|help : usage")
(exit 2))
(define (num-format cur max)
(format "~3d%" (round->exact (/. (* cur 100) max))))
(define (decompose-unit unit)
(let1 len (string-length unit)
(rxmatch-if (#/[0-9]+$/ unit)
(num)
(values (x->integer num) 'default)
(values (x->integer (string-take unit (- len 1)))
(string->symbol (string-drop unit (- len 1)))))))
(define (unit->millisecond unit)
(receive (num suffix)
(decompose-unit unit)
(* num (case suffix
((s) 1000)
((m)(* 1000 60))
(else 1)))))
(define (main args)
(let-args (cdr args)
((title "t|title=s" "timer")
(n "s|sleep=s" "0")
(h "h|help" => usage)
. rest)
(let ((p (make-text-progress-bar :header title
:header-width (+ (string-length title) 1)
:num-format num-format
:num-width 5
:max-value 100
:port (current-error-port)))
(interval (/ (unit->millisecond n) 100))
(message (and (not (null? rest))
(car rest))))
(dotimes (i 100)
(p 'inc 1)
(sys-nanosleep (* interval 1000000)))
(p 'finish)
(when message
(print message)))))


プログラミングGauche

2011/11/13

2011/11/13

shellからterminalの幅と高さを取得(tput)

$ tput cols
191
$ tput lines
44

tcpdump

$ sudo tcpdump -n -i wlan0

chromium proxy

preferenceからやるよりこっちが簡単
chromium-browser --proxy-server=proxy:port

gaucheでgoogleの非公開apiを使って天気を取得するコマンド

某所で掲題のようなgaucheのコードを見かけたのでコマンドにしてみた。
$ ./weather kumamoto
kumamoto:2011-11-12
condition:Cloudy
temp_f:60
temp_c:15
humidity:Humidity: 77%
icon:/ig/images/weather/cloudy.gif
wind_condition:Wind: E at 0 mph

day_of_week:Sat
low:52
high:73
icon:/ig/images/weather/mostly_sunny.gif
condition:Partly Sunny

day_of_week:Sun
low:46
high:70
icon:/ig/images/weather/mostly_sunny.gif
condition:Mostly Sunny

day_of_week:Mon
low:37
high:63
icon:/ig/images/weather/sunny.gif
condition:Clear

day_of_week:Tue
low:41
high:64
icon:/ig/images/weather/sunny.gif
condition:Clear
$ ./weather -j kumamoto
{"date":"2011-11-12","current":{"condition":"Cloudy","temp_f":"60","temp_c":"15","humidity":"Humidity: 77%","icon":"/ig/images/weather/cloudy.gif","wind_condition":"Wind: E at 0 mph"},"in_the_future":[{"day_of_week":"Sat","low":"52","high":"73","icon":"/ig/images/weather/mostly_sunny.gif","condition":"Partly Sunny"},{"day_of_week":"Sun","low":"46","high":"70","icon":"/ig/images/weather/mostly_sunny.gif","condition":"Mostly Sunny"},{"day_of_week":"Mon","low":"37","high":"63","icon":"/ig/images/weather/sunny.gif","condition":"Clear"},{"day_of_week":"Tue","low":"41","high":"64","icon":"/ig/images/weather/sunny.gif","condition":"Clear"}]}#% 
ソースはこちら
#!/usr/local/bin/gosh
(use srfi-1)
(use sxml.ssax)
(use sxml.sxpath)
(use rfc.http)
(use rfc.json)
(use gauche.parseopt)
(define (usage)
(print "Usage: weather [options ...] city-name")
(print " - c|city : city name")
(print " - j|json : print json format")
(print " - h|help : print usage")
(exit 2))
(define (get-weather-xml city)
(receive (status head body)
(http-get "www.google.com" (string-append "/ig/api?weather=" city))
(ssax:xml->sxml (open-input-string body) '())))
(define (print-weather weather)
(for-each (^e (display (car e))
(display ":")
(print (cadr (cadadr e))))
(cdr weather))
(newline))
(define (weather->alist weather)
(map (^e (cons (x->string (car e))
(x->string (cadar (cdadr e)))))
(cdr weather)))
(define (weathers->json date weathers)
(construct-json
(list (cons "date" date)
(cons "current" (weather->alist (car weathers)))
(cons "in_the_future" (list->vector (map weather->alist (cdr weathers)))))))
(define (main args)
(let-args (cdr args)
((city "c|city=s")
(json "j|json")
(help "h|help" => usage)
. rest)
(let* ((city (or city (if (null? rest)
(symbol->string (read))
(car rest))))
(xml (get-weather-xml city))
(weathers (drop (car ((sxpath "/xml_api_reply/weather") xml)) 3))
(date (car ((sxpath "/xml_api_reply/weather/forecast_information/forecast_date/@data[1]/text()") xml))))
(if json
(write (weathers->json date weathers))
(begin (print city ":" date)
(print-weather (car weathers))
(for-each print-weather (cdr weathers)))))))
view raw weather.scm hosted with ❤ by GitHub


関連

プログラミングGauche

2011/11/12

2011/11/12

冠婚葬祭のひみつ

先日、未来の二つの顔 (創元SF文庫)を読み終わったので、母親から借りている本10冊くらいの中から適当に見繕って読んでいた。ここ数日風邪でダウンしていたので本を消化していたわけです。

で、その中に掲題の本があった。 これ面白い(笑)母親からも「これ面白いから読んでみ」ってことだった。まだ読み終わったわけではないけど頭っから掴みはOK。「へぇーへぇー」状態。

冒頭は結婚式についての話から入るんだけど、神前式のルーツは意外に新しくて明治33年に行われた、後の大正天皇の結婚式からというお話。当時は日清戦争と日露戦争の間の年で、国としては「神の国」のイメージを固め、富国強兵を推し進めたいという背景からだそう。
かといって、神前式の前は仏前式だったかというとそうでもなく、そもそも仏教的には開祖が妻帯者(親鸞)だった浄土真宗以外は出家者の結婚なんてもっての外だったらしい。なるほど。僧侶の妻帯が認められたのは明治以降だという。なんと仏前式の歴史もそうとう短いぞ。
じゃあ、寺は葬式だけやってたのか?というとそうではなく、江戸時代以前の寺は「葬式?んなもん在家にやらしときゃいんだよ」というスタンスだったらしく、葬式にも大して関わっていなかったんだって。(じゃあ何してたの?)

江戸時代以前は僧侶もフリーランスが多かったらしい。江戸時代に入ってからキリシタンの取締が強化され、寺が周辺住民の管理を行う役所みたいな役割を担うようになる。どこそこの誰々は○○寺の門徒(つまりキリシタンではないことの証明)、というような住民台帳ようなもの(宗門人別帳)の管理をするようになった。
で、これ以降、寺が葬式に関わるようになる。地域の寺にはそれぞれ本寺(本家的なもの)があり、定期的に上納金を払わないといけないわけ。で、地域の寺はどこからそのお金を集めるかというと、自分たちの下のヒエラルキーに位置する門徒。建前として仏壇や位牌や戒名という制度ができて、葬式と定期的な先祖供養を寺が行うんだから手数料と謝礼払うのは当然だよね?仏壇も買うよね?戒名ないとあの世でどんな目に合うかわかってる?という搾取システムができあがったんだと。面白ぇー。

これが冒頭。

以前から結婚式や葬式に対してモヤモヤした感覚があった。
新郎新婦ですらよく知らない、政治的な理由で出席しているどこの誰かわからない社会的地位だけは高い小汚いおっさんの超絶つまらん話をえんえん聞かされ、出席者の中に友人が少ないなーと思って聞いてみるとこれまた新郎新婦本人たちとは直接関係のないところの事情でわけのわからん老人たちがたくさん出席するため友人の招待を減らしたとかいう誰のためかわからない結婚式。
葬式は葬式で、「故人とはそんなに交流なかったけど、こないといけない気がした」みたいなアホ面下げた参列者がたくさんいる通夜。談笑ばかりしてたいして悲しそうでもない葬儀参列者。なんだんだ?と思っていたので、結婚式はともかく、葬式は本心から「故人に最後のお別れをしたい」と思える人の葬儀にだけ出席するようにしていた。それも最近は少し考えが変わって、行けば遺族が喜んでくれそうな場合は行くようにしようかなーと思うようになった。

話がそれた気がした。この本は、そういった感覚に何か裏付けを与えてくれそうな気がしたという話。

目次

  • 第1章 冠婚葬祭の百年
    • 明治の家と冠婚葬祭
    • 昭和の結婚と優生思想
    • 「冠婚葬祭入門」とその時代
    • 少婚多死の時代を迎えて
  • 第2章 いまどきの結婚
    • 今日的ウェディング狂想曲
    • 結婚式に招待されたら
    • 多様化する結婚の形
    • 変容する通過儀礼
  • 第3章 葬送のこれから
    • 現代葬儀の基礎知識
    • 死の準備はどこまで必要か
    • 身近な人の死に際して
    • 遺骨のゆくえ
  • もっと知りたい人のためのブックガイド


関連

そういえば読み終わってから感想書いてなかった。すごくおもしろかったので書こう。

冠婚葬祭のひみつ (岩波新書)

2011/11/09

2011/11/09

パインアメ1kgパック

わさおに教えてもらった。光速でポチった。
ちょっとしたクッションくらいの大きさ。


実用 Common Lisp よりデカくて分厚い。


こっちの方がお得みたいだけど。

追記

もっとわかりやすい比較にしてみた。


実用 Common Lisp (IT Architects’Archive CLASSIC MODER)

gaucheのtext.progressとtputコマンド(コマンド?)

gaucheにtext.progressなるモジュールがあることを知ったので、早速サンプルを動かしてみました。
ふと疑問に思ったのが、こういうことやる時ってcursesってヤツがいるんじゃないの?ってこと。ソース見てみたら、CRで行頭復帰してるだけだった。ウロコー!

こんな感じ。
#!/usr/local/bin/gosh

(use srfi-1)
(for-each (^i (format (current-output-port) "~a\r" i)
              (flush)
              (sys-select #f #f #f 50000))
          (iota 256))


Gauche-cursesとかGauche-ncursesはないかとググったら、メンテされてなさそうなのがひっかかった。ついでにChicken Schemeのeggを調べたらncursesがあった。あとで試してみよう。
で、curses拡張がないならどうしたらいいのか?調べてみたらtputなんてものがあるんですね。
試しにやってみたらこんな感じ。topコマンドを実行したときみたいな。
!/usr/local/bin/gosh

(use gauche.process)

(dynamic-wind
  (^ _ (run-process '(tput "civis"))
     (run-process '(tput "clear")))
  (^ _(do ((i 0 (+ i 1)))
          ((= i 256))
        (format (current-output-port) "~a\r" (make-list 100 i))
        (sys-nanosleep 10000000)
        (run-process '(tput "cup" 0 0))
        (flush)
        (sys-select #f #f #f 50000)))
  (^ _ (run-process '(tput "cnorm"))))

こりゃ便利だなーということで、以前作ったライフゲームをコマンドにしてみた。
$ ./lifegame2.scm -s 100 -w 30


プログラミングGauche

2011/11/05

2011/11/05

Linuxでterminalからguiを自動操作(automation)

こういうものがあった。 先日C#で作ってKPFで紹介した「windowを制御するdsl」と同じだ・・・。というかもっとちゃんとしてる。。 試しに無限にクリックし続けるshell script書いて、Love Languages?で試してみたり。
#!/bin/sh

while :
do
        xte 'mouseclick 1'
        sleep 0.3
done


詳解 シェルスクリプト

ておくlet

defmacro
(define-macro (teoku-let binds . body)
  `(let ,(map (lambda (ls)
               (cons (car ls)'("ておくれ"))) binds)
     ,@body))

(teoku-let ((wasao 68)
            (gentoo 'linux)
            (kumamoto "熊本"))
       (print wasao)
       (print gentoo)
       (print kumamoto))
;; ておくれ
;; ておくれ
;; ておくれ


syntax-rules
                                                                                                                     
(define-syntax teoku-let
  (syntax-rules ()
    ((_ () body ...)
     (let ()
       body ...))
    ((_ ((var val) x ...) body ...)
     (let ((var "ておくれ"))
       (teoku-let (x ...)
                  body ...)))))

(teoku-let ((wasao 68)
            (gentoo 'linux)
            (kumamoto "熊本"))
       (print wasao)
       (print gentoo)
       (print kumamoto))
;; ておくれ
;; ておくれ
;; ておくれ


プログラミングGauche

JavaベースのScheme

ググった結果をざっくり

JVM上のlisp

参考



プログラミングClojure

2011/11/01

最近の雑多なコマンド(gauche)

現実逃避駆動スクリプティング。使い捨てでいいんだけど、あえてコマンドにしました的な。

jsonとalistを相互に変換。
$ echo '(("a" . 1)("b" . 2)("c" . (("d" . #(1 2 3)))))' | json2alist -a 
{"a":1,"b":2,"c":{"d":[1,2,3]}}
$ echo '(("a" . 1)("b" . 2)("c" . (("d" . #(1 2 3)))))' | json2alist -a | json2alist
(("a" . 1) ("b" . 2) ("c" ("d" . #(1 2 3))))  
#!/usr/local/bin/gosh
(use rfc.json)
(use gauche.parseopt)
(define (usage)
(print "j2a [a|alist j|json h|help]")
(exit 0))
(define (main args)
(let-args (cdr args)
((alist "a|alist")
(json "j|json" #t)
(help "h|help" => usage)
. rest-args)
(let ((arg (and (not (null? rest-args))
(car rest-args))))
(write (cond (alist (or (and arg (construct-json-string (read-from-string arg)))
(construct-json (read))))
(json (or (and arg (parse-json-string arg))
(parse-json)))
(else (usage)))))))
view raw json2alist.scm hosted with ❤ by GitHub


csvをjsonに。csvをtemplate engineに渡すときにかましたり。
$ echo '1,2,3\n4,5,6\n7,8,9'| csv2json
"{\"title\":\"\",\"lines\":3,\"body\":[[\"1\",\"2\",\"3\"],[\"4\",\"5\",\"6\"],[\"7\",\"8\",\"9\"]]}"    
#!/usr/bin/env gosh
(use rfc.json)
(use text.csv)
(use file.util)
(use util.list)
(use gauche.parseopt)
(define (usage)
(print "usage: sv2j [options] <csv>")
(print "d|delimiter" " - default : ,")
(print "f|file" " - file path")
(print "a|alist" " - to alist")
(print "t|title" " - have a title row")
(print "l|limit")
(print "o|offset")
(print "h|help")
(exit 0))
(define (input->csv delim file)
(port->list (make-csv-reader delim)
(if file
(open-input-file file)
(standard-input-port))))
(define (cut-csv csv limit offset)
(define (cut csv f1 f2 n)
(if n
((if (and n (positive? n)) f1 f2) csv (abs n))
csv))
(cut (cut csv drop* drop-right* offset)
take* take-right* limit))
(define (csv->alist csv title limit offset)
(let* ((title (and title (list->vector (car csv))))
(body (list->vector
(map list->vector
(cut-csv (if title (cdr csv) csv)
limit offset)))))
(list (cons "title" (or title ""))
(cons "lines" (vector-length body))
(cons "body" body))))
(define (main args)
(let-args (cdr args)
((delimiter "d|delimiter=s" ",")
(file "f|file=s")
(alist "a|alist")
(title "t|title")
(limit "l|limit=i")
(offset "o|offset=i")
(help "h|help" => usage)
. rest)
(let ((limit (and limit (x->integer limit)))
(offset (and offset (x->integer offset))))
(let* ((csv (input->csv (string-ref delimiter 0) file))
(ls (csv->alist csv title limit offset)))
(write (if alist
ls
(construct-json-string ls)))))))
view raw csv2json.scm hosted with ❤ by GitHub


jsonからkeyを取得したり、指定したkeyの値を取得したり。
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -k                                           
a                                                                                                  
b                                                                                                  
c                                                                                                  
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -t                                            
object                                                                                             
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -l                                                
3                                                                                                  
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -e c                                              
{"d":[1,2,3]}                                                                                   
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -e c | pryon -e d                                   
[1,2,3]                                                                                         
$ echo '{"a":1,"b":2,"c":{"d":[1,2,3]}}' | pryon -e c | pryon -e d | pryon -i 2                      
3

#!/usr/local/bin/gosh
(use rfc.json) ; parse-json
(use util.list) ; assoc-ref
(use gauche.parseopt) ; let-args
(define (usage)
(print "usage: gson [-t | -l | -k | -e | -i] <json>")
(print " -t | type")
(print " -l | length")
(print " -k | keys")
(print " -e | extract")
(print " -i | index")
(print " -h | help")
(exit 0))
;;
;; print type
;;
(define-method print-type ((ls <list>))
(print "object"))
(define-method print-type ((vect <vector>))
(print "vector"))
;;
;; print keys
;;
(define (print-keys json)
(for-each (compose print car) json))
;;
;; print length
;;
(define-method print-length ((ls <list>))
(print (length ls)))
(define-method print-length ((vect <vector>))
(print (vector-length vect)))
(define-method print-length ((str <string>))
(print (string-length str)))
;;
;; extract
;;
(define (print-extracted-json json key)
(print-filtered-value assoc-ref json key))
;;
;; index
;;
(define (print-index-value json i)
(print-filtered-value vector-ref json i))
;;
;; util
;;
(define (print-filtered-value filter json . args)
(let1 val (apply filter json args)
(if (or (list? val)
(vector? val))
(construct-json val)
(write val))))
;;
;; main
;;
(define (main args)
(let-args (cdr args)
((-type "t|type")
(-length "l|length")
(-keys "k|keys")
(-extract "e|extract=s")
(-index "i|index=i")
(-help "h|help" => usage)
. rest)
(let ((json (parse-json (current-input-port))))
(cond (-type (print-type json))
(-keys (print-keys json))
(-length (print-length json))
(-extract (print-extracted-json json -extract))
(-index (print-index-value json -index))
(else (exit 0))))))
view raw pryon.scm hosted with ❤ by GitHub
最後のやつは、jshonってののライト版的ノリで。ちょっと便利。というかjshonがうまいこと動いてくれなかったので仕方なく。

プログラミングGauche

terminal で json pretty print

terminalからweb apiを呼んで返ってきたjsonを見るときに。pythonはだいたいどこでも入ってるし。
python -m json.tool
wget -O - http://foo:piyo@hogehoge.com/api/fuga | python -m json.tool

例えばこんな感じ。
% wget -O - "https://api.twitter.com/1/statuses/user_timeline.json?id=valvallow&count=1" 2> /dev/null | python -mjson.tool
[
    {
        "contributors": null,
        "coordinates": null,
        "created_at": "Tue Nov 01 15:04:22 +0000 2011",
        "favorited": false,
        "geo": null,  
        "id": 131386101536526337,
        "id_str": "131386101536526337",
        "in_reply_to_screen_name": "sasagawa888",
        "in_reply_to_status_id": 131385453638201344,
        "in_reply_to_status_id_str": "131385453638201344",
        "in_reply_to_user_id": 236352281,
        "in_reply_to_user_id_str": "236352281",
        "place": null,
        "retweet_count": 0, 
        "retweeted": false, 
        "source": "twicli", 
        "text": "@sasagawa888 \u305d\u3046\u3067\u3059\uff3e\uff3e\uff1b", 
        "truncated": false, 
        "user": {
            "contributors_enabled": false, 
            "created_at": "Mon May 14 04:57:45 +0000 2007", 
            "default_profile": false, 
            "default_profile_image": false, 
            "description": "S\u5f0f\u304c\u597d\u304d\u3002\u660e\u65e5\u304b\u3089\u672c\u6c17\u51fa\u3059\u3002\u306e\u3093\u3073\u308a\u751f\u6d3b\u3057\u305f\u3044\u3002", 
            "favourites_count": 2686, 
            "follow_request_sent": false, 
            "followers_count": 1648, 
            "following": true, 
            "friends_count": 1395, 
            "geo_enabled": false, 
            "id": 6023392,
            "id_str": "6023392",
            "is_translator": false,
            "lang": "ja",
            "listed_count": 163,
            "location": "kumamoto",
            "name": "\u3057\u3083\u308c\u3053\u3046\u3079\u4e59",
            "notifications": false,
            "profile_background_color": "FFFFFF",
            "profile_background_image_url": "http://a0.twimg.com/profile_background_images/655452/Half_docro.jpg",
            "profile_background_image_url_https": "https://si0.twimg.com/profile_background_images/655452/Half_docro.jpg",
            "profile_background_tile": false,
            "profile_image_url": "http://a0.twimg.com/profile_images/557761803/dokuro33whitebig_normal.JPG",
            "profile_image_url_https": "https://si0.twimg.com/profile_images/557761803/dokuro33whitebig_normal.JPG",
            "profile_link_color": "000000",
            "profile_sidebar_border_color": "000000",
            "profile_sidebar_fill_color": "D3D3D3",
            "profile_text_color": "000000",
            "profile_use_background_image": true,
            "protected": false,
            "screen_name": "valvallow",
            "show_all_inline_media": false,
            "statuses_count": 30993,
            "time_zone": "Tokyo",
            "url": "http://valvallow.blogspot.com/",
            "utc_offset": 32400,
            "verified": false
        }
    }
]
webならここがいい。

矩形スクリーンショット

$ gnome-screenshot --area

notify-sendでラーメンタイマーというかリマインダ(ubuntuおまけでcygwin+growl for windows)


ちょくちょくあるんですよ、n分後にアラートして欲しいとか、何かしらの処理が終了したら通知して欲しいとか。 そこでnotify-sendとmplayerでいい感じに通知してもらえたのでメモ。

例えば下記の場合、3分経ったら上の画像のようなアラートを表示して音楽を流してくれます。
$ sleep 3m && notify-send -i /your/icon/path/terminal.png 'noodle !!'  && mplayer /your/music/path/notify.ogg > /dev/null 2> /dev/null

長いコンパイル、デカいファイルのコピーなんかの時に仕込んでおくと便利そう。いい感じのaliasを設定しときたいですね。

cygwin

cygwinの場合は、growl for windowsがインストールされてい(てかつgrowlが常駐して)れば下記のようにできる。
$ sleep 3m ; /cygdrive/c/Program\ Files/Growl\ for\ Windows/growlnotify.exe /i: "c:\your\icon\path\notify.png" /t:"hoge" 'Ha!!' 


参考



追記

alertって名前でshellスクリプト書いてみた。sh -x ./alert でtrace情報っぽいのが出るんですね。
!/bin/sh
                                                                                                  
ICON="/your/icon/path/icon.png"
MUSIC="/your/music/path/music.png"
                                                                                                   
while getopts s:m: OPT
do
        case $OPT in
                "s" ) FLG_SLEEP="TRUE" ; VALUE_SLEEP="$OPTARG" ;;
                "m" ) FLG_MESSAGE="TRUE" ; VALUE_MESSAGE="$OPTARG" ;;
        esac
done 
                                                                                                   
if [ "$FLG_SLEEP" = "TRUE" ]; then
        sleep $VALUE_SLEEP
fi
if [ "$FLG_MESSAGE" = "TRUE" ]; then
        notify-send -i $ICON "$VALUE_MESSAGE"
fi
mplayer $MUSIC > /dev/null 2> /dev/null

以下のように実行すると、3秒後に音楽とともにgrowlっぽいものが表示される。
$ alert -s 3 -m 'Hello, world !!'


詳解 シェルスクリプト