cireu
11
用了下common-lisp-indent-function
大部分时间可以正确handle,不过偶尔会抽风挺不爽的,缩进cl-flet
的时候比普通lisp-indent-function好看
common-lisp-indent-function
(cl-flet ((update-db! ()
;; The copy is necessary because our SQL query action
;; may conflicts with running Firefox.
(copy-file counsel-ffdata-database-path
counsel-ffdata--temp-db-path)
(clrhash counsel-ffdata--cache)))
(let* ((path counsel-ffdata--temp-db-path))
(condition-case e
(if (file-exists-p path)
(when force-update?
(delete-file path)
(update-db!))
(update-db!))
(error "Failed to ensure firefox database: %s" e))
nil))
lisp-indent-function
(cl-flet ((update-db! ()
;; The copy is necessary because our SQL query action
;; may conflicts with running Firefox.
(copy-file counsel-ffdata-database-path
counsel-ffdata--temp-db-path)
(clrhash counsel-ffdata--cache)))
(let* ((path counsel-ffdata--temp-db-path))
(condition-case e
(if (file-exists-p path)
(when force-update?
(delete-file path)
(update-db!))
(update-db!))
(error "Failed to ensure firefox database: %s" e))
nil))
对,但是我懒得折腾,而且也不是所有人都很讲究,缩进不一样需要协作时就会难受。
我自己一般取个折中写法:
(cl-flet ((mean
(numbers)
(/ (apply #'+ numbers)
(float (length numbers)))))
(mean '(1 2 3 4)))
cireu
13
总的来说还是利大于弊
(cl-defun func (&whole
whole-args
normal args
&optional
optionA
&key
keyA
keyB
&allow-other-keys
&rest
rest-part))
lisp-indent-function没法漂亮缩进带上CL扩展的参数列表
git hooks强制就好了,哈哈
common-lisp-indent-function
的确大部分时候表现良好,但我已经忘了为何我用了一段时间之后放弃了。
我现在回到 lisp-indent-function
,但是针对 plist 做了些改进。
以前:
;; '(:a 1
;; :b 2
;; :c 3)
现在:
;; '(:a 1
;; :b 2
;; :c 3)
冒号不对齐太难受了。
cireu
15
给lisp-indent-function
写handler只有两个参数:发生缩进的位置(一般是行首)parse-partial-sexp
的返回值,不是人用的。
lisp-indent-function
最难受的是不能很好识别和缩进带keyword的参数列表,比如
(propertize icon 'face `(:inherit ,face
:height 1.1)
默认显示为
(propertize icon 'face `(:inherit ,face
:height 1.1)
最后找了个改装版本才搞定。
我现在用的 indent 函数是抄来的,能偷懒则偷懒:.emacs.d/redef.el at af82072196564fa57726bdbabf97f1d35c43b7f7 · Fuco1/.emacs.d · GitHub
parse-partial-sexp
我需要把 docstring 贴在旁边作为注释,或者:
(let* ((st (parse-partial-sexp (point-min) (point)))
(depth (nth 0 st))
(start-of-innermost (nth 1 st))
(start-of-last-sexp (nth 2 st))
(inside-a-string? (nth 3 st))
...
))
cireu
18
不如直接用模式匹配
(pcase (parse-partial-sexp)
(`(,depth ,start-of-inner-most ,start-of-last-sexp ,inside-str? . ,rest)))
就你这个例子,可以转而用 list
绕过这个问题(如果非要换行的话,我一定会这么干)。
每个地方都加list很麻烦啊。
之前我是用的这个方案:
(propertize icon 'face `(:inherit
,face
:height
1.1)
pcase 的确很好用,但是也要看场合,这是我某个包中的真实代码:
(let* ((st (parse-partial-sexp (point-min) (point)))
(depth0? (eq 0 (nth 0 st)))
(start-of-innermost (nth 1 st))
(at-string? (nth 3 st))
(cst (car (syntax-after (point)))) ;; See (info "(elisp) Syntax Table Internals") for more
(lparens? (eq 4 cst)) ;; "("
(rparens? (eq 5 cst)) ;; ")"
(at-string-end? (and at-string? (eq 7 cst)))
(beg (if (and depth0? (not (and at-string?
(not at-string-end?))))
(if lparens?
(point))
(if (or (not at-string?)
at-string-end?)
start-of-innermost))))
...)
我并不是总是直接使用 parse-partial-sexp
的返回值,也没有顺序/全部使用,而是挑选了其中某些值计算之后再拿来用,而且我希望在一个 let
中搞定。
`
有时候也麻烦,如果效果跟 list
一样,用哪个都可行。
你这个方案可行,应该不少人都会这么办,还有实在不行就这么写:
(
:foreground "red"
:background "white")
然后再加一句注释来吐槽默认的缩进。
对,不知道为什么默认是这一种效果。我以前也采用过你说的这种方案。对于强迫症来说都不完美,最后用了上面说的那个改装版解决了这个问题。
pcase 如何跳跃式取值? 例如:
(let ((n (nth 5 '(1 2 3 4 5 6 7 8 9 0))))
n)
pcase 必须一格一格地数着跳过:
(pcase-let ((`(,_ ,_ ,_ ,_ ,_ ,n . ,_) '(1 2 3 4 5 6 7 8 9 0)))
n)
还是有更简便的写法?
cireu
27
没办法,毕竟是模式匹配。只能用wildcard跳过
用 seq
Pattern 写法要简单些:
(pcase (stream-range)
((seq _ _ _ _ _ n) n))
;; => 5
(stream-range) 表示自然数序列,需要安装 stream.el
还有一个办法是 File / Dir Local variable 里专门设置 lisp-indent-function
,我没折腾过,感觉可行?
File / Dir Local variable 就是用来协同作业的吧,记得以前代码常常会加上两行:
/* -*- mode: c++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
.dir-locals.el
可以写更多,把缩进规则一条一条加进去,但冒号关键字缩进似乎无法简单通过配置来解决。
前面用的那个缩进函数偶尔还是会出错:
(foo :a
1
:b
2
:c
3)
而且这个函数看起来挺复杂,我干脆自己写了一个 lisp-keyword-indent 包,用来应对:
和&
关键字的缩进,也实现了#13楼的锯齿效果。代码总量比单个函数略有增加,但是可配置,自己看得懂,容易扩展。
UPDATE
我错了,目前我的代码其实比那单个函数较少,逐步完善之后应该会超过。