创建一个帖子,记录自己学习 Elisp 的经过

根据大佬给的链接,搜最后的文件名,google 第一个就是的。

Elisp:thing-at-point

通过使用 thing-at-point 功能,从当前 buffer 上的 word、line、text block、file path、buffer 等处里的 text unit 塞进 string。

thing-at-point

(thing-at-point Thing &optional NO-PROPERTIES)

(defun ff ()
  "print current word"
  (interactive)
  (message "%s" (thing-at-point 'word)))

测试: 这里李杀定义了一个命令 ff,是将当前的光标所在的 word 取值,并显示在 minibuffeer 里

光标移动到 point 的末端,然后执行 ff 命令,minibuffer 返回 point 这个单词

Get Boundary Postion of a Thing 知道一个东西的边界

bounds-of-thing-at-point

该函数是返回一个指针所在 text unit 的边界,以 cons cell 的形式 (cons pos1 pos2)

(defun my-get-boundary-and-thing ()
  "example of using `bounds-of-thing-at-point'"
  (interactive)
  (let (bounds pos1 pos2 mything)
	(setq bounds (bounds-of-thing-at-point 'symbol))
	(setq pos1 (car bounds))
	(setq pos2 (cdr bounds))
	(setq mything (buffer-substring-no-properties pos1 pos2))

	(message
	 "thing begin at [%s], end at [%s], thing is [%s]"
	 pos1 pos2 mything)))
1 个赞

Elisp:Get Text Block

李杀举了个例子,作用于 Text Block(这个概念类似于 段落)

    (defun get-text-block-positions ()
      "Return a vector [begin end] of text block,
   Return a vector [begin end] that's the begin and end positions of text block the cursor is in.
  Text block is group of lines separated by blank lines.

  URL `http://xahlee.info/emacs/emacs/elisp_get_text_block.html'
  Version 2020-06-10 2022-01-21"
      (interactive)
      (let ($p1 $p2)
        (save-excursion
          (if (re-search-backward "\n[ \t]*\n" nil "move")
              (progn (goto-char (match-end 0))
                     (setq $p1 (point)))
            (setq $p1 (point)))
          (if (re-search-forward "\n[ \t]*\n" nil "move")
              (progn (goto-char (match-beginning 0))
                     (setq $p2 (point)))
            (setq $p2 (point)))
          (message "%s" (vector $p1 $p2))
          (vector $p1 $p2))))

李杀这个例子,直接把之前的章节串了起来。

2 个赞

Emacs Lisp 简明教程 - 水木社区Emacs版 这个网页版, 也好阅读

(re-search-forward "\n[ \t]*\n" nil "move")
(re-search-forward "^=provide= " (line-end-position) t)

提一个, 我在这里的 「nil」最后用猜的, 也可能那有 介绍过, 我就是没看见, 后来用明白了, 就是不用 搜到 最大, 给个具体位置, 到那就停, 后来 举一反三, string-match 这个后面的 参数, 不是用 0 开始, 是从给的位置开始

1 个赞

终于想到要开发什么功能了。我想给 org-super-links 开发一个 org-super-links-copy 的功能,可以把某个 org 文件里的 headline 复制到另外的 org 文件里去,类似 org-refile——但复制之后,同时两个 headline 之间可以关联起来。

因为我用 Emacs 来整理思考和输出方案,中间存在大量笔记。我曾经有想过要不直接用飞书算了,但是飞书的关联颗粒度很粗,只能做到文档之间的关联,对于平时会做大量项目笔记的我来说,整理方面会比较麻烦。

为了这个问题,在闲下来的时候,想了好几天,今天终于想到一个想做的,哈哈。

2 个赞
(defun my/copy-idlink-to-clipboard ()
    "Copy idlink to clipboard."
    (interactive)
    (when (eq major-mode 'org-agenda-mode) ;switch to orgmode
      (org-agenda-show)
      (org-agenda-goto))
    (when (eq major-mode 'org-mode) ; do this only in org-mode buffers
      (let* ((mytmphead (nth 4 (org-heading-components)))
	     (mytmpid (funcall 'org-id-get-create))
	     (mytmplink (format "[[id:%s][%s]]" mytmpid mytmphead)))
	(kill-new mytmplink)
	(message "Copied %s to killring (clipboard)" mytmplink)))
    (switch-to-buffer (concat (format-time-string "%Y-%m-%d") ".org")))

之前网上抄来的,可以复制 headline ,贴到别的地方去,通过 id 关联。你可以看看。

1 个赞

谢谢,我自己动手想一下怎么实现,不想用 id 关联。

利用 org properties 就可以实现了

借楼问一下, read-regexpread-string 有什么区别吗

可以从日常的一些小功能开始: 比如我经常需要从浏览器复制一个http link, 再复制一下description, 然后变成org 的link,没有现成的命令,就可以自己写一下

  1. 选中两行
  2. 判断哪个是http,哪个是description
  3. 然后组装
  4. 删除选择的region
  5. 插入
  6. 再配一下快捷键就可以了
2 个赞

叶文彬这本书我看了。跟着这本书走一遍,我感觉比学李杀的文章更系统一点,也更简单一点。李杀的文章优点是很容易上手实践,学起来有成就感。

另,官方手册是最详细的,也是最值得学习的资料,缺点是不适合给初学者学习。

2 个赞

很开心,今天成功用了 Hook 机制,将 major-mode 和 minor-mode 绑定。

将 org-stick-header 和 org-mode 绑定在一起,极大地提升了复盘项目文件的条理性。

配置如下:

(use-package org-sticky-header
  :straight (org-sticky-header
			 :type git
			 :host github
			 :repo "alphapapa/org-sticky-header")
  :ensure t)

(add-hook 'org-mode-hook #' (lambda () org-sticky-header-mode 1))

效果如图:

(lambda()) 前使用 #’ 应该是不规范写法,改为:

(add-hook 'org-mode-hook (lambda () (org-sticky-header-mode 1)))

都可以,无所谓,顶多算一点代码风格区别

嗯,我刚刚在 Org-transclusion User Manual 手册的第五部分也见到 #'(lambda()) 的写法了。

(add-hook 'org-transclusion-after-add-functions
          #'(lambda (_beg _end) (org-latex-preview '(16))))

学习到了,感谢指出。

补充1:复习了一下 (lambda ()) 社区约定俗成写法:

“Never hard quote a lambda, it impedes byte-compilation.”

;;; Good
(lambda (x) (car x))

;;; Ok, but redundant.
#'(lambda (x) (car x))

;;; Bad
'(lambda (x) (car x))

这个用 org protocol 加 capture 可能比较方便

问一下,这个函数意思是什么?为何可以返回值较大的那一个?

  (defun our-max (a b)
    (if (> a b) a b))

if is a special form in ‘C source code’.

(if COND THEN ELSE…)

If COND yields non-nil, do THEN, else do ELSE… Returns the value of THEN or the value of the last of the ELSE’s. THEN must be one expression, but ELSE… can be zero or more expressions. If COND yields nil, and there are no ELSE’s, the value is nil.

Probably introduced at or before Emacs version 1.1.

[back]

写成这样,你可能就看的更清楚了。

(defun our-max (a b)
  (if (> a b)
      a
    b))

其实 emacs 有内置的函数 max 来计算最大值, 而且支持更多的参数。