关于规律性代码的输入技巧

spacemacs
elisp

#1

image

请问大家, 对于这样的代码,有没有什么快速的输入方式?

规律比较明显的


#2

考虑一下模板, , 将 data_1+x, #13h定义成变量如data_$mov, $xh.


#3

输入【f3】mov data_1+【f3】, #13h【ret】【f4】 然后开始按【f4】回放刚刚录制的键盘宏,每按一次产生一行,偏移量自动递增。最后一栏没什么规律,只能手工改


#4

yasnippet一般用于反复使用的模版,临时模版用auto-yasnippet。


#5

iedit


#6

先把问题简化一下,假设所有的行都是 data_1+n 形式,需要解决的是两个问题:

mov      data_1+{SEQ_1}, #{VAL_1}h
mov      data_1+{SEQ_2}, #{VAL_2}h
mov      data_1+{SEQ_3}, #{VAL_3}h
...
mov      data_1+{SEQ_n}, #{VAL_n}h
                    |         |
                    |         '----- 问题2. 编辑位置跳转(编辑完 val_n 之后快速跳至下一个编辑点)
                    |    
                    '--------------- 问题1. 生成递增序列

问题 1

递增序列有很多方法可以产生。

问题 2

比较麻烦的是编辑位置跳转,当编辑完位置1的时候:

mov      data_1+1, #13h
mov      data_1+2, #{VAL_2}h
...

要怎么快速跳到 ${VAL_2} 进行编辑,并且同时消除占位符。即使没有占位符,想要把光标移到下一行的 #h 之间也是需要按不少键:

                      .--- 光标在这里
                      |
mov      data_1+1, #13|h
mov      data_1+2, #|h
                    |
                    '----- 移到这个位置

即便是 yasnippet command (注意是 command 才能产生动态数目的行) 或者 emmet (例如 div*7 展开产生 7 个 <div>{PLACE_HOLDER}</div>,也没办法处理好这个问题。

yasnippet 本来是可以按 tab 跳到下一个编辑点的,但是位置信息容易丢失,也就是说整个编辑过程必须一气呵成,稍有差错就不能跳转了。

与其一步到位,不如化整为零实现

  1. 先有一个简单的 snippet,只产生一行 mov data_1+1, #随便写h
  2. 然后粘贴 n 次,比如 10p
mov      data_1+1, #随便写h
mov      data_1+1, #随便写h
...
mov      data_1+1, #随便写h
  1. 有一个产生列状序列的快捷操作,把 1+ 后面的序列替换:
    1                        1
    1         =>             2
  ...                      ...
    1                        n
  1. 再来一个 narrow-to-rectangle,把编辑点占位符矩形区域凸显出来,这样每一行就是一个编辑点, enter 就到了,不必考虑跳转,或出现差错。不过似乎目前没有这么个函数,待我去研究一下。

    虽然还没这个函数,但是可以用 evil-ex-search 来代替。按 / 把所有占位符搜索出来,重复cgn 编辑下一个点(并清除占位符),还能 . 重复上一次操作。

每一小步的操作,都可以应用到日常的其他编辑。或者在日常编辑中早就用到了,现在只需要稍微组合一下。


如何善用注释/文档中的代码?
#7

有时可以先收集列表、拼接成字符串再添加到光标所处的位置:

(insert
 (cl-reduce (lambda (i j)
              (format "%s\n%s" i j))
            (loop
              for i from 1 to 15
              collect (format "mov data_1+%d, #13h" i))))
mov data_1+1, #13h
mov data_1+2, #13h
mov data_1+3, #13h
mov data_1+4, #13h
mov data_1+5, #13h
mov data_1+6, #13h
mov data_1+7, #13h
mov data_1+8, #13h
mov data_1+9, #13h
mov data_1+10, #13h
mov data_1+11, #13h
mov data_1+12, #13h
mov data_1+13, #13h
mov data_1+14, #13h
mov data_1+15, #13h

#8
  1. 使用 multiple-cursors 或者Emacs自带的rectangle命令C-x r t一次输入 多行的相同字符,比如这里的mov data_1+.
  2. 使用gse-number-rectangleC-x r N,Emacs默认提供) 插入1到7的序列到各行。

搞定 :slight_smile:


#9

总结来说,就两种思路:

  1. 使用代码片段生成器

    利用 elisp 代码或者现成的工具(yasnippet, emmet,tiny.el 等等),以 tiny.el 为例,输入:

    m1\n7x|mov      data_1+%d, #13h
    

    执行 tiny-expand 得到:

    mov      data_1+1, #13h
    mov      data_1+2, #13h
    mov      data_1+3, #13h
    mov      data_1+4, #13h
    mov      data_1+5, #13h
    mov      data_1+6, #13h
    mov      data_1+7, #13h
    

    生成模版准备好了,就万事俱备。

  2. 使用最基本的编辑功能

    粘贴 n 次得到:(多点编辑也可以,但是负担比较大)

    mov      data_1+1, #13h
    mov      data_1+1, #13h
    mov      data_1+1, #13h
    mov      data_1+1, #13h
    mov      data_1+1, #13h
    mov      data_1+1, #13h
    mov      data_1+1, #13h
    

    然后列编辑产生递增序列号:

    mov      data_1+1, #13h
    mov      data_1+2, #13h
    mov      data_1+3, #13h
    mov      data_1+4, #13h
    mov      data_1+5, #13h
    mov      data_1+6, #13h
    mov      data_1+7, #13h
    

    平时就熟练的操作,组合起来也很炫。


emacs如何快速的产生一个数字序列?
#10

感谢各位的回复,看来要学的还有很多。非常给力。


#12

大佬能给我解释一下tiny的doc里的这个example的表达式是啥吗?

m10+x?a%c -> a b c d e f g h i j k

#13

完整语法

m{range start:=0}{separator:= }{range end}{Lisp expr:=indentity}|{format expr:=%d}

示例分解

 .----------- 递增序列,结束值 25 (默认起始值 0),即 '(0 1 2 3 ... 25) 共计 26 个元素
 |
 |  .-------- 求值表达式,展开之后是 (+ x ?a),其中 x 代表序列中的一个元素
 |  |
 |  |  .----- 输出格式,把求值结果转换为 %c
 |  |  |
 |  |  |
___....__
m25+x?a%c

(PS 我其实更偏向于组合使用基本的编辑功能,只是记得有这么个扩展,想着以后也许用得上,example 也只在回复这个主题的时候临场看了前两个。)


#14

话说列编辑生成递增序列的方法你用的哪个?目前就看到个rectangle-number-lines,但这个会填充空格


#15

通过 C-u C-x r N 调用 rectangle-number-lines 会询问起始值和格式,默认格式是 "%Nd ",尾巴带空格。可以现场改,也可以修改 rectangle--default-line-number-format 函数一劳永逸。


#16

这个其实只要在附近找个段落空隙,猛敲几次enter,搞一块试验田出来,然后输入#13h #12h #10h和enter就行了,像这样:

#some serious code...


#13h
#12h
#10h


#some serious code...

然后选取rectangle剪切到几行mov后面,再删掉多余的空行。


#17

看起来很笨,其实是很有效的操作,我也经常这么干。如果能实现不脱离前后文,在原地达成这个效果,就更好了。


#18

找了半天终于找到这个帖子了。有时借用下外部工具也挺好的:

k

然后不规则的地方,自己手动调整吧,没别的法子。


#19

你好,萌新觉得这个字体很好看,请问能告知是什么字体么~


#20

fantasque-sans-mono 的斜体:

(set-frame-font "FantasqueSansMono-12:weight=medium:slant=italic")

#21

谢谢~我去试试~