2016-03-17 28 views
0

我想刪除附加文本之間的特殊字符,如:[「{'<(等..這樣我可以刪除像」這是一個非常......長文本「與文本一個簡單的鍵盤快捷鍵我在尋找一些已經存在的模式,但是我沒有找到任何類似的東西,所以我創建了一些lisp代碼,在大多數情況下都能很好地執行,但是它在所有情況下都不能正常工作。我有下面的文本條目,我把光標放在「^」的位置,然後我會刪除所有的文字「,但它不起作用:刪除Emacs中的封閉文本

」aaaaa]> [more text] 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

+0

它是如何失敗? – sds

+0

這似乎是因爲您正在尋找所有的括號類型,而不是包含您要刪除的特定區域的特定類型。所以當你在雙引號字符串中有一個尖括號時,它會變得困惑。嘗試確定支架類型,只查找那些。 – jpkotta

+2

FWIW,我通常使用'expand-region'包來選擇(也許刪除)這樣的區域。但它肯定需要更多擊鍵。 – jpkotta

回答

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))) 
+0

非常感謝您的解決方案。它工作正常,但當我將光標放在分隔符之間的第一個字符時失敗。例如,如果我把光標放在下面文字中的字符1下面,刪除就不起作用了:「12222222222」 – redobot

+1

@redobot謝謝你的測試。我試過另一種解決方案似乎更好。 – djangoliv

+0

工程就像一個魅力:) ..非常感謝你。請編輯答案以僅保留代碼的工作版本。我會接受答案。 – redobot

0

我快速繪製的東西,它不完全匹配你問什麼,但我認爲它可以以更舒適的方式滿足相同的要求,試試看,讓我知道!這種互動式功能選擇區域,並詢問您的包圍標記之後調用不帶參數的:它可以是任何字符或字符串,它是由replace-regex(直接使用*.直接確認[等不會是這種情況,但你仍然可以使用其他字符,如{},%等,甚至像<idx>這樣的HTML-like標記)。

該功能將刪除所選區域內的所有文字,從標記的第一個幻影到最後一個(即使它們有奇數個),標記也會被刪除。

(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))) 

然後你就可以在全球範圍綁定到任何鍵盤快捷鍵你想要像往常一樣:

(global-set-key (kbd "C-. <C-return>") 'remove-enclosed-in-selection)

或本地任何自定義鉤你可能有:

(defun custom-whatever-hook() 
    (local-set-key (kbd "C-. <C-return>")) 'remove-enclosed-in-selection) 
(add-hook 'whatever-hook 'custom-whatever-hook) 

如此,總結:

  1. 選擇區域
  2. M-x remove-enclosed-in-selection或您的自定義鍵盤
  3. RET,類型有效的標記,按RET
  4. 封閉的內容應該被刪除

窄變寬的做法似乎快&髒我,但我無法在短期內找到另一種方式。所以它可能仍然需要一些修復,讓我知道它是否按預期工作。另外,我不是一個emacs黑客......還沒有!:P 歡呼

+0

非常感謝你的時間和代碼。我認爲這種行爲並不是我要找的,我需要用最少的關鍵筆劃刪除文本,而不需要引入任何提示,這應該是足夠聰明的找到包含字符並使用它作爲 分隔符。我修改了這個問題,添加了一個gif所需的行爲,因爲您可以看到我的當前代碼或多或少有效,但仍有一些情況。 – redobot

相關問題