删除Emacs中的封闭文本

时间:2016-03-17 07:37:36

标签: emacs elisp

我想在特殊字符之间删除封闭文本,如:[“{'<(等等。这样我就可以删除文本,例如”这是一个非常......很长的文字“使用简单的键盘快捷键。我正在寻找一些已经存在的模式,它执行类似的操作,但我没有找到任何类似的,所以我创建了一些在大多数情况下表现良好的lisp代码,但是它在所有情况下都无法正常工作。例如如果我有以下文本条目并且我将光标放在“^”位置,那么我将谎言删除所有包含的文本“但它不起作用:

“aaaaa”> [更多文字] aaaaa“
------------ ^

我的lisp代码如下:

;; returns the enclosing character for the character "c"
(defun get-enc-char (c) (cond
                         ((string= c "(") ")")
                         ((string= c "[") "]")
                         ((string= c "{") "}")
                         ((string= c ">") "<")
                         ((string= c "<") ">")
                         ((string= c "'") "'")
                         ((string= c "\"") "\"")
                         (t nil)
                         )
  )

(defun delete-enclosed-text ()
  "Delete texts between any pair of delimiters."
  (interactive)
  (save-excursion
    (let (p1 p2 mychar)
      ; look for one of those characters and store the cursor position
      (skip-chars-backward "^([\'\"><{") (setq p1 (point))
      ; store the char at this point, look for its enclosed char and advance
      ; the cursor newly (this done to avoid the cases when the char and
      ; its enclosed-char are the same like " or ' chars.
      (backward-char 1) (setq mychar (thing-at-point 'char)) (forward-char 1)
      ; look forward for the enclosed char
      (skip-chars-forward (concatenate 'string "^" (get-enc-char mychar))) (setq p2 (point))
      ; only delete the region if we found the enclosed character
      (if (looking-at "[\]\}\"\'\)<>]") (kill-region p1 p2)))))

以下是一个示例:enter image description here

2 个答案:

答案 0 :(得分:1)

这是一个基于您的代码的解决方案

;; returns the enclosing character for the character "c"
  (defun get-enc-char (c) (cond
                           ((string= c "(") ")")
                           ((string= c "[") "]")
                           ((string= c "{") "}")
                           ((string= c ">") "<")
                           ((string= c "<") ">")
                           ((string= c "'") "'")
                           ((string= c "\"") "\"")
                           (t nil)
                           ))
 (defvar empty-enclose 0)
  (defun delete-enclosed-text ()
    "Delete texts between any pair of delimiters."
    (interactive)
    (setq empty-enclose 0)
    (save-excursion
      (let (p1 p2 orig)
        (setq orig (point))
        (setq p1 (point))
        (setq p2 (point))
        (setq find 0)
        (setq mychar (thing-at-point 'char))
        (if (-contains? '("(" "[" "{" "<" "'" "\"") mychar)
            (progn
              (setq left_encloser (thing-at-point 'char))
              (backward-char -1)
              (if (string-equal (thing-at-point 'char) (get-enc-char left_encloser))
                  (progn
                    (backward-char -1)
                    (setq p2 (point))
                    (setq find 1)
                    (setq empty-enclose 1)))))
        (while (eq find 0)
          (skip-chars-backward "^({[<>\"'")
          (setq p1 (point))
          (backward-char 1)
          (setq left_encloser (thing-at-point 'char))
          (goto-char orig)
          (while (and (not (eobp)) (eq find 0))
            (backward-char -1)
            (skip-chars-forward "^)}]<>\"'")
            (setq right_encloser (thing-at-point 'char))
            (if (string-equal right_encloser (get-enc-char left_encloser))
                (progn
                  (setq p2 (point))
                  (setq find 1))))
          (goto-char p1)
          (backward-char 1))
        (delete-region p1 p2)))
    (if (eq empty-enclose 0)
        (backward-char 1)))

答案 1 :(得分:0)

我快速勾勒出一些东西,它并不完全符合您的要求,但我认为它可以以更舒适的方式满足相同的要求,试一试让我知道!选择区域后,此交互式函数称为,没有参数并要求您提供封闭标记:这可以是{{1}所有直接识别的字符串或字符串(直接使用replace-regex*.等不是这种情况,但您仍然可以使用其他字符,例如[,{{1}等等,甚至是类似HTML的标记,如{})。

该功能将删除所选区域内的所有文本,从标记的第一个显示到最后一个(即使它们有奇数),标记也会被删除。

%

然后,您可以将其全局绑定到您想要的任何键盘快捷键:

<idx>

或本地到您可能拥有的任何自定义挂钩:

(defun remove-enclosed-in-selection (beginning end)
"select a region, call this function and type any valid regex
 markup. All characters from its first to its last appearance will
 be removed (including the symbol itself. Example: try with § and %:
 aaaa§bbbbcc%c§cc§ddddeeee§ffffgggghhhhiiii§jjjj§kkkkllll§mmmm%nnnn"
(interactive "r")
(let ((x (read-string "type enclosing mark: ")))
  (narrow-to-region beginning end)
  (replace-regexp (concat x ".*" x) "")
  (widen)))

所以,总结:

  1. 选择区域
  2. (global-set-key (kbd "C-. <C-return>") 'remove-enclosed-in-selection)或您的自定义按键
  3. (defun custom-whatever-hook () (local-set-key (kbd "C-. <C-return>")) 'remove-enclosed-in-selection) (add-hook 'whatever-hook 'custom-whatever-hook) ,输入有效标记,然后按M-x remove-enclosed-in-selection
  4. 应删除随附的内容
  5. 对于我来说,狭窄范围的方法似乎很快和肮脏,但我无法在短期内找到另一种方式。所以它可能仍然需要一些修复,让我知道它是否按预期工作。另外,我不是那个emacs黑客...... :P 欢呼声