- 平成22年7月14日(水) 16時48分40秒
-
区分
- ActiveRecord
-
報告者:
- chiba
WordPressのデータを一括でいろいろと変更する際には、SQLでいろいろすると思うのですが、もしかしてActiveRecordを使えたら割と便利だったりするのかな、ということでActiveRecordからWordPressのDBに接続してみたりしていました。
しかし、これは既に試してみている人が絶対いそうだなと思ったので軽くググってみたところ、やはり、そのものズバリがありました。
github: jystewart / wp_ar
こんな感じで使えます。
irb(main):254:0> WpUser.count
12
150行弱のコードですが、機械的に変換する作業には割と使えるかもしれないなと思いました。
自分も、CLSQLなどで同じようなものを組んでみたいです。
■
>View Comments
このページの上へ戻る
- 平成22年7月8日(木) 16時50分29秒
-
区分
-
-
報告者:
- chiba
隙があればlispを詰め込んで行きたい日々ですが、今回は一つのファイルを複数ファイルに分割する仕事です。
こういうのはやっぱりsed/awkの仕事だろう、と思うのですが、一つLISPでがんばりたいところ
具体的な仕事内容ですが、
- 複数のエントリーがまとめられた、複数の長いテキストファイルを入力とする
- エントリーの区切り文字は^_
- エントリーごとに1ファイルにして出力
というところです。
書き捨てな感じですが、
(dolist (file (directory "/var/tmp/foo/bar/big-*.txt"))
(dolist (mail (cl-utilities:partition-if
(mycl-util:curry #'string= "^_")
(kmrcl:read-file-to-strings file)))
(alexandria:with-output-to-file
(out (format nil "/var/tmp/result/~A" (gensym "foo-")))
(print out)
(dolist (line mail)
(write-line line out)))))
のように書いてみました。
軽く解説すると、
- ファイル読み込み1行を要素とするリストにする
- PARTITION-IFでリストの中身をデリミタで1ファイル1リストとして分割する
- 分割した要素1リストを1ファイルとして出力。名前が被らないようにGENSYMで名前をつける
という風にしてみました。
想像していたより短く書けたので満足です。
■
>View Comments
このページの上へ戻る
- 平成22年6月29日(火) 11時09分06秒
-
区分
- lisp
-
報告者:
- chiba
隙があればlispを詰め込んで行きたい日々ですが、今回はWordPressのデータをいじる仕事です。
仕事の内容ですが、WordPressにはカスタムフィールドという便利機能があり、ここに入力したデータが便利にページに表示されます。
このカスタムフィールド内のHTMLを大量に変更することになりました。
具体的には、
select * from wp_postmeta where meta_key = 'こんにちは画像';
で目的の内容が取得できるので、このテキストの内容を置換して同じ場所に戻してやる、ということになります。
SQL文を書いて色々すれば良いのですが、CLSQLを使ってみることにしました。
(asdf:oos 'asdf:load-op :clsql)
(in-package :clsql-user)
(connect '("localhost" "db" "wp" "")
:database-type :mysql)
(execute-command "set character_set_client='utf8'")
(execute-command "set character_set_connection='utf8'")
(execute-command "set character_set_results='utf8'"))
;; DBから読み出してSQLを出力
;; <a href=...>を<a target="_blank" href=...>に変更
(let ((ahref (ppcre:create-scanner "(<a)(\\s+)(href=.*)"))
(window.open (ppcre:create-scanner "window.open")))
(alexandria:with-output-to-file (out "/tmp/foo.txt")
(do-query ((meta_id post_id meta_key meta_value)
"select * from wp_postmeta where meta_key = 'こんにちは画像';")
(cond ((ppcre:scan "window.open" meta_value)
;; 既にwindow.openで開くような指定があるばあいはスルー
:nop)
('T (let ((new-val
(ppcre:regex-replace
ahref
meta_value
(lambda (match &rest registers)
(declare (ignore match))
(destructuring-bind (a b c) registers
(format nil
"~a target=\"_blank\"~a~a"
a
b
c)))
:simple-calls 'T)))
(format out
"update wp_postmeta set meta_value = '~A' where meta_key = 'こんにちは画像' and post_id = ~A;~%"
new-val
post_id)))))))
内容としては、
- CLSQLを準備
- MySQLに接続
- 文字コードをUTF-8に設定(任意)
- select文を発行して結果をリストで受けとる
- リストの内容から、目的の文を取り出しPPCRE(Common LispのPerl正規表現互換パッケージ)で処理
- ファイルにSQL文を書き出し
今回は目的のSQLサーバーに直接接続するのが面倒だったので、ファイルにSQL文を書き出しましたが、CLSQLで接続して変更ということも勿論できます。
また、"select〜"みたいなことになっていますが、(select [...])のようにも書けるようです。
色々適当ですが、とりあえず目的は達成できました
■
>View Comments
このページの上へ戻る
- 平成22年6月22日(火) 10時13分38秒
-
区分
- LISP
-
報告者:
- chiba
隙があればlispを詰め込んで行きたい日々ですが、今回はウェブ上のHTMLの内容確認の仕事です。
具体的には、h1、title、meta keywords、meta descriptionが記述されたCSV形式のファイルがあり、これの内容どおりになっているかをチェックする、という内容。
とりあえず、HTMLのタグの抜き出しには、Drakmaと、closure-htmlを使って、欲しいタグの内容を抜き出す関数を作成してみました。
|((:h1 ...) (:keywords ...) (:description ...) (:title ...))|という変な名前ですが、title keywords description h1を抜き出して返す関数名が思い付かなかったので返す結果の形をそのまま名前にしています。Common Lispは名前に記号も使えるので思考が停止したときに便利ですね。
(defun |((:h1 ...) (:keywords ...) (:description ...) (:title ...))| (url)
(let* ((page (drakma:http-request url))
(doc (chtml:parse page (cxml-stp:make-builder)))
(ans () ))
(stp:do-recursively (a doc)
(when (and (typep a 'stp:element)
(or (string-equal (stp:local-name a) "title")
(string-equal (stp:local-name a) "meta")
(string-equal (stp:local-name a) "h1")))
(let* ((kwd-or-dsc (cond ((string-equal (stp:attribute-value a "name")
"description")
`(:description
,(stp:attribute-value a "content")))
((string-equal (stp:attribute-value a "name")
"keywords")
`(:keywords
,(stp:attribute-value a "content")))))
(tag (intern (string-upcase (stp:local-name a)) :keyword))
(svalue (stp:string-value a))
(tem () ))
(cond ((and (string= "" svalue)
(eq :meta tag))
:nop)
('T (push svalue tem)
(push tag tem)))
(when kwd-or-dsc
(push (cadr kwd-or-dsc) tem)
(push (car kwd-or-dsc) tem))
(and tem (push tem ans))
)))
ans))
この|((:h1 ...) (:keywords ...) (:description ...) (:title ...))|を使って
(progn
(print '////////////////////////////////////////////////////////////////)
(dolist (x (fare-csv:read-csv-file "foo.csv"))
(destructuring-bind (url title kwd dsc h1) x
(let* ((url (ppcre:regex-replace "://www.example.com" ;CSVファイルのURL
url
"://www.example.net")) ;実際のサーバーのURL
(q (|((:h1 ...) (:keywords ...) (:description ...) (:title ...))| url)))
(flet ((*check (var key)
(string= var (second (assoc key q)))))
(cond ((and (*check h1 :h1)
(*check kwd :keywords)
(*check dsc :description)
(*check title :title))
:nop)
('t
(flet ((frob (var key)
(list key
(if (*check var key)
:ok
(list :ng var (second (assoc key q)))))))
(print '*******************************************)
(print url)
(print (frob h1 :h1))
(print (frob kwd :keywords))
(print (frob dsc :description))
(print (frob title :title))))))))))
のように殴り書きしてみました。キーワードが一致していないと
////////////////////////////////////////////////////////////////
*******************************************
"http://www.example.com/foo/bar"
(:H1 (:NG "こんにちは" "Routing Error"))
(:KEYWORDS (:NG "なるほど" NIL))
(:DESCRIPTION (:NG "なんのことですか?" NIL))
(:TITLE (:NG "mjd!" "Action Controller: Exception caught"))
...
のような結果がREPLに出てきます。
なんだか長いですけど、Common Lispで書いても実行を確認しながら書けるので、そんなに大変でもありません。
■
>View Comments
このページの上へ戻る
- 平成22年6月12日(土) 00時08分23秒
-
区分
- LISP
-
報告者:
- chiba
こんにちは、chibaです。
今回もネタがないのでLISPネタです。
日常の作業では、テキストファイルを加工することが割とあったりすると思いますが、そういう時には、sedや、awkって便利ですよね。
ちょっとした一行野郎が大活躍、ということは結構あると思います。
自分もそういう一行野郎が好きではあるのですが、いやしかし、隙があればlispを詰め込んで行きたい。
最近もsedを使いたくなるようなHTMLの編集作業に遭遇しました。
「指定したディレクトリ以下に含まれるすべてのHTMLファイルの<div class="foo"から、</div>の間を、用意したテキストファイルの内容と置き換える。」
という仕事です。
sedで一発だろうと思いましたが、とりあえず、Common Lispで書いてみました。
(LOOP :FOR FILE :IN
(DIRECTORY "/tmp/foo/**/*.html")
:DO
(WITH-OPEN-FILE (IN FILE)
(WITH-OPEN-FILE (OUT (FORMAT NIL "~A.new.html" (PATHNAME FILE))
:DIRECTION :OUTPUT
:IF-EXISTS :SUPERSEDE
:IF-DOES-NOT-EXIST :CREATE)
(LOOP :WITH OPEN
:FOR LINE := (READ-LINE IN NIL NIL) :WHILE LINE
:DO (PROGN
(WHEN (SEARCH "" LINE)
(SETQ OPEN 'T))
(COND ((AND OPEN (SEARCH "
" LINE))
(SETQ OPEN NIL)
(WITH-OPEN-FILE (IN2 "g000001/foo.html")
(LOOP :FOR LINE := (READ-LINE IN2 NIL NIL) :WHILE LINE
:DO (WRITE-LINE LINE OUT))))
((NOT OPEN)
(WRITE-LINE LINE OUT)))
)))))
気分は一行野郎なのでコードもいきあたりばったりで汚ないです。
これで仕事は片付いたのですが、率直な感想として、sedに比べると書くのがかなりめんどくさいです。(一切ライブラリを使ってないということもありますが…)
こんなにめんどうでは、やっぱりCommon Lispよりsedを使ってしまいます。
いやしかし、こういう道具を沢山書き溜めておいて、必要なときにさっと出せるようになれば、そのうちsedやawkではなく、自然にCommon Lispを使うようになるかもしれません。
ということで、若干無理はあるものの、コードを纒めて次の機会に備えておくことにしました。
(DEFUN SED (START-PAT END-PAT NEW
&KEY (IN *STANDARD-INPUT*) (OUT *STANDARD-OUTPUT*))
(LOOP :WITH OPEN
:FOR LINE := (READ-LINE IN NIL NIL) :WHILE LINE
:DO (PROGN
(WHEN (SEARCH START-PAT LINE)
(SETQ OPEN 'T))
(COND ((AND OPEN (SEARCH END-PAT LINE))
(SETQ OPEN NIL)
(WRITE-LINE NEW OUT))
((NOT OPEN)
(WRITE-LINE LINE OUT))))))
(DEFUN MAP-FILE-INTO (FILES FUNCTION)
(LET ((TEMPNAME-SUFFIX (GENSYM "TEMP-FILE-")))
(DOLIST (FILE FILES)
(LET ((TEMPFILE-NAME (FORMAT NIL "~A_~A" FILE TEMPNAME-SUFFIX)))
(WITH-OPEN-FILE (IN FILE)
(WITH-OPEN-FILE (OUT TEMPFILE-NAME
:DIRECTION :OUTPUT
:IF-EXISTS :SUPERSEDE
:IF-DOES-NOT-EXIST :CREATE)
(FUNCALL FUNCTION IN OUT)))
(RENAME-FILE TEMPFILE-NAME FILE)))))
この2つを使えば、今回の仕事は、
(MAP-FILE-INTO (DIRECTORY "**/*.html")
(LAMBDA (IN OUT)
(SED "<div class='foo'>"
"</div>"
(KL:READ-FILE-TO-STRING "foo.txt")
:IN IN
:OUT OUT)))
のように書けます。
いまのところぱっとしませんが、そのうちCommon Lispだけでテキスト仕事は片付けられるようになることを目指します!
■
>View Comments
このページの上へ戻る
- 平成22年6月2日(水) 16時22分57秒
-
区分
- Emacs
-
報告者:
- chiba
こんにちは、chibaです。
今回もネタがないのでEmacsネタです。
Dylanのマクロについての文献:
http://people.csail.mit.edu/jrb/Projects/dexprs.pdf
を読んでいて、XMLや、LISPは、Skeleton Syntax Tree Representationsに分類されるというのを読んで、そうか、HTMLも簡単にマクロ書けたりするのかもと思ったのでEmacs Lispでちょっと試してみました。
(defun split-id-or-class (string)
(let ((elts (split-string string "[\\.#]")))
(if (cdr elts)
elts
string)))
(defmacro defhtmltag (tag)
(let* ((tag-str (symbol-name tag))
(tags (split-string tag-str "[\\.#]"))
(tag-name (car tags))
(attr (cadr tags)))
`(defmacro ,tag (&rest body)
`(list ,(concat
"<"
,tag-name
(apply #'concat
(cond ((find ?. ,tag-str)
(list " class=\"" ,attr "\""))
((find ?# ,tag-str)
(list " id=\"" ,attr "\""))
('T (list ""))))
">")
,@body
,(concat "</" ,tag-name ">")))))
(defun flatten (lis)
(cond ((atom lis) lis)
((listp (car lis))
(append (flatten (car lis)) (flatten (cdr lis))))
(t (append (list (car lis)) (flatten (cdr lis))))))
(defmacro with-html-output-to-string (&rest body)
`(reduce (lambda (x y) (format "%s%s" x y))
(flatten (list ,@body))))
使い方としては、
(defhtmltag li.foo)
のようにすると、
(list "<li>" "こんにちは" "</li>")
のようなものにマクロが展開されるので、リストの入れ子を平坦にして一つの文字列に繋げれば完成です。
ちょっと込み入ったところだと
(defhtmltag table)
(defhtmltag tbody)
(defhtmltag td)
(defhtmltag tr)
(defun list-to-table (list)
(table
(tbody
(mapcar (lambda (x)
(tr
(mapcar (lambda (y) (td y))
x)))
list))))
(insert
(with-html-output-to-string
(list-to-table '((foo bar baz quux)
(1 2 3 4)
(z z z z)))))
;=> <li class="foo"><li class="foo"><li class="foo"><li class="foo">foo</li><li class="foo">bar</li><li class="foo">baz</li><li class="foo">quux</li></li><li class="foo"><li class="foo">1</li><li class="foo">2</li><li class="foo">3</li><li class="foo">4</li></li><li class="foo"><li class="foo">z</li><li class="foo">z</li><li class="foo">z</li><li class="foo">z</li></li></li></li>
ということもできます。
ちなみに、マクロ展開でHTML書くって新しいかも!と思いましたが、別にマクロにしなくても関数でも書けることに今気付きました…
とりあえず、もし、HTMLにマクロがあったとしたらLISPと似た感じになるのかなあという印象は持ちました。
■
>View Comments
このページの上へ戻る
- 平成22年5月25日(火) 16時09分08秒
-
区分
- Emacs
-
報告者:
- chiba
こんにちは、chibaです。
今回もネタがないのでEmacsネタです。
日常のちょっとしたテキストの編集作業なのですが、
app/views/top/foo.html.erb
app/views/shared/_foo.html.erb
app/views/shared/foo.html.erb
app/views/top/_foo.html.erb
app/views/shared/foo.html.erb
app/views/layouts/application.html.erb
config/links/foo.html.erb
public/images/shared/foo.jpg
のようなテキストをスペース区切りの一行にまとめる必要に迫られました。
ここはEmacsで、改行をスペースに置換してやれば良いんじゃないかと思いますが、いや、ここは踏ん張ってlispを書いてゆきたいと思い、
(mapconcat (lambda (x) (format "%s" x))
'(
app/views/top/foo.html.erb
app/views/shared/_foo.html.erb
app/views/shared/foo.html.erb
app/views/top/_foo.html.erb
app/views/shared/foo.html.erb
app/views/layouts/application.html.erb
config/links/foo.html.erb
public/images/shared/foo.jpg
)
" ")
のようなものを書いて、式のにカーソルを持っていって、C-u C-x C-eです。
そうすると、式の後ろに
=> "app/views/top/foo.html.erb app/views/shared/_foo.html.erb app/views/shared/foo.html.erb app/views/top/_foo.html.erb app/views/shared/foo.html.erb app/views/layouts/application.html.erb config/links/foo.html.erb public/images/shared/foo.jpg"
のようなものが挿入されます。lambdaって書けて良かったですよね。
次に、
A app/views/top/foo.html.erb
M app/views/shared/_foo.html.erb
M app/views/shared/foo.html.erb
M app/views/top/_foo.html.erb
? app/views/shared/foo.html.erb
M app/views/layouts/application.html.erb
A config/links/foo.html.erb
M public/images/shared/foo.jpg
のようなテキストでファイル名の部分だけ、一行にスペース区切りでつなげる必要に迫られました。
ここは、Emacsで、kill-rectangleでしょうか。いや、ここは踏ん張ってlispを書いてゆきたいと思い、
(apply #'concat
(loop for (x y) on
'(
A app/views/top/foo.html.erb
M app/views/shared/_foo.html.erb
M app/views/shared/foo.html.erb
M app/views/top/_foo.html.erb
? app/views/shared/foo.html.erb
M app/views/layouts/application.html.erb
A config/links/foo.html.erb
M public/images/shared/foo.jpg
)
by #'cddr
collect (format "%s " y))
)
のようなものを書き、上と同じく、eval-last-sexp すると
"app/views/top/foo.html.erb app/views/shared/_foo.html.erb app/views/shared/foo.html.erb app/views/top/_foo.html.erb app/views/shared/foo.html.erb app/views/layouts/application.html.erb config/links/foo.html.erb public/images/shared/foo.jpg "
という文字列が得られます。
なるほど、これは、shell-command-on-regionで、awk '{if($1=="M"){printf("%s ", $2);}}'とかしている場合ではないですね。
Emacs便利です。
■
>View Comments
このページの上へ戻る
- 平成22年5月20日(木) 11時19分38秒
-
区分
- Emacs
-
報告者:
- chiba
こんにちは、chibaです。
今回もネタがないのでEmacsで遊んでいたネタを。
Googleは、便利にグラフを書けるAPIであるGoogle Chart APIというのを提供しています。
URLを指定するだけで、グラフが書けたり、QRコードが書けたり色々便利なものですが、数値のリストからスタックされた棒グラフを書いてみようと思ったので、ちょっと遊んでみました。
(defun* gchart-stack-bar-chart-url (data &key (style :horizontal))
(let ((len (length data)))
(concat
"http://chart.apis.google.com/chart?"
"cht=b" (case style
(:horizontal "hs")
(otherwise "vs"))
"&chd=t:"
(let* ((totals (mapcar (lambda (x)
(apply #'+ x))
data))
(max (apply #'max totals))
(to-string (lambda (x) (format "%s" x))))
(mapconcat
to-string
(mapcar
(lambda (x)
(mapconcat
to-string x ","))
(apply #'mapcar*
#'list
(mapcar
(lambda (x)
(mapcar
(lambda (y)
(format "%.1f"
(* (/ 100 max) y)))
x))
data)))
"|"))
"&chco=ff0000,00ff00,0000ff"
"&chs=350x"
(int-to-string (* len 28)))))
(let ((data '((10 20 30)
(3 50 1)
(1 2 3)
(33 33 33)
(5 6 7)
(33 33 33)
(3 3 9))))
(browse-url (gchart-stack-bar-chart-url data)))
これで、
のようなグラフが書けます。
タイトルも付けられるようですが、飽きてしまいました
Emacs便利です。
■
>View Comments
このページの上へ戻る
- 平成22年5月14日(金) 17時06分08秒
-
区分
- Emacs
-
報告者:
- chiba
こんにちは、chibaです。
ネタがないので今回もEmacsの小ネタです。
Emacsには、LISPが搭載されているので、ちょっとしたLISPを書くことでも色々便利に使えます。
代表的なところとしては、ちょっとした計算でしょうか
(+ 1500
200
3000
4500
)
;⇒ 9200
S式の前置記法がこういう場合には便利です。
最近、SSLの申請で、更新するCSRを確認することがあったのですが、こういう確認の為の文字列比較にも使えることに気付きました。
(equal
"-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwRTELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx
ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAM7k/tno3FquqOOrhkFxCiAVx/0qPjjcOhcD0PXx
ZCgSd6vHK0oSjDrWl+KFRMISd+EECBIrWR0I/u3RywKmlj1Q29wgt+UzFFJSK5+k
wsiQTnxs//uAqWoLBUUU3Y0/67P+cJSqflAcGgt8imhXEh2GzfPPKfB9nK3P4MZ7
WcrKvTwUEewASdaBWU+8+4ic8JzIwiCLge6tQvf/xeqkBhp7Othsf9vmwGARjDaI
DPSswlaKqkaXEog9fhhJmO2QUzEQ9R92MNmxu+wXHKxx3LuC4dvnoNNFz1l+cPq9
3wVoLBIaEBw8U06+BEPtlAf8ZRGYVG7LpxvhyS0EdDirN0MCAwEAAaAAMA0GCSqG
SIb3DQEBBQUAA4IBAQAF/Stfy58MQFRCmXZxaiKK1Ez9CBdyBtbCM+xquYzfRTMg
EEmGRXoZ1FomV2B2avkUU0frOnb3cktfuttBs1olwKvf3lzktdRoQBPrzDy7iAej
p4MwQHEmFgVXe3ZstjoYIQ2PudSPUlCQRUAi9oiNjVt0iAY7w1xnlCMqYTzGBW4y
8MpnVDKtTmmMPM0wxtiKDkOmT3S8L/mR1wNDnpavv5hOIn8z7No+qHzkLcuHEHYF
IVn9suw6L2GvPgxdw4XarWoFjeuADhszwwVpI87oGMH3H5Z6kniW22bQX1l402dO
YqSaxgasSPwJi+3njg0upYERIV7i9fR74/tufNv7
-----END CERTIFICATE REQUEST-----"
"-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwRTELMAkGA1UEBhMCSlAxEzARBgNVBAgTClNvbWUtU3RhdGUx
ITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAM7k/tno3FquqOOrhkFxCiAVx/0qPjjcOhcD0PXx
ZCgSd6vHK0oSjDrWl+KFRMISd+EECBIrWR0I/u3RywKmlj1Q29wgt+UzFFJSK5+k
wsiQTnxs//uAqWoLBUUU3Y0/67P+cJSqflAcGgt8imhXEh2GzfPPKfB9nK3P4MZ7
WcrKvTwUEewASdaBWU+8+4ic8JzIwiCLge6tQvf/xeqkBhp7Othsf9vmwGARjDaI
DPSswlaKqkaXEog9fhhJmO2QUzEQ9R92MNmxu+wXHKxx3LuC4dvnoNNFz1l+cPq9
3wVoLBIaEBw8U06+BEPtlAf8ZRGYVG7LpxvhyS0EdDirN0MCAwEAAaAAMA0GCSqG
SIb3DQEBBQUAA4IBAQAF/Stfy58MQFRCmXZxaiKK1Ez9CBdyBtbCM+xquYzfRTMg
EEmGRXoZ1FomV2B2avkUU0frOnb3cktfuttBs1olwKvf3lzktdRoQBPrzDy7iAej
p4MwQHEmFgVXe3ZstjoYIQ2PudSPUlCQRUAi9oiNjVt0iAY7w1xnlCMqYTzGBW4y
8MpnVDKtTmmMPM0wxtiKDkOmT3S8L/mR1wNDnpavv5hOIn8z7No+qHzkLcuHEHYF
IVn9suw6L2GvPgxdw4XarWoFjeuADhszwwVpI87oGMH3H5Z6kniW22bQX1l402dO
YqSaxgasSPwJi+3njg0upYERIV7i9fR74/tufNv7
-----END CERTIFICATE REQUEST----"
)
;⇒ nil
Emacs便利です。
■
>View Comments
このページの上へ戻る
- 平成22年5月6日(木) 15時58分51秒
-
区分
- Emacs
-
報告者:
- chiba
こんにちはchibaです。
ネタ切れなのでいきなりLISPネタなのですが、letでつつまれた式を編集している際に、後で束縛したい変数を追加したくなることって良くありますよね。
(let ((str "foo bar baz"))
....
(setq len (length str)))
という風に書いていて、後でlenが欲しくなるような
つまり
(let ((str "foo bar baz")
(len 0))
....
(setq len (length str)))
こういう風に前に戻って(len 0)を追加したいわけですね。
思い立ったが吉日なのでそういうelispを書いてみることにしました。
(progn
(defun edit-let-bind ()
(interactive)
(let ((foundp nil))
(save-excursion
(catch 'loop
(while (not (c-at-toplevel-p))
(backward-up-list)
(down-list)
(let ((thing (thing-at-point 'symbol)))
(cond ((or (string= "let" thing)
(string= "do" thing))
(down-list)
(setq foundp t)
(throw 'loop nil))
('T (backward-up-list))))))
(when foundp
(recursive-edit)))))
;; keybind
(define-key global-map [(control meta shift ?c)] 'edit-let-bind))
非常に適当な作りですが、letや、doの束縛部を編集するために、再帰編集モードに入り、束縛部分にカーソルを飛し、編集が終わったら、再帰編集モードから抜ける、という風にしてみました。
再帰編集モードから抜けるのが、C-M-cだったので、C-M-sh-cで、束縛部の編集へ。
一応それなりに便利に使えますが、どなたかもっとちゃんとした、elispの流儀に則ったものを作成して頂けると嬉しいです!
■
>View Comments
このページの上へ戻る