Entered on [2017-12-24 Sun 14:08]
(let* ((l (benchmark-run (sleep-for .2)))
(total (nth 0 l))
(gc (nth 1 l))
(gc-total (nth 2 l)))
(list total gc gc-total))
(pcase-let ((`(,total ,gc ,gc-total)
(benchmark-run (sleep-for .2))))
(list total gc gc-total))
(seq-let (total gc gc-total) (benchmark-run (sleep-for .2))
(list total gc gc-total))
(-let (((total gc gc-total)
(benchmark-run (sleep-for .2))))
(list total gc gc-total))
Entered on [2017-12-25 Mon 11:43]
根据参数的类型自动选择不同的方法。
(cl-defgeneric foo-size (x)
"Return the size of x.")
(cl-defmethod foo-size ((s string))
"Return the size of the string S."
(length s))
(cl-defmethod foo-size ((b buffer))
"Return the size of the buffer B."
(buffer-size b))
(foo-size "hello")
(with-temp-buffer
(insert "hello")
(foo-size (current-buffer)))
Entered on [2017-12-27 Wed 14:52]
(bar baz qux quux corge grault garply waldo fred plugh) (bar baz qux quux corge thud grault garply waldo fred xyzzy plugh)
and ignore white spaces can be userful
(setq ediff-diff-options "-w")
Sexp-diff like mode for elisp source diffing - Emacs Stack Exchange
Entered on [2017-12-29 Fri 21:41]
cl-block/cl-return is like catch/throw
(catch 'found
1
2
(throw 'found 100)
3)
(cl-block nil
1
2
(cl-return 100)
3)
cl-defun/cl-dotimes/etc implies cl-block
(cl-defun foo ()
1
2
(cl-return-from foo 100)
3)
(foo)
(let (res)
(cl-dotimes (i 10000)
(if (< i 4)
(push i res)
(cl-return)))
(nreverse res))
Entered on [2017-12-30 Sat 14:13]
Like shell/eshell/comint, find a way to move point (for example, C-b
(backward-char
)) within the prompt then mark-copy as usual.
echo area - How to copy minibuffer contents? - Emacs Stack Exchange
Entered on [2018-01-04 Thu 00:58]
Use make-hash-table
(make-hash-table :test #'equal)
Use the printed representation
#s(hash-table test equal data (:one 1 :two 2))
Add and lookup
(let ((hash (make-hash-table :test #'eq)))
(puthash :one 1 hash)
(puthash :two 2 hash)
(list :one (gethash :one hash)
:two (gethash :two hash)))
Remove
(let ((hash #s(hash-table test eq data (:one 1 :two 2))))
(remhash :one hash)
hash)
Clear (remove all)
(let ((hash #s(hash-table test eq data (:one 1 :two 2))))
(clrhash hash)
hash)
Lookup all
(let (alist)
(maphash
(lambda (key value)
(push (cons key value) alist))
#s(hash-table data (:one 1 :two 2)))
alist)
Count
(hash-table-count #s(hash-table data (a 1 b 2)))
Keys & Values (hash-table-keys and hash-table-values is defined by subr-x.el)
(hash-table-keys #s(hash-table data (one 1 two 2 three 3)))
(hash-table-values #s(hash-table data (one 1 two 2 three 3)))
Performance (vs Alist)
(let ((alist nil)
(hash (make-hash-table :test #'eq)))
(mapatoms
(lambda (symbol)
(let ((key symbol)
(val (length (symbol-name symbol))))
(push (cons key val) alist)
(puthash key val hash))))
(let ((t1 (car (benchmark-run 1000 (assq 'length alist))))
(t2 (car (benchmark-run 1000 (gethash 'length hash)))))
(message "Alist takes %.5fs, Hash Table takes %.5fs" t1 t2)))
Entered on [2018-01-07 Sun 01:54]
Modify element of list
(let ((l '(0 1 2 3 4 5 6)))
(setf (nth 3 l) 100)
l)
(let ((l '(0 1 2 3 4 5 6)))
(setcar (nthcdr 3 l) 100)
l)
Move point
(macroexpand '(setf (point) (point-min)))
cl-callf
(let ((l '(0 1 2 3 4 5 6)))
(cl-callf + (nth 3 l) 100)
l)
(let ((alist '((one . 1)
(two . 2)
(thr . 3)
(fou . 4))))
(setf (alist-get 'one alist) 100)
(cl-callf + (alist-get 'two alist) -2)
alist)
Define new setf form
(gv-define-setter length (val x) `(substring ,x 0 ,val))
(setf (length "hello") 2)
Entered on [2018-01-07 Sun 15:55]
info:elisp#Recursive Editing
在 Emacs command loop 中运行另外一个 command loop,比如 ediff-regions-wordwise
中间需要让用户选中两个区域,就可以用 recursive-edit
,Debug 和 Isearch 等地方也有用到。
举个例子,我需要让用户从 Dired 中选中一个文件来处理:
(defun foo ()
(interactive)
(dired ".")
(message
(substitute-command-keys
"When done, type \\[exit-recursive-edit]. Use \\[abort-recursive-edit] to quit"))
(recursive-edit)
(message "You have picked '%s'" (dired-get-filename)))
Entered on [2018-01-09 Tue 16:56]
(progn
(unwind-protect
(recursive-edit)
(message-box "Always run"))
(message-box "Only run with 'C-M-c' ('exit-recursive-edit')")
nil)
(progn
(condition-case nil
(recursive-edit)
(quit (message-box "Only run with 'C-]' ('abort-recursive-edit')")))
(message-box "Always run")
nil)
(progn
(condition-case err
(recursive-edit)
(quit
(message-box "Only run with 'C-]' ('abort-recursive-edit')")
(signal (car err) (cdr err))))
(message-box "Only run with 'C-M-c' ('exit-recursive-edit')")
nil)
Entered on [2018-01-09 Tue 21:29]
添加:
(advice-add #'emacs-version :filter-return #'upcase)
(advice-add #'emacs-version :filter-return #'nreverse)
(advice-add #'emacs-version :filter-return (lambda (x) (concat "=> " x)))
检查:
(defun chunyang-function-advices (symbol)
(let (advices)
(advice-mapc
(lambda (f _)
(push f advices))
symbol)
(nreverse advices)))
(chunyang-function-advices 'emacs-version)
删除:
(advice-mapc
(lambda (f _)
(advice-remove 'emacs-version f))
'emacs-version)
(chunyang-function-advices 'emacs-version)
Entered on [2018-01-11 Thu 17:42]
;; * Define structure
(cl-defstruct person
name
age
sex)
=> person
;; * Make object of structure
(setq P (make-person :name (rot13-string user-full-name)
:age 99
:sex "TWFsZQ=="))
=> #s(person "Kh Puhalnat" 99 "TWFsZQ==")
;; * Access slots
(person-name P)
=> "Kh Puhalnat"
(person-age P)
=> 99
(person-sex P)
=> "TWFsZQ=="
;; * Change slots
(cl-callf + (person-age P) 100)
=> 142
(person-age P)
=> 142
(setf (person-name P) (md5 user-full-name))
=> "670a835cea7294c07ccb015c6ec651dd"
(person-name P)
=> "670a835cea7294c07ccb015c6ec651dd"
;; * Type Check
(person-p P)
=> t
;; * Create object using printd representation
(let ((not-me #s(person "某某" 22 "Unknown")))
(person-p not-me))
=> t
Entered on [2018-01-11 Thu 18:47]
(let ((x1 +1) (x2 +2) (x3 +3)
(y1 -1) (y2 -2) (y3 -3))
(cl-psetq x1 y1
y1 x1
x2 y2
y2 x2
x3 y3
y3 x3)
(list (list x1 x2 x3) (list y1 y2 y3)))
(let ((a 1) (b 2) (c 3)
(x -1) (y -2) (z -3))
(cl-rotatef a x)
(cl-rotatef b y)
(cl-rotatef c z)
(list (list a b c) (list x y z)))
(defmacro chunyang-swap-varsf (vars-1 vars-2)
(cons 'cl-psetf
(cl-loop for x in vars-1
for y in vars-2
append (list x y y x))))
(let ((a 1) (b 2) (c 3)
(x -1) (y -2) (z -3))
(chunyang-swap-varsf (a b c) (x y z))
(list (list a b c) (list x y z)))
Entered on [2018-02-18 Sun 15:44]
For example, get parent directory
(file-name-nondirectory
(directory-file-name
(file-name-directory
"~/.emacs.d/init.el")))
(thread-first "~/.emacs.d/init.el"
file-name-directory
directory-file-name
file-name-nondirectory)
(thread-last "~/.emacs.d/init.el"
file-name-directory
directory-file-name
file-name-nondirectory)
Entered on [2018-02-21 Wed 02:20]
(with-temp-buffer
(thunk-let ((a (insert "1"))
(b (insert "2")))
(insert "3")
b
a)
(buffer-string))
Entered on [2018-02-23 Fri 18:27]
(read-answer
"Are you sure? "
'(("yes" ?y "perform the action")
("no" ?n "skip to the next")
("all" ?! "accept all remaining without more questions")
("help" ?h "show help")
("quit" ?q "exit")))
Entered on [2018-03-21 Wed 15:41]
(assq (make-symbol "one") '((one . 1)))
=> nil
(assq (intern "one") '((one . 1)))
=> (one . 1)
(let ((alist (list (cons (make-symbol "one") 1))))
(list (assq 'one alist)
(assq (make-symbol "one") alist)
(assq (intern "one") alist)))
=> (nil nil nil)
(eq (intern "foo") (intern "foo"))
=> t
(eq (make-symbol "foo") (make-symbol "foo"))
=> nil
Entered on [2018-03-22 Thu 15:00]
(oref (epkg "magit") homepage)
info:epkg#Using Epkg Objects
Entered on [2018-03-23 Fri 13:04]
获得
(interactive-form 'find-file)
重用
(eval (cadr (interactive-form 'find-file)))
在某些特殊情况下,指的是没经过 byte-compile 和用 list 构造,甚至能选择重用哪一部分
(defun foo (string number)
(interactive (list (read-string "String: ")
(read-number "Number: "))))
(interactive-form 'foo)
(pcase-let ((`(interactive (list ,string ,number))
(interactive-form 'foo)))
(list string number))