基本编辑操作

进入编辑模式

标准的emacs用户是遇不到这一节的,因为默认就可以编辑。但是spacemacs用户需要先学习一下强大的vi的模式切换功能了。

vi的一个重要特点就是命令特别多,所以一旦学会了效率就非常高。

我们以进入编辑模式为说明一下,大家就清楚了。

有同学说了,切换到编辑模式,只用一条命令,比如i命令,切过去就是了么。从功能上说,是这样的。但是,这样的效率还不够高。

vi中是这样的定义的:

* i:在当前光标之前插入文本

* a: 在当前光标之后插入文本

* A: 在当前行的结尾处插入文本

* I: 在当前行的开始处插入文本

* o: 在光标位置的下一行加一个新行插入文本

* O: 在光标位置的上一行加一个新行插入文本

* s: 删除光标所在位置的字符,再进行插入

* S: 删除光标所在行,再进行插入

* R: 用新的字符替换现有的字符

在evil的实现中,i对应的是evil-insert函数:

(defun evil-insert (count &optional vcount skip-empty-lines)
  (interactive
   (list (prefix-numeric-value current-prefix-arg)
         (and (evil-visual-state-p)
              (memq (evil-visual-type) '(line block))
              (save-excursion
                (let ((m (mark)))
                  ;; go to upper-left corner temporarily so
                  ;; `count-lines' yields accurate results
                  (evil-visual-rotate 'upper-left)
                  (prog1 (count-lines evil-visual-beginning evil-visual-end)
                    (set-mark m)))))
         (evil-visual-state-p)))
  (if (and (called-interactively-p 'any)
           (evil-visual-state-p))
      (cond
       ((eq (evil-visual-type) 'line)
        (evil-visual-rotate 'upper-left)
        (evil-insert-line count vcount))
       ((eq (evil-visual-type) 'block)
        (let ((column (min (evil-column evil-visual-beginning)
                           (evil-column evil-visual-end))))
          (evil-visual-rotate 'upper-left)
          (move-to-column column t)
          (evil-insert count vcount skip-empty-lines)))
       (t
        (evil-visual-rotate 'upper-left)
        (evil-insert count vcount skip-empty-lines)))
    (setq evil-insert-count count
          evil-insert-lines nil
          evil-insert-vcount (and vcount
                                  (> vcount 1)
                                  (list (line-number-at-pos)
                                        (current-column)
                                        vcount))
          evil-insert-skip-empty-lines skip-empty-lines)
    (evil-insert-state 1)))

a绑定的是evil-append

A绑定evil-append-line

I绑定evil-insert-line

o绑定evil-open-below

O绑定evil-open-above

s绑定evil-substitute

S绑定evil-change-whole-line

R绑定的是evil-replace-state

从编辑模式退回普通模式的命令的Esc.

标准emacs下的编辑命令

删除一个字符

Del 删除上一个字符,对应delete-forward-char函数。

C-d (delete-char) 删除光标位置字符,不过这个绑定在spacemacs中不支持。

在spacemacs中的正常模式下,可以使用vi的x命令来删除当前字符,函数是evil-delete-char.

(evil-define-operator evil-delete-char (beg end type register)
  :motion evil-forward-char
  (interactive "<R><x>")
  (evil-delete beg end type register))

删除一行

下面我们学习emacs中非常有趣的一个功能。

在vi中,删除一行非常容易,一条命令dd就可以了。

但是emacs不会这样的,要想删除一行,需要三个命令C-a C-k C-k,哈哈

C-k绑定的命令是kill-line,它的作用是,删除光标至行尾的所有内容,但是不包括换行符。删除掉这个空行需要再执行一次kill-line.

如果要删除从光标开始到行首的命令的话,我们可以使用kill-line的负命令,就是把负号做为参数传给kill-line. 方法是调用negative-argument函数,它绑定的键特别多,有C–, A–, C-A–,反正跟减号的组合都是它就是了。

(defun negative-argument (arg)
  "Begin a negative numeric argument for the next command.
\\[universal-argument] following digits or minus sign ends the argument."
  (interactive "P")
  (prefix-command-preserve-state)
  (setq prefix-arg (cond ((integerp arg) (- arg))
                         ((eq arg '-) nil)
                         (t '-)))
  (universal-argument--mode))

剪切,复制和粘贴

文本区域的选择

要想做剪切和复制,第一步要先做文本区域的选择。

在想要选择的文本区域的头部,使用set-mark-command函数来设置标记:

(defun set-mark-command (arg)
  (interactive "P")
  (cond ((eq transient-mark-mode 'lambda)
     (kill-local-variable 'transient-mark-mode))
    ((eq (car-safe transient-mark-mode) 'only)
     (deactivate-mark)))
  (cond
   ((and (consp arg) (> (prefix-numeric-value arg) 4))
    (push-mark-command nil))
   ((not (eq this-command 'set-mark-command))
    (if arg
    (pop-to-mark-command)
      (push-mark-command t)))
   ((and set-mark-command-repeat-pop
     (eq last-command 'pop-global-mark)
     (not arg))
    (setq this-command 'pop-global-mark)
    (pop-global-mark))
   ((or (and set-mark-command-repeat-pop
             (eq last-command 'pop-to-mark-command))
        arg)
    (setq this-command 'pop-to-mark-command)
    (pop-to-mark-command))
   ((eq last-command 'set-mark-command)
    (if (region-active-p)
        (progn
          (deactivate-mark)
          (message "Mark deactivated"))
      (activate-mark)
      (message "Mark activated")))
   (t
    (push-mark-command nil))))

set-mark-command绑定在Ctrl-@和Ctrl-空格上。不管是Windows还是MacOS,Ctrl-空格都已被操作系统征用了,可以用C-@,不过这个键确实是不好用,需要按Ctrl-Shift-2。

设置了标记之后,将光标移至要选择的结尾就可以了。

如果想确认下标记的位置,可以用exchange-point-and-mark函数,快捷键C-x C-x.

剪切

选中文本块之后,就可以将其删除kill-region,然后再到新的位置通过yank命令粘贴出来就好。删除之后,删除的结果会存到删除环中。

在标准emacs下,kill-region绑定在C-w上,但是spacemacs下不支持。可以使用Shift-Delete组合。yank在标准emacs上绑定在C-y上,spacemacs下也不支持,但是可以使用Shift-Insert.

spacemacs是个土洋结合的系统,使用emacs的方式选中文本区域之后,可以使用vi的d命令达到同样的剪切效果,函数是evil-delete。

不选中文本块,只删除一行的话,命令是dd。

(evil-define-operator evil-delete (beg end type register yank-handler)
  (interactive "<R><x><y>")
  (unless register
    (let ((text (filter-buffer-substring beg end)))
      (unless (string-match-p "\n" text)
        ;; set the small delete register
        (evil-set-register ?- text))))
  (let ((evil-was-yanked-without-register nil))
    (evil-yank beg end type register yank-handler))
  (cond
   ((eq type 'block)
    (evil-apply-on-block #'delete-region beg end nil))
   ((and (eq type 'line)
         (= end (point-max))
         (or (= beg end)
             (/= (char-before end) ?\n))
         (/= beg (point-min))
         (=  (char-before beg) ?\n))
    (delete-region (1- beg) end))
   (t
    (delete-region beg end)))
  ;; place cursor on beginning of line
  (when (and (called-interactively-p 'any)
             (eq type 'line))
    (evil-first-non-blank)))

复制

复制也是先选中文本区域,然后使用kill-ring-save函数将其复制到删除环中,最后还是通过yank命令粘贴。它绑定的键是A-w,在spacemacs中仍然有效。

也可以使用vi中的y命令,达到同样的效果,函数是evil-yank. 有没有觉得用y键比A-w键要舒服一些?

(evil-define-operator evil-yank (beg end type register yank-handler)
  "Saves the characters in motion into the kill-ring."
  :move-point nil
  :repeat nil
  (interactive "<R><x><y>")
  (let ((evil-was-yanked-without-register
         (and evil-was-yanked-without-register (not register))))
    (cond
     ((and (fboundp 'cua--global-mark-active)
           (fboundp 'cua-copy-region-to-global-mark)
           (cua--global-mark-active))
      (cua-copy-region-to-global-mark beg end))
     ((eq type 'block)
      (evil-yank-rectangle beg end register yank-handler))
     ((eq type 'line)
      (evil-yank-lines beg end register yank-handler))
     (t
      (evil-yank-characters beg end register yank-handler)))))

如果要复制一行的话,命令是yy.

vi中的粘贴命令是p,函数是evil-paste-after

(evil-define-command evil-paste-after
  (count &optional register yank-handler)
  "Pastes the latest yanked text behind point.
The return value is the yanked text."
  :suppress-operator t
  (interactive "P<x>")
  (if (evil-visual-state-p)
      (evil-visual-paste count register)
    (evil-with-undo
      (let* ((text (if register
                       (evil-get-register register)
                     (current-kill 0)))
             (yank-handler (or yank-handler
                               (when (stringp text)
                                 (car-safe (get-text-property
                                            0 'yank-handler text)))))
             (opoint (point)))
        (when text
          (if (functionp yank-handler)
              (let ((evil-paste-count count)
                    ;; for non-interactive use
                    (this-command #'evil-paste-after))
                (insert-for-yank text))
            ;; no yank-handler, default
            (when (vectorp text)
              (setq text (evil-vector-to-string text)))
            (set-text-properties 0 (length text) nil text)
            (unless (eolp) (forward-char))
            (push-mark (point) t)
            ;; TODO: Perhaps it is better to collect a list of all
            ;; (point . mark) pairs to undo the yanking for COUNT > 1.
            ;; The reason is that this yanking could very well use
            ;; `yank-handler'.
            (let ((beg (point)))
              (dotimes (i (or count 1))
                (insert-for-yank text))
              (setq evil-last-paste
                    (list #'evil-paste-after
                          count
                          opoint
                          beg       ; beg
                          (point))) ; end
              (evil-set-marker ?\[ beg)
              (evil-set-marker ?\] (1- (point)))
              (when (evil-normal-state-p)
                (evil-move-cursor-back)))))
        (when register
          (setq evil-last-paste nil))
        (and (> (length text) 0) text)))))

p是粘贴到当前光标后,如果要粘贴到当前光标前的话,命令是P,函数是evil-paste-before.

从删除环中获取更早的结果

删除环不只会保存上一次的结果,如果想要更早的结果,可以通过yank-pop函数来获取。

vi移动光标方式的补充

上一讲讲过,可以在正常模式下通过使用0来移动到行首。但是,有时候我们希望跳过行首第一个不是空白符的位置,这时候,就要用”^”命令,函数是evil-first-non-blank.

(evil-define-motion evil-first-non-blank ()
  "Move the cursor to the first non-blank character of the current line."
  :type exclusive
  (evil-narrow-to-line (back-to-indentation)))

vi括号匹配

vi中的%命令,可以匹配跟当前括号配对的另一半括号,函数是evil-jump-item.

vi重复做上一条命令

“.”可以执行上一条命令,函数是evil-repeat.

(evil-define-command evil-repeat (count &optional save-point)
  "Repeat the last editing command with count replaced by COUNT.
If SAVE-POINT is non-nil, do not move point."
  :repeat ignore
  :suppress-operator t
  (interactive (list current-prefix-arg
                     (not evil-repeat-move-cursor)))
  (cond
   ((null evil-repeat-ring)
    (error "Already executing repeat"))
   (save-point
    (save-excursion
      (evil-repeat count)))
   (t
    (unwind-protect
        (let ((confirm-kill-emacs t)
              (kill-buffer-hook
               (cons #'(lambda ()
                         (user-error "Cannot delete buffer in repeat command"))
                     kill-buffer-hook))
              (undo-pointer buffer-undo-list))
          (evil-with-single-undo
            (setq evil-last-repeat (list (point) count undo-pointer))
            (evil-execute-repeat-info-with-count
             count (ring-ref evil-repeat-ring 0))))
      (evil-normal-state)))))

小结

功能 函数 键绑定 leader key
删除光标处字符 delete-char
evil-delete-char x
删除光标至行尾 kill-line C-k
传递负参数 negative-argument C–, A–, C-A–
设置文本块开始标记 set-mark-command C-@
交换光标与文本标记 exchange-point-and-mark C-x C-x
剪切文本块到删除环 kill-region Shift-Delete
evil-delete d
复制文本块到删除环 kill-ring-save A-w
evil-yank y
从删除环中弹出,即粘贴 yank Shift-Insert
evil-paste-after p
evil-paste-before P
从删除环中弹出更早的结果 yank-pop
移至行首第一个非空白符 evil-first-non-blank ^
匹配下一个可配对的括号 evil-jump-item %
再次执行上一次执行的命令 evil-repeat .

我也说说Emacs吧(5) - 基本编辑操作的更多相关文章

  1. Emacs学习心得之 基础操作

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Emacs学习心得之 基础操作 1.前言与学习计划2.Emacs基础操作 一. 前言与学习计 ...

  2. Html简单demo_html列表中进行编辑操作

    html列表中进行编辑操作 <div class="_sort_box" style="float: left;"><?php echo $v ...

  3. linux --> VIM的列编辑操作

    VIM的列编辑操作   一.删除列 1.光标定位到要操作的地方. 2.CTRL+v 进入“可视 块”模式,选取这一列操作多少行. 3.d 删除.   二.插入列 插入操作的话知识稍有区别.例如在每一行 ...

  4. Asp.Net MVC +EntityFramework主从表新增编辑操作的实现(删除操作怎么实现?)

    Asp.Net MVC +EntityFramework主从表新增编辑操作的实现 对于MVC中同时对主从表的表单操作在网上现有的解决很少,而这样的操作在做业务系统中是经常为遇到的.我在网上搜索了很久都 ...

  5. 【vim】插入模式与常用编辑操作

    vim不像很多编辑器那样一启动便可以直接编辑文本,需要在普通模式按下i, a等键才会进入插入模式进行文本编辑. 如何进入插入模式 以下的命令都会让vim从普通模式切换到插入模式,但命令执行后的字符插入 ...

  6. 【Linux学习】Vi / Vim编辑器—编辑器工作模式、vi编辑操作

    Vi / Vim编辑器-编辑器工作模式.vi编辑操作 推荐一个很好的学习指南:http://www.oschina.net/translate/learn-vim-progressively 一.编辑 ...

  7. Web UI开发神器—Kendo UI for jQuery数据管理网格编辑操作

    Kendo UI for jQuery最新试用版下载 Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support f ...

  8. jQqery EasyUI dategrid行中多列数据的可编辑操作

    最近的项目中需要在前台dategrid列表中直接修改某些列的数据,并且修改后的数据需要不通过后台而自动更新在列表中. 带着这一问题开始寻找实现的思路,首先想到的就是去jQqery EasyUI官网找例 ...

  9. ao的编辑操作

    自从10.0以后,ArcMap的编辑界面发生了变化,原本的“目标图层”和“编辑任务”不见了,取而代之的是“要素构造”窗口,里面融合了目标图层和编辑任务功能.查看sdk发现,多了几个接口,前面已经讲过. ...

随机推荐

  1. 关于Java -cp引用jar是否支持通配符

    其实是支持的: JDK6支持java -cp后面跟通配符'*',试了一下发现还是需要注意: 错误方式(Wrong way): java  -cp /data/apps/lib/*.jar com.ch ...

  2. 爬虫之动态HTML处理(Selenium与PhantomJS )动态页面模拟点击

    动态页面模拟点击 #!/usr/bin/env python # -*- coding:utf-8 -*- # python的测试模块 import unittest from selenium im ...

  3. QT 样式表基础知识

    1. 何为Qt样式表2. 样式表语法基础3. 方箱模型4. 前景与背景5. 创建可缩放样式6. 控制大小7. 处理伪状态8. 使用子部件定义微观样式 8.1. 相对定位    8.2. 绝对定位 摘要 ...

  4. htop 比top更好用的top

    安装 sudo apt-get install htop 使用 htop

  5. 【Python】“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9”根因及解决方法

    背景 自动化测试调用HTMLTestRunner生成测试报告的时候,出现了编码错误,错误如题 原因 搜索了很多资料,得出的结论是python的str默认是ascii编码,和unicode编码冲突,就会 ...

  6. [postgreSql]postgreSql数据库、模式、表、函数的删除与创建

    1.删除/新增数据库    DROP DATABASE "testDB";    CREATE DATABASE "testDB" WITH OWNER = t ...

  7. jquery中的工具方法$.isFunction, $.isArray(), $.isWindow()

    本文正式地址:http://www.xiabingbao.com/jquery/2015/07/25/jquery-judge-type 在javascript中对变量类型的判断中,我们讲解了了jqu ...

  8. 在windows操作系统中,查询端口占用和清除端口占用的程序

    一.在windows操作系统中,查询端口占用和清除端口占用的程序 提升权限后用:netstat -b或用 1.查询端口占用的进程ID 点击"开始"-->"运行&qu ...

  9. 重新学习MySQL数据库10:MySQL里的那些日志们

    重新学习MySQL数据库10:MySQL里的那些日志们 同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分.MySQL有几种不同的日志文件,通常包括错误日志文件,二进制日志,通用日志, ...

  10. 如何把数字字符'1'转换为整数(java 实现)

    在一些表达式计算时,如 “3+2”    表达式自身是个字符串,通过切片得到的是数字字符和操作符,不能直接进行计算,在表达式计算中需要进行一步操作是,把数字字符'2','3'转化为整数. 如何操作? ...