Emacs
的原生键位本来就强于 vim
的那一套切换来切换去的模式按键,唯一的缺点是比较废小拇指。
自己用的时候实际上可以跟模式按键搭着使用,比如编辑的时候以 Emacs
按键为主,移动或者阅读代码的时候可以配合上模式按键,具体怎么搭还是要根据自己的实际情况来定。
Emacs
的原生键位本来就强于 vim
的那一套切换来切换去的模式按键,唯一的缺点是比较废小拇指。
自己用的时候实际上可以跟模式按键搭着使用,比如编辑的时候以 Emacs
按键为主,移动或者阅读代码的时候可以配合上模式按键,具体怎么搭还是要根据自己的实际情况来定。
text object相关的技巧,可以用evil的api(如evil-define-text-object
)写自己的text object.
这里有几个自定义text object的例子,
其他技巧就是拼插件了.可以从melpa上下载最多的插件看起,
最好是看插件官方文档和代码. 通用的入门教程不可能在每个插件上做深入讲解.
在用 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
右ctrl和大小写换下就好了,mac和win都这么搞了,省事不少
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)
模式化主要是增加了一个维度,解放了出来很多可以 map 的键。复杂场景下不可能沿用一套按键的,在一个场景下适用的按键在另一个场景下就显得格格不入。
正确的做法应该是场景化绑定或者说上下文绑定。在不同 buffer、window、文件类型… 甚至同一buffer 不同段落等各自有其特定含义(感觉是不是和 button、switch 等“现代”元素很像?),并尽量向语义化、易记易发现方面靠拢。
这样不可避免地带来一些困惑,这些困惑可能来自用户没有意识到 context 已经切换,可能来自默认绑定不符合用户期望… 这些困惑怎么解决?答案是感官反馈。比如把光标形状从指针换成细线/十字,背景色文字颜色,增加 panel、button 等…甚至 notification、beep 声等。这点上 vim/emacs 等很多人因为是自用的配置,不会过多去关注。
通用型应用为了照顾大多数,一般很少向用户强调 context 切换。但 context 切换这一事实是真实存在的,正如复杂性不可能凭空消失一样。当然,一些用户因为自身需求并不想 context 切换,也不想理解 context 切换。这是自身需求决定的,并没有高下之分。
但如果你想要你的应用如手术刀一般精确,你应该适应 context 切换,并尝试定制自己的工作流。
因为逗号用右手中指输入,是最轻松的一个非字母按键。
按下一个(组合)键,(选中)按下右键鼠标,点按 panel 中一个 button,滚动到 buffer 某 viewport,本质上都属于 context 切换。Emacs 在感官反馈呈现形式是很强的,可以深度定制极大地降低学习成本减少困惑。但是很多功能没有内置需要额外包,或者没有很方便的 ad-hoc override 输入方式,这点对比 Vim 通常只需要输入一行命令,多数配置都是内置 api 调用几乎没有自定义函数,非常易懂,这是它做得好的地方。
用了几年vim,最近才了解到 text object 这个概念,思路突然清晰了很多
最近发现用key-chord 设置成 空格和其他按键 的组合,突然感觉多了好多有用的按键。
text object? 就是yw, cw什么的吧,扩展到操作() {}之类? emacs也有类似的东西,有个easy-kill可以实现copy这些对象,easy-mark可以选中这些对象,然后可以执行vim的y/d/c之类的命令了。不过我还是习惯无脑expand region选中再操作。
text object 和 motion其实还不太一样,你说的通常是motion,一般指的是对从当前光标的位置到motion结束的光标之间的文本进行操作。text object指的是对当前光标所在的区域进行操作,比如当前光标所处的一对括号之内啥的。通常以a为前缀表示包含端点,i为前缀表示不包含端点。基于treesitter可以对程序的syntax作为text object,比如af表示一整段函数,ac表示一整段类之类的操作。
一样的东西,这里 knu/easy-kill-extras.el: Extra functions for easy-kill/easy-mark. (github.com) 还有补充:
(add-to-list 'easy-kill-alist '(?W WORD " ") t)
(add-to-list 'easy-kill-alist '(?\' squoted-string "") t)
(add-to-list 'easy-kill-alist '(?\" dquoted-string "") t)
(add-to-list 'easy-kill-alist '(?\` bquoted-string "") t)
(add-to-list 'easy-kill-alist '(?q quoted-string "") t)
(add-to-list 'easy-kill-alist '(?Q quoted-string-universal "") t)
(add-to-list 'easy-kill-alist '(?\) parentheses-pair-content "\n") t)
(add-to-list 'easy-kill-alist '(?\( parentheses-pair "\n") t)
(add-to-list 'easy-kill-alist '(?\] brackets-pair-content "\n") t)
(add-to-list 'easy-kill-alist '(?\[ brackets-pair "\n") t)
(add-to-list 'easy-kill-alist '(?} curlies-pair-content "\n") t)
(add-to-list 'easy-kill-alist '(?{ curlies-pair "\n") t)
(add-to-list 'easy-kill-alist '(?> angles-pair-content "\n") t)
(add-to-list 'easy-kill-alist '(?< angles-pair "\n") t)
发个easy-kill/easy-mark的使用示例,这里面仅用了easy-mark,easy-kill其实也就mark后直接复制,效果是一样的只不过是直接复制了。 先调用easy-mark,我这里调用时由于默认设置成thing at point的word了,所以是直接选中了当前的word,然后你可以继续按gif里绑定的那些额外的键,如f就是vim里的forward char(我这里没有演示),如果按了上面绑定外的char就退出easy mark/easy kill模式了。
从最开始就一直用emacs本身的快捷键。即便现在用spacemacs,也没用vim模式。从来没觉着不方便啊。
不过ctrl键改到了大小写位置。
感谢陈老师
其实我最想事,还是没有配置的emacs的使用,当然如果我需要配置,为什么不装一堆插件,或者直接用doom emacs呢
其实我的配置内也有一些关于编辑文本的插件,但我感觉还是不太行,因为我本身长时间用evil,最近发现了为什么会乱按jkjkjkkj,因为在模式切换的时候,可能我的思路已经被打断了
然后,现在就是用的是原生的键位。最大的影响还是C-SPC被win占用了,后面打算换到Linux或者BSD。
所以我还是打算用原生的
更好的是想晓得一些善于原生键位的操作方法,就像Vim的组合键一样。