読者です 読者をやめる 読者になる 読者になる

by shigemk2

当面は技術的なことしか書かない

Emacs本体に投げたパッチが取り込まれました

前置き

github.com

思うところがあり、Emacs本体にパッチを投げました。結果マージされました。去年の暮れの話です。この記事を今年の抱負の代わりとします。

修正しようと思った

Emacsでシェルスクリプトのファイルを開くと、自動的にsh-modeが開くようになっています。各種シェルをサポートしており、.bashファイルならbash、.shファイルならshに対応するようにsh-modeのなかで定義されてます。

ですが、Emacswikiを見るとsh-modeはzshにも対応しているとあるのにzshのファイルを開いてもzshのsh-modeが起動しません。

これはなぜだろう、というところをEmacsの日本の大家るびきち氏に メルマガで相談しました所、Emacs本体のsh-script.elにて、該当する処理がないためにzshファイルを開いてもsh-modeが起動しないから、という返答をいただきました。

該当する箇所はこちらです。

(sh-set-shell
 (cond
  ((save-excursion
     (goto-char (point-min))
     (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
   (match-string 2))
  ((not buffer-file-name) sh-shell-file)
  ;; Checks that use `buffer-file-name' follow.
  ;; ファイル名で判断する
  ((string-match "\\.m?spec\\'" buffer-file-name) "rpm")
  ((string-match "[.]sh\\>"     buffer-file-name) "sh")
  ((string-match "[.]bash\\>"   buffer-file-name) "bash")
  ((string-match "[.]ksh\\>"    buffer-file-name) "ksh")
  ((string-match "[.]csh\\>"    buffer-file-name) "csh")
  ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
  (t sh-shell-file))
 nil nil)

cond文の中で、バッファのファイル名からsh-modeでどのシェルを動かすかを判断していますが、zshに対応した処理がないので、シバンに#!/usr/bin/zshなどと書かない限りsh-modeのzshは起動せず環境変数SHELLで定義されているシェルが起動してしまうのです。

f:id:shigemk2:20170103155408p:plain

この画像はopensource.comでどのログインシェルを使っているかのアンケートですが、bash、zsh、fishと続いています。zshユーザーがこんなにいるのにファイルを開いてもsh-modeがzshで起動する設定がないのは不自然です。るびきち氏も謎だと言っていました。しかも修正箇所はcondのなかで1行追加するだけで済みそうなので、パッチを送って取り込んでもらおうと思いました。しかし、EmacsのソースコードはGitで管理されていますがGitHubなどのホスティングサービスは使っていませんので、GitHubに慣れきっていた僕としては一苦労する手順でした。

ソースコードの修正と確認

cloneする

とにもかくにもまずはローカルにソースコードを落とさないと始まらないので、まずはローカルにソースコードを落とします。 ソースコードはGitで管理されているので、cloneするだけでオーケーです。

git clone git://git.savannah.gnu.org/emacs.git

GitHubで管理されていたらghqを使ってforkなりcloneなりをしていますが、いったんGitHubのことは忘れましょう。

GitHubのページはありますがこちらはミラーサイトなのでここにプルリクエストを送っても取り込んでくれないと思います。

github.com

「Emacs 開発」などとググっても必要な情報は出てきません。「contributing emacs」などとググってみましょう。そうすればこのページが出てきます。英語はしんどいですが日本語の情報は皆無に等しいため、頑張って読むしかないです。

GNU Emacs Manual: Contributing

ソースを修正する

該当するファイルは lisp/progmodes/sh-script.el です。c言語で書かれているぶぶんとemacs lispで書かれている部分がありますが、今回修正するのはemacs lispのところだけです。さくっと修正してみましょう。

これを、

  (sh-set-shell
   (cond ((save-excursion
            (goto-char (point-min))
            (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
          (match-string 2))
         ((not buffer-file-name) sh-shell-file)
         ;; Checks that use `buffer-file-name' follow.
         ((string-match "\\.m?spec\\'" buffer-file-name) "rpm")
         ((string-match "[.]sh\\>"     buffer-file-name) "sh")
         ((string-match "[.]bash\\>"   buffer-file-name) "bash")
         ((string-match "[.]ksh\\>"    buffer-file-name) "ksh")
         ((string-match "[.]t?csh\\(rc\\)?\\>" buffer-file-name) "csh")
     ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
         (t sh-shell-file))
   nil nil)

こうします。

  (sh-set-shell
   (cond ((save-excursion
            (goto-char (point-min))
            (looking-at "#![ \t]?\\([^ \t\n]*/bin/env[ \t]\\)?\\([^ \t\n]+\\)"))
          (match-string 2))
         ((not buffer-file-name) sh-shell-file)
         ;; Checks that use `buffer-file-name' follow.
         ((string-match "\\.m?spec\\'" buffer-file-name) "rpm")
         ((string-match "[.]sh\\>"     buffer-file-name) "sh")
         ((string-match "[.]bash\\>"   buffer-file-name) "bash")
         ((string-match "[.]ksh\\>"    buffer-file-name) "ksh")
         ((string-match "[.]t?csh\\(rc\\)?\\>" buffer-file-name) "csh")
         ((string-match "[.]zsh\\(rc\\)?\\>" buffer-file-name) "zsh") ;; こちらを追加。
     ((equal (file-name-nondirectory buffer-file-name) ".profile") "sh")
         (t sh-shell-file))
   nil nil)

1行だけです。

ビルドして確認する

コードを修正しただけでは本当に動いているかどうか分からないので、ビルドして、問題がないことを確認します。no-pieのオプションをつけているのは開発環境がUbuntu 16.10だから。

./configure CFLAGS=-no-pie --prefix=$HOME/emacs-build ; sudo make; sudo make install

パッチを送る

重ねて申し上げますがGitHubなどと違い自分の修正を取り込んで欲しい場合Emacsではパッチをメールで送信する必要があります。ココが重要です。ブラウザでポチポチしてリクエストは送れないのです。

やりかたとしては、下のコマンドをなぞればオーケーです。

$ git commit -m "Enable sh-mode zshrc" # コミットします
$ git format-patch HEAD^ # 直前のコミットの中身をパッチとして作成します
$ git send-email 0001-Enable-sh-mode-zshrc.patch # パッチをメールで送ります。git-emailのパッケージをインストールする必要があります

ちなみにgit send-emailするためには.gitconfigにメール送信の設定を行う必要があります。

[sendemail]
    smtpencryption = tls
    smtpserver = SMTPサーバ
    smtpuser = メールアドレス
    smtpserverport = SMTPサーバのポート(通常は587)

メールの送り先についてですが、こちらを読むと、バグは bug-gnu-emacs@gnu.org へ、議論の余地のある機能追加は emacs-devel@gnu.org と書いています。ちょっと迷いましたが、やはりこれもるびきち氏に相談した所ユーザーがそれなりにいるにもかかわらずsh-modeがzshファイルに対応していないのはバグでしょうとのことなので、bug-gnu-emacsのほうへメールを送りました。メールを送ると、以下のようなメールが返ってきます。

Thank you for filing a new bug report with debbugs.gnu.org.

This is an automatically generated reply to let you know your message
has been received.

Your message is being forwarded to the package maintainers and other
interested parties for their attention; they will reply in due course.

Your message has been sent to the package maintainer(s):
 bug-gnu-emacs@gnu.org

If you wish to submit further information on this problem, please
send it to 25217@debbugs.gnu.org.

Please do not send mail to help-debbugs@gnu.org unless you wish
to report a problem with the Bug-tracking system.

パッチを取り込まれるまでは

GNUにはbug trackerが用意されており、これがGitHubでいうところのIssue管理となっています。 パッチをメールで送ると、自動的にチケットとメールアドレスが発行され、以後のやりとりはそのメールアドレスに送信する形で行います。

今回は 25217@debbugs.gnu.org というメールアドレスが発行されたので、チケットにコメントする際はこのメールアドレスに送信します。

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=25217 パッチのメールを送ってからのやりとりはこちらに記載してありますが、いくつかやりとりをして修正パッチを送ったあと、パッチが無事にEmacs本体に取り込まれました。ぱちぱちー

ちなみにmasterブランチに取り込まれたので、自分のパッチが当てられたバージョンがそのうちリリースされると思います。

困ったこと

copyright assignmentを忘れていました。これは見落としていました。Emacsなどのフリーソフトウェア財団のソフトウェアに貢献する際は、著作権の譲渡の手続きを行わないといけません。

こちらにそれが書いてありました。 GNU Emacs Manual: Copyright Assignment

ということで、わからなかったので emacs-devel@gnu.org にメールを送りました。

I would like to assign copyright.
I have sent a patch before, but I didn't know about copyright
assignment. I read this page:
https://www.gnu.org/software/emacs/manual/html_node/emacs/Copyright-Assignment.html#Copyright-Assignment,
but I didn't understand how to assign copyright.

Please let me know about copyright assignment.

Thank you.

すると、assign@gnu.org にメールを送れという返答をいただきました。フォーマットは以下です。こちらに必要な情報を入れて送信しました。

Please email the following information to assign@gnu.org, and we
will send you the assignment form for your past and future changes.

Please use your full legal name (in ASCII characters) as the subject
line of the message.
----------------------------------------------------------------------
REQUEST: SEND FORM FOR PAST AND FUTURE CHANGES

[What is the name of the program or package you're contributing to?]



[Did you copy any files or text written by someone else in these changes?
Even if that material is free software, we need to know about it.]



[Do you have an employer who might have a basis to claim to own
your changes? Do you attend a school which might make such a claim?]



[For the copyright registration, what country are you a citizen of?]



[What year were you born?]



[Please write your email address here.]



[Please write your postal address here.]




[Which files have you changed so far, and which new files have you written
so far?]

今後

去年感じたのは、なんとなく自分/自分たちのやっていることがあまり周りに伝わっていないなあということでした。エンジニアに対してはともかく、エンジニア以外の人に、自分たちのやっていることって伝わっているのかなあっていう疑問がもんもんとしてありました。 こんな感じでちょこちょこコミットログを中心に、自分の名前をもっと残していくことと、それをエンジニアだけじゃなくいろいろな人に知ってもらうことを今年の目標とします。

S.H.フィギュアーツ 仮面ライダータイガ

S.H.フィギュアーツ 仮面ライダータイガ