请问,你是如何使用Emacs的原生键位的?

最近用上了Emacs原生键位,感觉还行,就是突然写代码,也有一种轻松的感觉了。

请问你是如何使用Emacs的原生键位,我在外网上看到那些博主,用Emacs原生键位写代码的感觉不输evil键位,而且Evil还要改键什么的,我想的是直接换改Emacs原生键位。

有没有什么技巧,或者最佳实践?就是原生键位,对文档操作的,技巧。

感谢!

1 个赞

我就是用原生的,基本不改键。Ctrl 在机械键盘上就用手掌外侧,小指根部的肌肉按,习惯后基本感觉不到Ctrl 的存在。

最近在 MacBook 上用的多,Ctrl 用大拇指按,大范围移动靠 avy(绑定了 C-;)以及触摸板像素滚动。台式机也用鼠标滚文档,为了保护手指,我不追求全键盘,让手指能够有休息时间。

M-j 绑定到了 join-line,默认是M-^,不好按。

关于按键操作,直接用就行了,把官方的指南操作一遍。不熟悉的话,开始可以安装 which-key。我现在连这个包也不用了,embark 这个包推荐使用,它也有查按键的功能。

其实很多时候会直接用 M-x 找命令,如果安装了 vertico + orderless 类似的包,找命令比按快捷键还要快。

4 个赞

请问下,Emacs的默认键位,有没有像Vim的那样的组合式操作,可以快速编辑文档的技巧。

我需要一个Emacs的编辑文档的操作指南,就是我不知道我用的这点键位就是Emacs Tutorial的键位教学,就是编辑功能的全部了吗。

能否有什么Emacs键位 编辑文档的文章推荐。

感谢!

C-h t 读一遍,尝试操作一下就好了。Emacs 的基本操作都在这里,不用很多时间就走完。也有中文版的,我忘记怎么开出来了。

还有忘记按键的话,也在按了前缀(比如 C-x)后按 ?键,弹出一个按键列表。

新手的话最好装一个 which-key

2 个赞

好的,其实我就是读的Tutorial,我以为 emacs还会有什么Tutorial之外的操作技巧。 :grinning_face_with_smiling_eyes:

感谢

其他技巧就后面慢慢积累了,可以多看看本论坛,很多人分享。

你可以在使用过程中,遇到具体的需求,不清楚了,来论坛先搜索,实在找不到答案的话,就开贴提问,一个帖子一个问题。应该有很多大佬可以帮到你。

1 个赞

原生键位上which-key,或者自定义hydra集合,常用的建议还是绑定C-x,另外默认如kill-ring kill-region什么的都要advise一翻才顺手。另外建议可以用colemak布局,跟emacs非常搭。另外还可以左边Alt和Ctrl互换,我用了近十年,告别小指疼。

1 个赞

Emacs 的原生键位本来就强于 vim 的那一套切换来切换去的模式按键,唯一的缺点是比较废小拇指。

自己用的时候实际上可以跟模式按键搭着使用,比如编辑的时候以 Emacs 按键为主,移动或者阅读代码的时候可以配合上模式按键,具体怎么搭还是要根据自己的实际情况来定。

4 个赞

text object相关的技巧,可以用evil的api(如evil-define-text-object)写自己的text object.

这里有几个自定义text object的例子,

其他技巧就是拼插件了.可以从melpa上下载最多的插件看起,

最好是看插件官方文档和代码. 通用的入门教程不可能在每个插件上做深入讲解.

2 个赞

在用 Evil 之前,主要是通过 xcape 将 Ctrl 和 Space 合并成同一个按键。

然后是:

(global-set-key (kbd ", ,") (lambda () (interactive) (insert ",")))
(global-set-key (kbd ", SPC") (lambda () (interactive) (insert ", ")))
(global-set-key (kbd ", RET") (lambda () (interactive) (insert ",") (newline)))

将逗号接空格绑定为输入一个逗号和空格,因为绝大多数写代码的时候,输入了逗号后面都应该接空格或回车。

这样就多出非常多以逗号开头的键绑定可以用了。

God mode

1 个赞

右ctrl和大小写换下就好了,mac和win都这么搞了,省事不少

1 个赞

熟悉的代码,看来用号当快捷键的人还是不少的。感觉这个 结合hydra 就大部分快捷键问题都可以解决了

1 个赞

Meow + one-key,基本上不要同时多个键一起按,按顺序按就好了。

(defun meow-setup ()
  (meow-motion-overwrite-define-key
   '("j" . meow-next)
   '("k" . meow-prev))
  (meow-leader-define-key
   ;; SPC j/k will run the original command in MOTION state.
   '("j" . "H-j")
   '("k" . "H-k")
   ;; Use SPC (0-9) for digit arguments.
   '("1" . meow-digit-argument)
   '("2" . meow-digit-argument)
   '("3" . meow-digit-argument)
   '("4" . meow-digit-argument)
   '("5" . meow-digit-argument)
   '("6" . meow-digit-argument)
   '("7" . meow-digit-argument)
   '("8" . meow-digit-argument)
   '("9" . meow-digit-argument)
   '("0" . meow-digit-argument)
   '("/" . meow-keypad-describe-key)
   '("?" . meow-cheatsheet))
  (meow-normal-define-key
   '("0" . meow-expand-0)
   '("9" . meow-expand-9)
   '("8" . meow-expand-8)
   '("7" . meow-expand-7)
   '("6" . meow-expand-6)
   '("5" . meow-expand-5)
   '("4" . meow-expand-4)
   '("3" . meow-expand-3)
   '("2" . meow-expand-2)
   '("1" . meow-expand-1)
   '("-" . negative-argument)
   '(";" . meow-reverse)
   '("," . meow-inner-of-thing)
   '("." . meow-bounds-of-thing)
   '("[" . meow-beginning-of-thing)
   '("]" . meow-end-of-thing)
   '("a" . meow-append)
   '("A" . meow-open-below)
   '("b" . meow-back-word)
   '("B" . meow-back-symbol)
   '("c" . meow-change)
   '("d" . meow-delete)
   '("D" . meow-backward-delete)
   '("e" . meow-next-word)
   '("E" . meow-next-symbol)
   '("f" . meow-find)
   '("g" . meow-cancel-selection)
   '("G" . meow-grab)
   '("h" . meow-left)
   '("H" . meow-left-expand)
   '("i" . meow-insert)
   '("I" . meow-open-above)
   '("j" . meow-next)
   '("J" . meow-next-expand)
   '("k" . meow-prev)
   '("K" . meow-prev-expand)
   '("l" . meow-right)
   '("L" . meow-right-expand)
   '("m" . meow-join)
   '("n" . meow-search)
   '("o" . meow-block)
   '("O" . meow-to-block)
   '("p" . meow-yank)
   '("q" . meow-quit)
   '("Q" . meow-goto-line)
   '("r" . meow-replace)
   '("R" . meow-swap-grab)
   '("s" . meow-kill)
   '("t" . meow-till)
   '("u" . undo)
   '("U" . undo-redo)
   ;; '("u" . meow-undo)
   ;; '("U" . meow-undo-in-selection)
   '("v" . meow-visit)
   '("w" . meow-mark-word)
   '("W" . meow-mark-symbol)
   '("x" . meow-line)
   '("X" . meow-goto-line)
   '("y" . meow-save)
   '("Y" . meow-sync-grab)
   '("z" . meow-pop-selection)
   '("'" . repeat)
   '("<escape>" . mode-line-other-buffer)))

(add-hook 'after-init-hook 'meow-setup)

(meow-global-mode)

(setq meow-use-clipboard t)

(add-to-list 'meow-mode-state-list '(netease-cloud-music-mode . motion))
(add-to-list 'meow-mode-state-list '(osx-dictionary-mode . motion))
(add-to-list 'meow-mode-state-list '(stock-tracker-mode . motion))
(add-to-list 'meow-mode-state-list '(elfeed-show-mode . normal))
(add-to-list 'meow-mode-state-list '(elfeed-summary-mode . motion))
(add-to-list 'meow-mode-state-list '(helpful-mode . normal))
(add-to-list 'meow-mode-state-list '(calibredb-search-mode . motion))
(add-to-list 'meow-mode-state-list '(Info-mode-hook . motion))

;; (advice-add 'org-edit-special :after 'meow-insert)

(require 'one-key)

(setq one-key-popup-window nil)

(meow-leader-define-key '("a" . my/org-agenda))

(one-key-create-menu
 "BIBTEX"
 '((("a" . "Actions") . orb-note-actions)
   (("o" . "open") . consult-bibtex-open-any)
   (("e" . "entry") . consult-bibtex-show-entry)
   (("n" . "note") . my/edit-notes)
   (("x" . "extract annots") . my/extract-pdf-annots-to-ref-note))
 t)

(meow-leader-define-key '("b" . one-key-menu-bibtex))

(one-key-create-menu
 "DIRECTORY"
 '((("c" . "Cloud") . (lambda () (interactive) (dired "~/Nextcloud/")))
   (("d" . "Downloads") . (lambda () (interactive) (dired "~/Downloads/")))
   (("p" . "Pictures") . (lambda () (interactive) (dired "~/Pictures/"))))
 t)

(meow-leader-define-key '("d" . one-key-menu-directory))

(one-key-create-menu
 "FILE"
 '((("f" . "FINANCE") . one-key-menu-beancount)
   (("r" . "recent") . consult-recent-file)
   (("o" . "open") . one-key-menu-specific-file)
   (("e" . "External") . xah-html-open-in-safari))
 t)

(meow-leader-define-key '("f" . one-key-menu-file))

(one-key-create-menu
 "SPECIFIC-FILE"
 '((("b" . "Blog file") . (lambda () (interactive) (find-file "~/hugo-source/content-org/all-posts.org")))
   (("I" . "README.org") . (lambda () (interactive) (find-file (expand-file-name "README.org" user-emacs-directory))))
   (("i" . "Inbox") . (lambda () (interactive) (find-file (expand-file-name "daily/inbox.org" my-galaxy))))
   (("r" . "rss") . (lambda () (interactive) (find-file (expand-file-name "main/elfeed.org" my-roam))))
   (("g" . "gtd") . (lambda () (interactive) (find-file (expand-file-name "todos/org-gtd-tasks.org" my-galaxy))))
   (("a" . "alipay") . (lambda () (interactive) (find-file (expand-file-name "alipay.bean" my-finance-year))))
   (("m" . "Beancount main") . (lambda () (interactive) (find-file (expand-file-name "main.bean" my-finance)))))
 t)

(one-key-create-menu
 "ORG"
 '((("c" . "Capture") . one-key-menu-org-capture)
   (("d" . "Download") . one-key-menu-download)
   (("p" . "Process") . org-gtd-process-inbox)
   (("P" . "Pomodoro") . org-pomodoro)
   (("l" . "cliplink") . org-cliplink)
   (("i" . "ID") . org-id-get-create)
   (("t" . "Transclusion") . one-key-menu-transclusion))
 t)

(meow-leader-define-key '("o" . one-key-menu-org))

(one-key-create-menu
 "DOWNLOAD"
 '((("c" . "clipboard") . org-download-clipboard)
   (("i" . "image") . org-download-image)
   (("r" . "rename") . org-download-rename-at-point)
   (("s" . "screenshot") . org-download-screenshot))
 t)

(one-key-create-menu
 "TRANSCLUSION"
 '((("a" . "Add") . org-transclusion-add)
   (("A" . "Add all") . org-transclusion-add-all)
   (("r" . "Remove") . org-transclusion-remove)
   (("R" . "Remove all") . org-transclusion-remove-all)
   (("g" . "Refresh") . org-transclusion-refresh)
   (("m" . "make") . org-transclusion-make-from-link)
   (("o" . "Open") . org-transclusion-open-source)
   (("e" . "Edit") . org-transclusion-live-sync-start))
 t)

(one-key-create-menu
 "ORG-CAPTURE"
 '((("d" . "Diary") . (lambda () (interactive) (my/org-capture-shortcut "d")))
   (("t" . "Today tasks") . (lambda () (interactive) (my/org-capture-shortcut "tt")))
   (("T" . "Date tasks") . (lambda () (interactive) (my/org-capture-shortcut "td")))
   (("i" . "Inbox") . (lambda () (interactive) (my/org-capture-shortcut "i")))
   (("r" . "Random note") . (lambda () (interactive) (my/org-capture-shortcut "r")))
   (("s" . "Code Snippet") . (lambda () (interactive) (my/org-capture-shortcut "s"))))
 t)

(one-key-create-menu
 "LANGUAGE"
 '((("t" . "Translate") . gts-do-translate)
   (("f" . "Fanyi Point") . fanyi-dwim2)
   (("F" . "Fanyi Input") . fanyi-dwim)
   (("d" . "Dictionary Point") . osx-dictionary-search-pointer)
   (("D" . "Dictionary Input") . osx-dictionary-search-input)
   (("t" . "Thesaurus") . powerthesaurus-lookup-dwim)
   (("s" . "Style region") . smog-check)
   (("S" . "Style buffer") . smog-check-buffer))
 t)

(meow-leader-define-key '("l" . one-key-menu-language))

(one-key-create-menu
 "ROAM"
 '((("a" . "Alias") . one-key-menu-roam-alias)
   (("b" . "Roam Buffer") . my/org-roam-buffer-turn-on-off)
   (("c" . "Roam capture") . org-roam-capture)
   (("d" . "Dailies") . one-key-menu-roam-dailies)
   (("f" . "Node find") . org-roam-node-find)
   (("i" . "Node insert") . org-roam-node-insert)
   (("s" . "Search content") . bms/org-roam-rg-search)
   (("t" . "Tags") . one-key-menu-roam-tags)
   (("r" . "Ref") . one-key-menu-roam-ref)
   (("u" . "UI") . one-key-menu-roam-ui))
 t)

(meow-leader-define-key '("r" . one-key-menu-roam))

(one-key-create-menu
 "ROAM-ALIAS"
 '((("a" . "Add") . org-roam-alias-add)
   (("r" . "Remove") . org-roam-alias-remove))
 t)

(one-key-create-menu
 "ROAM-DAILIES"
 '((("t" . "Today") . org-roam-dailies-find-today)
   (("y" . "Yesterday") . org-roam-dailies-find-yesterday)
   (("d" . "Directory") . org-roam-dailies-find-directory)
   (("j" . "Date") . org-roam-dailies-goto-date)
   (("p" . "Past Diary") . my/history-morning-diary))
 t)

(one-key-create-menu
 "ROAM-REF"
 '((("a" . "Add") . org-roam-ref-add)
   (("f" . "Find") . org-roam-ref-find)
   (("r" . "Remove") . org-roam-ref-remove))
 t)

(one-key-create-menu
 "ROAM-TAGS"
 '((("a" . "Add") . org-roam-tag-add)
   (("c" . "Completion") . org-roam-tag-completions)
   (("r" . "Remove") . org-roam-tag-remove))
 t)

(one-key-create-menu
 "ROAM-UI"
 '((("o" . "Open") . org-roam-ui-open)
   (("l" . "Local") . org-roam-ui-node-local)
   (("z" . "Zome") . org-roam-ui-node-zoom)))

(one-key-create-menu
 "WINDOWS"
 '((("d" . "Destroy") . kill-this-buffer)
   (("h" . "Left") . windmove-left)
   (("j" . "Down") . windmove-down)
   (("k" . "Up") . windmove-up)
   (("l" . "Right") . windmove-right)
   (("e" . "Email") . mu4e)
   (("r" . "RSS") . elfeed-summary)
   (("t" . "Telega") . telega)
   (("m" . "Message") . (lambda () (interactive) (switch-to-buffer "*Messages*")))
   (("s" . "scratch") . (lambda () (interactive) (switch-to-buffer "*scratch*")))
   (("u" . "Winner Undo") . winner-undo)
   (("v" . "vundo") . vundo))
 t)

(meow-leader-define-key '("w" . one-key-menu-windows))

(one-key-create-menu
   "TOOLS"
   '((("o" . "Outline") . consult-outline)
     (("m" . "Menu") . my/imenu-list-on-off))
   t)

(meow-leader-define-key '("t" . one-key-menu-tools))

(one-key-create-menu
   "BLOG"
   '((("h" . "Easy hugo") . easy-hugo)
     (("n" . "New post") . easy-hugo-newpost)
     (("g" . "Magit") . easy-hugo-magit)
     (("p" . "note") . easy-hugo-preview)
     (("t" . "Tags") . easy-hugo-complete-tags))
   t)
3 个赞

模式化主要是增加了一个维度,解放了出来很多可以 map 的键。复杂场景下不可能沿用一套按键的,在一个场景下适用的按键在另一个场景下就显得格格不入。

正确的做法应该是场景化绑定或者说上下文绑定。在不同 buffer、window、文件类型… 甚至同一buffer 不同段落等各自有其特定含义(感觉是不是和 button、switch 等“现代”元素很像?),并尽量向语义化、易记易发现方面靠拢。

这样不可避免地带来一些困惑,这些困惑可能来自用户没有意识到 context 已经切换,可能来自默认绑定不符合用户期望… 这些困惑怎么解决?答案是感官反馈。比如把光标形状从指针换成细线/十字,背景色文字颜色,增加 panel、button 等…甚至 notification、beep 声等。这点上 vim/emacs 等很多人因为是自用的配置,不会过多去关注。

通用型应用为了照顾大多数,一般很少向用户强调 context 切换。但 context 切换这一事实是真实存在的,正如复杂性不可能凭空消失一样。当然,一些用户因为自身需求并不想 context 切换,也不想理解 context 切换。这是自身需求决定的,并没有高下之分。

但如果你想要你的应用如手术刀一般精确,你应该适应 context 切换,并尝试定制自己的工作流。

3 个赞

因为逗号用右手中指输入,是最轻松的一个非字母按键。

1 个赞

按下一个(组合)键,(选中)按下右键鼠标,点按 panel 中一个 button,滚动到 buffer 某 viewport,本质上都属于 context 切换。Emacs 在感官反馈呈现形式是很强的,可以深度定制极大地降低学习成本减少困惑。但是很多功能没有内置需要额外包,或者没有很方便的 ad-hoc override 输入方式,这点对比 Vim 通常只需要输入一行命令,多数配置都是内置 api 调用几乎没有自定义函数,非常易懂,这是它做得好的地方。

1 个赞

用了几年vim,最近才了解到 text object 这个概念,思路突然清晰了很多

1 个赞

最近发现用key-chord 设置成 空格和其他按键 的组合,突然感觉多了好多有用的按键。

1 个赞

text object? 就是yw, cw什么的吧,扩展到操作() {}之类? emacs也有类似的东西,有个easy-kill可以实现copy这些对象,easy-mark可以选中这些对象,然后可以执行vim的y/d/c之类的命令了。不过我还是习惯无脑expand region选中再操作。

1 个赞