emacs内にlocal-twitter的なものを創った。

追記

  • 上から下に挿入していくのを止めて、下から上に上がっていくようにした。(上の方が最近、下の方が過去)
  • use-local-mapを使っていたせいで、post-to-buferを実行した後key-mapが変更されてしまっていた。
    • read-from-minibufferはkey-mapを引数として取れるので、use-local-maoは存在自体いらない。

以下本文

ちょっとしたメモを取るときにtimelineも一緒に挿入されるとうれしい。
でも、twitterにpostするときに生じるwait-timeが煩わしい。
そんなわけで、emacs内でtwitter的な形式でメモを取れるようにした。*1

;;key-chordを有効にしていなければ...
(require 'key-chord)
(setq key-chord-two-keys-delay 0.04)
(key-chord-mode 1)
;;

;;post-to-buffer
(defvar post-to-buffer-func ;何かbuffer名を返すような関数を
  (lambda ()  (file-name-nondirectory (get-last-file "~/memo" "notice"))))

(defvar post-to-buffer-marker "==from-post-to-buffer==")
	;;この変数に格納されている文字列以降にメモが挿入されていく

(defsubst post-content-to-buffer--insert-content (from-buf content)
  (insert (current-time-string) ": " "[[" from-buf "]]\n")
  (dolist (line (cdr (split-string content "\n")))
    (insert* "  " line)))
  
(defsubst post-content-to-buffer--find-position ()
  (goto-char (point-min))
  (cond ((re-search-forward post-to-buffer-marker nil t 1)
	 (forward-char 1))
	(t
	 (insert* post-to-buffer-marker)
	 (goto-char (point-max)))))
 
(defun post-content-to-buffer (buf content)
  (let1 old-buf (or (buffer-file-name) (buffer-name (current-buffer)))
    (with-current-buffer buf
      (save-excursion
	(post-content-to-buffer--find-position)
	(post-content-to-buffer--insert-content old-buf content))))
  (message "posted"))


(defun post-to-buffer () (interactive)
  (let* ((buf (funcall post-to-buffer-func))
	 (map (copy-keymap minibuffer-local-map)))
    (define-key map (kbd "RET") 'newline)
    (define-key map "\C-c\C-c" 'exit-minibuffer)
    ;(use-local-map map)
    (let1 message (read-from-minibuffer buf "\n" map)	
      (post-content-to-buffer buf message)))	 
  )

(defun post-to-buffer-region (beg end) (interactive "r")
  (let1 buf (funcall post-to-buffer-func)
  (post-message-to-buffer buf (buffer-substring beg end))))

(key-chord-define-global "po" 'post-to-buffer)

これで、pとoのキーを同時に押したあと、文章を書いて"C-c C-c"でメモがとれる。

追記

let1は自分で定義したんだった。

(defmacro let1 (var val &rest body)
  `(let ((,var ,val))
     ,@body))
(put 'let1 'lisp-indent-function 2)

insert*

(defsubst insert* (&rest strs)
  (apply 'insert strs)
  (insert "\n"))

get-last-file

(require 'cl)
(defun file-name-file-number (file)
  (let ((base (file-name-nondirectory file)))
    (when (string-match "[0-9]+" base)
      (string-to-number (match-string 0 base)))))

(defun compare-by-file-number (file1 file2)
  (> (file-name-file-number file1)
     (file-name-file-number file2)))

(defun get-last-file (dir file-part)
  (let* ((l (loop for file in (directory-files dir)
		  if (string-match-p file-part file)
		  collect file))
	 (base (car (sort l 'compare-by-file-numbe))))
    (when base (expand-file-name base dir))))

*1:他の人の発言などは存在しないけれど