カテゴリー別アーカイブ: emacs

emacs 25.1 で org2blogを使って WordPress に投稿するには

以前から気になっていた org2blog を emacs-25.1.1 で動かそう。 という話。

(この記事はemacs-25+org2blogで投稿しました)

org2blog / README.org を参考に、packageから org2blog をインストールして、以下の様に設定。

(require 'org2blog-autoloads)
(setq org2blog/wp-blog-alist
   '(("wordpress"
      :url "http://***.somof.net/****"
      :username "****"
      :password "****"
      :wp-latex nil
      :wp-code t
      )))

早速試してみるとワーニングが出たので、追加で htmlize の新しいバージョンを手動でインストールした。

これでログイン(org2blog/wp-login)まで出来るようになったけれど、投稿(org2blog/wp-post-buffer)が出来ない。

エラーメッセージは、こんな感じ。



error in process sentinel: url-http-create-request: Multibyte text in HTTP request: POST /xmlrpc.php HTTP/1.1




error in process sentinel: Multibyte text in HTTP request: POST /xmlrpc.php HTTP/1.1

雰囲気、文字コードか改行コードの問題の様。 org2blogが呼び出している gzipコマンドを Apple製からGNU製に変えてみたけど、症状は変わらず。

仕方ないので org2blogのソースを追ってみたところ、エラーの発信源は emacsに添付されている url-http.el だった。 なんと、 emacs 自身のコード側に問題があったのだった。

url-http-create-request関数の中に、こんなコードが紛れていた。

;; Bug#23750
(unless (= (string-bytes request)
           (length request))
  (error "Multibyte text in HTTP request: %s" request))
(url-http-debug "Request is: \n%s" request)

今使っているemacsは、リリース版の emacs 25.1.1 なのだけど、たまたま出来たてのバグを踏んでしまったらしい。

request(XML-RPCのXMLそのもの)の文字数とバイト数が一致しない場合にエラーを返す、多分デバッグ用のコードなのだけど、 ユーザーには意味がないので、とりあえず削除することにする。

こんな風に、initファイルに追加。

(advice-add 'url-http-create-request :override
            'url-http-create-request-debug)
(defun url-http-create-request-debug (&optional ref-url)
  "Create an HTTP request for <code>url-http-target-url', referred to by REF-URL."
  (let* ((extra-headers)
         (request nil)
         (no-cache (cdr-safe (assoc "Pragma" url-http-extra-headers)))
         (using-proxy url-http-proxy)
         (proxy-auth (if (or (cdr-safe (assoc "Proxy-Authorization"
                                              url-http-extra-headers))
                             (not using-proxy))
                         nil
                       (let ((url-basic-auth-storage
                              'url-http-proxy-basic-auth-storage))
                         (url-get-authentication url-http-proxy nil 'any nil))))
         (real-fname (url-filename url-http-target-url))
         (host (url-http--encode-string (url-host url-http-target-url)))
         (auth (if (cdr-safe (assoc "Authorization" url-http-extra-headers))
                   nil
                 (url-get-authentication (or
                                          (and (boundp 'proxy-info)
                                               proxy-info)
                                          url-http-target-url) nil 'any nil))))
    (if (equal "" real-fname)
        (setq real-fname "/"))
    (setq no-cache (and no-cache (string-match "no-cache" no-cache)))
    (if auth
        (setq auth (concat "Authorization: " auth "\r\n")))
    (if proxy-auth
        (setq proxy-auth (concat "Proxy-Authorization: " proxy-auth "\r\n")))

    ;; Protection against stupid values in the referrer
    (if (and ref-url (stringp ref-url) (or (string= ref-url "file:nil")
                                           (string= ref-url "")))
        (setq ref-url nil))

    ;; We do not want to expose the referrer if the user is paranoid.
    (if (or (memq url-privacy-level '(low high paranoid))
            (and (listp url-privacy-level)
                 (memq 'lastloc url-privacy-level)))
        (setq ref-url nil))

    ;; url-http-extra-headers contains an assoc-list of
    ;; header/value pairs that we need to put into the request.
    (setq extra-headers (mapconcat
                         (lambda (x)
                           (concat (car x) ": " (cdr x)))
                         url-http-extra-headers "\r\n"))
    (if (not (equal extra-headers ""))
        (setq extra-headers (concat extra-headers "\r\n")))

    ;; This was done with a call to </code>format'.  Concatenating parts has
    ;; the advantage of keeping the parts of each header together and
    ;; allows us to elide null lines directly, at the cost of making
    ;; the layout less clear.
    (setq request
          (concat
             ;; The request
             (or url-http-method "GET") " "
             (url-http--encode-string
              (if using-proxy (url-recreate-url url-http-target-url) real-fname))
             " HTTP/" url-http-version "\r\n"
             ;; Version of MIME we speak
             "MIME-Version: 1.0\r\n"
             ;; (maybe) Try to keep the connection open
             "Connection: " (if (or using-proxy
                                    (not url-http-attempt-keepalives))
                                "close" "keep-alive") "\r\n"
                                ;; HTTP extensions we support
             (if url-extensions-header
                 (format
                  "Extension: %s\r\n" url-extensions-header))
             ;; Who we want to talk to
             (if (/= (url-port url-http-target-url)
                     (url-scheme-get-property
                      (url-type url-http-target-url) 'default-port))
                 (format
                  "Host: %s:%d\r\n" host (url-port url-http-target-url))
               (format "Host: %s\r\n" host))
             ;; Who its from
             (if url-personal-mail-address
                 (concat
                  "From: " url-personal-mail-address "\r\n"))
             ;; Encodings we understand
             (if (or url-mime-encoding-string
                     ;; MS-Windows loads zlib dynamically, so recheck
                     ;; in case they made it available since
                     ;; initialization in url-vars.el.
                     (and (eq 'system-type 'windows-nt)
                          (fboundp 'zlib-available-p)
                          (zlib-available-p)
                          (setq url-mime-encoding-string "gzip")))
                 (concat
                  "Accept-encoding: " url-mime-encoding-string "\r\n"))
             (if url-mime-charset-string
                 (concat
                  "Accept-charset: "
                  (url-http--encode-string url-mime-charset-string)
                  "\r\n"))
             ;; Languages we understand
             (if url-mime-language-string
                 (concat
                  "Accept-language: " url-mime-language-string "\r\n"))
             ;; Types we understand
             "Accept: " (or url-mime-accept-string "*/*") "\r\n"
             ;; User agent
             (url-http-user-agent-string)
             ;; Proxy Authorization
             proxy-auth
             ;; Authorization
             auth
             ;; Cookies
             (when (url-use-cookies url-http-target-url)
               (url-http--encode-string
                (url-cookie-generate-header-lines
                 host real-fname
                 (equal "https" (url-type url-http-target-url)))))
             ;; If-modified-since
             (if (and (not no-cache)
                      (member url-http-method '("GET" nil)))
                 (let ((tm (url-is-cached url-http-target-url)))
                   (if tm
                       (concat "If-modified-since: "
                               (url-get-normalized-date tm) "\r\n"))))
             ;; Whence we came
             (if ref-url (concat
                          "Referer: " ref-url "\r\n"))
             extra-headers
             ;; Length of data
             (if url-http-data
                 (concat
                  "Content-length: " (number-to-string
                                      (length url-http-data))
                  "\r\n"))
             ;; End request
             "\r\n"
             ;; Any data
             url-http-data))
    ;; Bug#23750
    ;;(unless (= (string-bytes request)
    ;;           (length request))
    ;;  (message "   text byte %d vs %d length" (string-bytes request) (length request)))
      ;;(message "===============================")
      ;;(error "Multibyte text in HTTP request: %s" request))
    (url-http-debug "Request is: \n%s" request)
    request))

これで、無事 org2blogから投稿できるようになった。

そのうち解決されるだろうけれど、それまではこれで凌ごう。

emacs helm find-fileの設定を整理

emacsとhelmののアップデートで、
find-fileの動きが大分変わってしまったので修正する。

|—————-+———————————————|
| 関数 | いろいろ |
|—————-+———————————————|
| find-file | 標準の補完リストがバッファになり |
| | 操作がacejumpみたくなった (acejumpの機能?) |
| helm-find-file | TAB補完の設定が効かなくなった |
| | その代り → を使え、と言うことらしい |
|—————-+———————————————|

両方をしばらく使ってみたけれど、
どちらも、find-fileとしては、おせっかい過ぎる感じがする。

滅多に使わないコマンドを探す様な場合はhelmは最高だけども、
find-fileする時は目的のファイル名が頭の中にある訳なので、
候補が大量に出てきても有難味が薄いのだ。

emacs標準機能に慣れるのも良いかと、しばらく素で使ってみたけれど、
helm-miniと補完操作が違うのは、やっぱり気持悪い
そうは言っても helm I/Fが便利だし、補完操作は揃えておきたい。

|—————-+———————————————|
| 関数 | 操作方法 |
|—————-+———————————————|
| find-file | 水平リスト, ace-jump的選択 |
| | TAB: 補完 (複数候補があると確定しない) |
| | C-BS: 直前の単語削除 |
| helm-find-file | helm I/F、垂直リスト、Action込み |
| | →: 補完 (複数候補があっても何か確定できる) |
| | C-l: 直前の単語削除 |
| | TAB: Actionの選択 |
| | C-j,C-z: 昔のTABの様な動作 (多分) |
|—————-+———————————————|

補完キーがカーソルになっているのは、 lynxスタイルというものらしい。

#+BEGIN_SRC lisp
(defcustom helm-ff-lynx-style-map t
“Use arrow keys to navigate with helm-find-files'.
You will have to restart Emacs or reeval
helm-find-files-map’
and `helm-read-file-map’ for this take effect.”
:group ‘helm-files
:type ‘boolean)
#+END_SRC

ただ、これを nil にしても、TABキーは元に戻らない。

昔のTAB相当の機能 helm-execute-persistent-action は
C-jとC-zに割り当てられている。

そもそもActionなんて使わないぜ!という男の中の男は。

#+BEGIN_SRC lisp
(define-key helm-map (kbd “TAB”) ‘helm-execute-persistent-action)
#+END_SRC

とすれば簡単で良い。

僕は女々しいので、今後はC-jとC-zを使うことにする。

find-filesとhelm-miniの動作がちょっと違うのが
もやっとするけど、慣れられそうな範囲だと思う。

emacs helm の補完情報(ソース)を切り替えるキー操作

helmは、殆どの場合、タブキーで補完してくれるので、
操作方法を覚える必要はあまりない。

だけど、覚えなくて良いせいで
たまに補完の情報源を切り替えたい時に、
毎回検索することになる。

#+BEGIN_SRC lisp
;; helm-20160321.959:
./helm-files.el:409: (define-key map (kbd “<M-left>”) ‘helm-previous-source)
./helm-files.el:410: (define-key map (kbd “<M-right>”) ‘helm-next-source))
#+END_SRC

カーソルキーの左右で切り替えられるみたいだ。

これで、ソースを recentf から buffers-list に
さくっと切り替えられる。

きっと
また忘れるだろうな。

emacs helm の設定を整理

2016/03/24 現在のhelmの初期状態が、
変更していた自分好みと殆ど同じになったので
設定を見直した。

#+BEGIN_SRC lisp
;; ————————————————————————
;; @ helm
(require ‘helm-config)
(require ‘helm-command)
;;(require ‘helm-descbinds)

;; 体感速度向上
;;(setq helm-idle-delay 0.2)
;;(setq helm-input-idle-delay 0.2)

;;(setq helm-candidate-number-limit 200)
(setq helm-mini-default-sources ‘(helm-source-recentf
;;helm-source-files-in-current-dir
helm-source-buffers-list
;;helm-source-buffer-not-found
))
(helm-mode 1)

;; Helm KeyBind
(define-key global-map [remap find-file] ‘helm-find-files)
(define-key global-map [remap occur] ‘helm-occur)
(define-key global-map [remap list-buffers] ‘helm-buffers-list)
(define-key global-map [remap dabbrev-expand] ‘helm-dabbrev)
(global-set-key (kbd “M-x”) ‘helm-M-x)

;;; helmで変更したい/したくないコマンド
;;(add-to-list ‘helm-completing-read-handlers-alist ‘(find-file . nil))
;; ‘((describe-function . helm-completing-read-symbols)
;; (describe-variable . helm-completing-read-symbols)
;; (describe-symbol . helm-completing-read-symbols)
;; (debug-on-entry . helm-completing-read-symbols)
;; (find-function . helm-completing-read-symbols)
;; (disassemble . helm-completing-read-symbols)
;; (trace-function . helm-completing-read-symbols)
;; (trace-function-foreground . helm-completing-read-symbols)
;; (trace-function-background . helm-completing-read-symbols)
;; (find-tag . helm-completing-read-with-cands-in-buffer)
;; (ffap-alternate-file . nil)
;; (tmm-menubar . nil)
;; (find-file . nil)
;; (execute-extended-command . nil))

;; 自動補完を無効にする
;;(custom-set-variables ‘(helm-ff-auto-update-initial-value nil))

;; C-hでバックスペースと同じように文字を削除
;;(define-key helm-read-file-map (kbd “C-h”) ‘delete-backward-char)

;; TABで任意補完。選択肢が出てきたらC-nやC-pで上下移動してから決定することも可能
;;(define-key helm-read-file-map (kbd “TAB”) ‘helm-execute-persistent-action)

;; helm
;; minibuffer で C-k を押すと先頭から丸ごと削除され、kill ring に追加されないのを解決
;; → 今は不要
;;(setq helm-delete-minibuffer-contents-from-point t)
;;(defadvice helm-delete-minibuffer-contents (before helm-emulate-kill-line activate)
;; “Emulate `kill-line’ in helm minibuffer”
;; (kill-new (buffer-substring (point) (field-end))))

#+END_SRC

migemoの不具合から、macのemacsをgit-HEADから25.0.50に戻してみたり

Windows上で快適に使っている emacs-w64 は、 アップデートする毎、動作が機敏になってきていたので、 割と頻繁に追従していた。

それがある時から、不調になりがちになった。

emacs-w64 自体のバージョンは 25.0.x なのだが 25.1.x を目指した変更が外のパッケージに不具合を起こす様だ。

良い機会なので、もう使っていない古いパッケージを整理した結果、 むしろサクサク動く様になって、快適快適… と思いきや。

  • migemoが動かない。
  • helmの挙動が、変わってしまう。
  • moccur が無くなった?

helmの方は、症状が深刻ではないし、 helm自体の更新が速いので、直に元に戻るだろう。

migemo/cmigemoは、もう枯れたパッケージだし、 そんなに更新頻度が高くないので、なんとか設定で回避したい。

migemo と emacs25.1.x

emacs25.1.x で isearch.elに変更があったために、 migemo.elと辻褄が合わなくなっている様だ。

Warning (bytecomp): ‘isearch-word’ is an obsolete variable (as of 25.1); use ‘isearch-regexp-function’ instead.

なので、

(setq search-default-regexp-mode nil) ;; emacs25.1

とすれば、まずは動作する。

追記

2016年03月24日現在、 isearch.elの実装がしょっちゅう変更されている様で、 ちょいちょい対応する必要がありそう。

macbook上のemacsは、 git HEAD で問題なくmigemoが動作する様になっている。

cygwinのcmigemoを使う emacs-w64 では、 問題なく使えるのは 2015年10月頃のバージョンみたいだ。

homebrewのemacsを25.0.50に戻す方法

Formula/emacs.rb を見ると、25.0-dev が良さげ。

brew reinstall emacs --devel --with-cocoa --with-rsvg --with-imagemagick

で、一応 25.0.xに戻せるのだけれど、 isearch.el は既にemacs25.1.x相当のものに置き換わってしまっていた。

むむむ。

そういう事なら、最新版にしておこう。と言う場合は。

brew reinstall emacs --HEAD --use-git-head --with-cocoa --with-rsvg --with-imagemagick

cygwinのファイルアクセスが遅い件:解決編

もうmagit無しではemacsでコーディングできない体になってしまった。 さらに便利を求めて git-gutter-fringe+ をインストールしたところ、 Macではもう最高の使い心地。

だけども。 これをCygwinとntemacsで使うと、しょっちゅうプチフリーズしてしまう。 Cygwinのファイルアクセスが異常に遅いせいなのだけれど、 仕事上Cygwin環境は必須だし、git-gutterは手放したくないし。

いくら便利でも、作業中に30秒も固まられると、さすがに我慢できない。 いい加減、ちゃんとCygwinに対策をしなければ…

と言う訳で。

Cygwinの起動やファイルアクセスが遅くて怪しい場合に

CygwinのFAQサイト を検索してみた。

以下、Cygwinのページから引用。

4.2. Starting a new terminal window is slow. What’s going on?

There are many possible causes for this.

~snip~

For almost all its lifetime, Cygwin has used Unix-like /etc/passwd and /etc/group files to mirror the contents of the Windows SAM and AD databases. Although these files can still be used, since Cygwin 1.7.34, new installations now use the SAM/AD databases directly.

To switch to the new method, move these two files out of the way and restart the Cygwin terminal. That runs Cygwin in its new default mode.

~snip~

For the AD case, it can be slower than the old method, since it is trading a local file read for a network request. Version 1.7.35 will reduce the number of AD server requests the DLL makes relative to 1.7.34, with the consequence that you will now have to alter /etc/nsswitch.conf in order to change your Cygwin home directory, instead of being able to change it from the AD configuration.

If you are still experiencing very slow shell startups, there are a number of other things you can look into:

One common cause of slow Cygwin Terminal starts is a bad DNS setup. This particularly affects AD clients, but there may be other things in your Cygwin startup that depend on getting fast answers back from a network server.

~snip~

Another cause for AD client system is slow DC replies, commonly observed in configurations with remote DC access. The Cygwin DLL queries information about every group you’re in to populate the local cache on startup. You may speed up this process a little by caching your own information in local files. Run these commands in a Cygwin terminal with write access to /etc:

getent passwd $(id -u) > /etc/passwd getent group $(id -G) > /etc/group Also, set /etc/nsswitch.conf as follows:

passwd: files db group: files db

~snip~

Either in addition to the previous item or instead of it, you can run cygserver as a local caching service to speed up DC requests.

~snip~

A less preferable option is to create a static read-only cache of the authentication data. This is the old-fashioned method of making Cygwin integrate with AD, the only method available in releases before 1.7.34. To do this, run mkpasswd and mkgroup, then put the following into /etc/nsswitch.conf to make Cygwin treat these files as the only sources of user and group information:

passwd: files group: files

~snip~

If none of the above helps, the best troubleshooting method is to run your startup scripts in debug mode. Right-click your Cygwin Terminal

~snip~

4.3. Why is Cygwin suddenly so slow?

If suddenly every command takes a very long time, then something is probably attempting to access a network share. You may have the obsolete //c notation in your PATH or startup files. Using //c means to contact the network server c, which will slow things down tremendously if it does not exist.

要するに、ドメインで使っている会社のPCで遅くなる原因は。。。

  1. cygwinを 1.7.35 以降の最近のバージョンにする (古いのは遅い)
  2. DNSのIPアドレスが間違っていると、長い待ちがおこる
  3. ドメインじゃないなら、 /etc/passwd と /etc/group を消すと良いかも(知れない)
  4. ドメインなら、ドメインコントローラの返事が遅いのかも
    • その場合、passwd/group をキャッシュして高速化できる
    • cygserverでドメンインキャッシュサーバをたててみても良いぞ
    • そもそもドメインにアクセスするの辞めちゃえば? (ADが更新しても知らんけど)
  5. それでもダメならデバッグモードで起動してみな
  6. ひょっとして ‘//c’ とか書いてない?

DNSが関係しているのは分かっていたけど、 会社のドメインコントローラが遅いとは疑っていなかった。 Windowsでは困ったことないし。

でもやってみよう。

まずはバージョン確認

以下のどちらかで確認できる。

uname -a
cygcheck -c cygwin

2.2.0 だったので、問題なし。

/etc/passwd と /etc/group の削除

cygwinでドメインに関係するような事はしないし、 むしろ悪さしそうなので、まず削除して様子をみてみた。

数時間使ってみて、酷いフリーズは経験しなかったけれど、 プチフリーズが解決したかと言うと、ちょっと分からない。

AD情報のキャッシュ化

ドメインの情報を削除するのも危険な気がしたので、 一応キャッシュしておいて、様子をみてみた。

ドメイン情報のキャッシュは、こうしてとれる。

getent passwd $(id -u) > /etc/passwd
getent group $(id -G) > /etc/group

その後、 /etc/nsswitch.conf を編集して、 ADにアクセスするより先にキャッシュ(files)を見るように変更する。

passwd: files db
group:  files db

正直、これも良くなったのか悪くなったのか分からない。

そもそもドメイン情報を使わないようにする

いくつか試してみた結果、 /etc/passwd と /etc/group を削除してしまうことにした。

実はこの状態でも、ドメインでアクセス管理しているネットワークサーバの ファイルにアクセスできたのだった。しかも今迄よりもサクサクと。(汗)

まだ、たまにフリーズはするものの (キャッシュはあった方が良いのかも知れない)、 全体的にファイルアクセスが軽快になった。

無くて良いものは、無い方が良い。 この状態で、またしばらく使ってみようと思う。

org-mode で WordPress の記事を書きたい その3 スタイル追加

とりあえず、手元の emacs で書いた org-mode の記事を、 そのまんま WordPress の載せられるようになったけれど、 見た目があまりにも素気ないので、スタイルシートを追加してみる。

HTMLはともかく、デザインっぽい css には縁がなく、サッパリ分らない。 とりあえず、人様のを パクってきて 参考にしてみよう。

とその前に。 WordPressが勝手に追加したHTMLタグを削除しておく。

まずは WordPress 標準の HTML タグを排除する

remove_filter で、余計なフィルタを削除する事までは分かっている。 削除するフィルタは ‘wptexturize’、’wpautop’、’wp_richedit_pre’ あたりで十分そうだ。

ただ、どの資料や先人のブログを見ても、remove_filter を functions.php に 記述するように、とある。

今回のプラグインでも、呼び出される時に同時に remove_filter を行なうと、 とりあえず想定通りの動作はした。

無駄はあるかも知れないけれど、まぁ良いか。

プラグインに挿入したのは、こんなコード フィルタの存在確認は特に必要ないようだし、 このプラグインでは画面の種類まで気にする必要がないので、 今は、これで必要十分。

remove_filter('the_title', 'wptexturize');   // タイトルの記号を実態文字化する
remove_filter('the_content', 'wptexturize'); // 記事の記号を実態文字化する
remove_filter('the_excerpt', 'wptexturize'); // 抜粋の記号を実態文字化する
remove_filter('the_title', 'wpautop');       // タイトルの自動整形を無効にする
remove_filter('the_content', 'wpautop');     // 記事の自動整形を無効にする
remove_filter('the_excerpt', 'wpautop');     // 抜粋の自動整形を無効にする
remove_filter('the_editor_content', 'wp_richedit_pre'); // 改行とBRのあつかい

WP-Markdown や JP Markdown のソースコードを見てみると、 上と同じコードがないし、それぞれ違う実装方法を選んでいるみたいだ。

WP-markdownでは

./wp-markdown.php:79:  remove_filter( 'bbp_new_reply_pre_content', 'bbp_code_trick',  20 );
./wp-markdown.php:80:  remove_filter( 'bbp_edit_reply_pre_content', 'bbp_code_trick',  20 );
./wp-markdown.php:81:  remove_filter( 'bbp_get_form_reply_content', 'bbp_code_trick_reverse',  10 );
./wp-markdown.php:85:  remove_filter( 'bbp_new_topic_pre_content', 'bbp_code_trick', 20 );
./wp-markdown.php:86:  remove_filter( 'bbp_edit_topic_pre_content', 'bbp_code_trick', 20 );
./wp-markdown.php:87:  remove_filter( 'bbp_get_form_topic_content', 'bbp_code_trick_reverse', 10 );
./wp-markdown.php:91:  remove_filter( 'content_save_pre', 'balanceTags', 50 ); //Remove balanceTags and apply after MD -> HTML
./wp-markdown.php:125: if ( remove_filter( 'content_save_pre', 'wp_filter_post_kses' ) ) {

jetpack-markdownでは

./markdown/easy-markdown.php:137: remove_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ), 10, 2 );
./markdown/easy-markdown.php:138: remove_filter( 'edit_post_content', array( $this, 'edit_post_content' ), 10, 2 );
./markdown/easy-markdown.php:139: remove_filter( 'edit_post_content_filtered', array( $this, 'edit_post_content_filtered' ), 10, 2 );
./markdown/easy-markdown.php:141: remove_filter( '_wp_post_revision_fields', array( $this, '_wp_post_revision_fields' ) );
./markdown/easy-markdown.php:143: remove_filter( 'content_save_pre', array( $this, 'preserve_code_blocks' ), 1 );
./markdown/easy-markdown.php:161: remove_filter( 'pre_comment_content', array( $this, 'pre_comment_content' ), 9 );
./markdown/easy-markdown.php:238: $this->kses = remove_filter( 'content_filtered_save_pre', 'wp_filter_post_kses' ) && remove_filter( 'content_save_pre', 'wp_filter_post_kses' );
./markdown/easy-markdown.php:568: remove_filter( 'wp_revisions_to_keep', '__return_false', 99 );

WordPressのどこを勉強すれば、こういう方法を思いつくのかな?

せめてソースコードのスタイルシートは綺麗に

さて、問題のスタイルシート。 WordPressのHTMLタグを取り除いたので、ひとまず見られる位になったので、 もう少し華やかにしてみたい。

出来るだけ楽をしたいので デザインに自信ないので、出回っている物を流用しよう。

検索すると、 Highlight.js と SyntaxHighlighter が見付かった。 軽量で扱い易そうな Highlight.js を有り難く使わせて頂こう。

javascriptの設置と登録

Highlight.js は、名前の通り javascript なので、 どこかのサーバに置いて、 WordPress に教えてあげる必要がある。

そこではたと困るのが、プラグインのフォルダを知る方法。 探してみると、それっぽいのが結構色々みつかる。

Highlight.js から zenburn.css を選んだとすると。 こんな感じ?

wp_enqueue_script('org2html-highlight', plugin_dir_url( __FILE__ ) . 'script/highlight.pack.js');
wp_enqueue_style('org2html-style', plugin_dir_url( __FILE__ ) . 'style/zenburn.css');

動く以前に、何か怒られた。

login_enqueue_scripts hooks. Please see Debugging in WordPress for more information. (This message was added in version 3.3.) in ... /wp-includes/functions.php on line 3622

検索してみると、一旦関数にして add_action で登録しろって事らしい。 なので、それっぽく書き直してみよう。

function my_enqueue_scripts() {
    wp_enqueue_script('org2html-highlight', plugins_url('script/highlight.pack.js', __FILE__ ));
    wp_enqueue_style('org2html-style', plugins_url('style/zenburn.css', __FILE__ ));
}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts');

あと、本文の方に javascript の実行部分を追加して、作業完了。

$html .= '<script>hljs.initHighlightingOnLoad();</script>';

おぉ〜 良い感じになった。

想定外の文字が意外に多くて、時々パーサが失敗してるけど… まぁ、良いか。そのうち直そう。

emacsのorg-mode で WordPress の記事を書きたい

org-mode で書いた記事を、そのまま WordPress に投稿したい。

方法は、大きく分けて二つある。

– org-mode で HTMLに変換してからコピペする
– org-mode の書式を解釈する WordPress のプラグインを新たに作る

org-mode側でHTMLに変換する方法は、
WordPressの記事一覧が酷い事になるのが目に見えている。

いつかは画像も自動で組込みたいし、
後者の、プラグインを新たに作るのが良さそう。

車輪の再発明ぽくてイヤだけど、自分で使う目的だし、
自由が効く方が良いか。

問題はむしろ、PHPの開発経験が全く無いこと。

orgのテーブルを変換するプラグインは小さかったので、
一旦pythonで書いてから、本番サーバ上でPHPに移植する
という、恐しい開発方法だったけど。

今回は、ちゃんとテスト環境をそろえて開発したい。

テーブルプラグインの開発では、
WP-MarkDown の不具合(バグの様な仕様)で、
保存する度に記事を壊されて無駄に時間がかかってしまった。

WP-MarkDown とはオサラバして、スッキリ開発したい。

で。

対応したいタグは、こんなもの。

– 段落タイトル 3段階
– 段落
– コード
– テーブル
– 引用
– 段落
– 強調/イタリック
– リンク
– リスト
– *インライン画像
– (入れ子リスト)
– (番号リスト)

これだけ変換するには、
テーブルプラグインの構造では間に合わないので、
きちんと文章を構文解析する必要がある。

それに、ちゃんとしたテスト環境を作ってから開発したいし
新調した MacBookPro に合わせて、CI環境を再構築しないと…

emacs magitでソース管理

cygwin上のemacsから使い易い gitクライアントが無かったので、
Windowsでの開発では、ソースの編集はemacsでやっていても、
バージョン管理には TortoiseGit を使っていた。

TortoiseGit は GUIが上等なので、それはそれで便利なのだけど、
いちいちマウスを持つのが面倒なので、
編集に関わる作業は全部emacsの中で連続してやってしまいたい。

で、 magit を使うことにした。

今迄 emacs内でgitを触りたくなかったのは
cygwinのファイルアクセスが異常に遅いのが理由なのだけど、
最新のemacs-win64(25.0.50)とmagitの組み合わせなら何とかなる範囲。

で、インストール。

一旦、magitをGitHubからダウンロードしたものの、
中のドキュメントを見たら、 emacsのパッケージからインストールできる、
という事だったので、そっちに方針変更。

ドキュメント内では、 Melpa と Marmalade のパッケージが説明されていたけど、
結局、 Elpa 内の magit を使うことにした。

使用している git は 2.5.0、emacsは25.0.50 なので、
動作条件は満しているものの、 emacsがHEADのせいか、
こういう状況だった。

  • Melpa は、パッケージ自体に問題がちょいちょい起こるのでリストから外している
  • Marmalade の Magit は、バージョンが 1.2 だったけど、エラーで動作せず
  • Elpaの Magit は、バージョンが 0.8.1 で、かなり古いけど、問題なく動作する

Elpaのパッケージは更新されそうにないので、
そのうち GitlHub の Magit 2.1.0 に乗り換えるかも知れない。

で、Magitの使用方法は、とても簡単。

で、今のソースの更新状況が表示される。

これが emacs に出るのが本当に嬉しい。
うっかり編集や、気の迷いでチョット修正したのを忘れてしまう、
という、本当におバカなミスを防いでくれる。

TortoiseGit だと気付くタイイングが大分後になってしまうし、
そもそも作業が億劫なので、こまめに commit しなくなるから
gitの有難味が、ちょっとそがれてしまう。

emacs の magit-status 画面で普段使う機能は以下の通り。

  • s でファイルを一つ add
  • S 全ファイルを全てadd(git add -A)
    • 実際には C-u S とする
  • c コミット
  • u addの取消
  • l ログ一覧表示
  • L ログ一覧詳細表示

Macでの作業は、基本個人のローカル運用なので、コレで十分。

Windowsの開発案件で必要な pull/push/merge などは、
今のところ TortoiseGit を使っている。
外部と関わる重要作業は、GUIがしっかりしていた方がちょっと安心なので。

emacs org-modeで画像をインライン表示する

などして、
(org-toggle-inline-images) の所で C-c C-c とすると
インライン画像が表示される。

上にやり方だと、トグル動作の状態が

とか

とか、orgファイル上に勝手に追加される。
それがイヤな場合は、 M-X org-toggle-inline-images でOK。

としておけば、常のインライン表示されるけど、
普段は邪魔なのでトグル動作にしてる。

この書式のままで、
画像ファイルの転送も含めて WordPress の記事が書けると、
ブログを書くのが楽になるんだけどなぁ。

プラグインを書くのに、
またWP-MarkDownとケンカするのを解決するのが面倒そうだ。
WordPressでは MarkDown書式が一般的だしなぁ。

いっそMarkDownをやめて、
全て org-mode で書くプラグインを作るか…