Why does this elisp function to grab text from buffer not work

…衆ロ難τιáo~ 提交于 2019-12-24 10:48:17

问题


I have some text like this:

qwerty\tberty 
merty\tserty 

I want to grab the text berty between the tab character and end of line. Then to show it worked goto the end of the buffer and insert the text there.

But this code doesn't work. Any ideas why not?

(defun do-test ()
  "tester"
  (interactive)
  (goto-char (point-min))
  (if (search-forward "qwerty" nil t)
     (delete-char 1) ;;delete tab
     (setq myStr (buffer-substring point end-of-line)) ;add text to variable
     ;goto end of buffer and insert text as demonstration it works
     (goto-char (point-max))
     (insert(myStr))
  )
)

EDIT:

Sorry cut and paste error. Should have been:

(if (search-forward "qwerty" nil t)


回答1:


There are a number of problems in your code:

  1. if takes a first argument which is executed in case the test is positive; all remaining args are executed otherwise (like what would be and else clause in most imperative languages). You can either group all your expressions in a progn form, or use the when form, which takes an arbitrary number of expressions to evaluate if the condition is true, and no else clause.

  2. point and line-end-position are functions, which means you have to call them to get values: e.g (point).

  3. On the other hand, myStr is a variable, which means you can directly insert its value (and you cannot call it like a function)

  4. If you want to keep your original buffer intact, you should move point forward by 1 character instead of deleting the TAB. This can be done using the forward-char command.

Here is a modified version of your function, taking all this into account. Also, I changed "Option Name" to "qwerty" to match your example.

(defun do-test ()
  "tester"
  (interactive)
  (goto-char (point-min))
  (when (search-forward "qwerty" nil t)
      (forward-char 1) ;;skip tab
      ;store text in variable `myStr'
      (setq myStr (buffer-substring (point) (line-end-position)))
      ;goto end of buffer and insert text as demonstration it works
      (goto-char (point-max))
      (insert myStr)))

Please note that using regular expressions could be a better way of achieving your goal:

(defun do-test ()
  (interactive)
  (goto-char (point-min))
  (when (re-search-forward "qwerty\t\\(.*\\)")
    (goto-char (point-max))
    (insert (match-string 1))))



回答2:


In addition to @Francesco's answer, I'd argue that the logic is quite brittle and it affects the editor's global state. You might consider extracting the parsing into a pure function, along these lines:

(defun extract-matches (str)
  "Extract the last tab-separated value of each line in STR."
  (mapcar (lambda (s) (car (last (split-string s "\t"))))
          (remove-if-not (lambda (s) (string-match-p "\t" s))
                         (split-string str "\n"))))

(defun extract-eol-tsv ()
  "For each line in the buffer, extract the last tab-delimited
phrase and insert it at the end of the buffer."
  (interactive)
  (save-excursion
    (goto-char (point-max))
    (dolist (m (extract-matches (buffer-string))) 
      (insert (format "%s\n" m)))

Using pure functions helps keep the interesting logic testable - now, you can verify the finnicky parsing stuff works without modifying your buffer.



来源:https://stackoverflow.com/questions/15973900/why-does-this-elisp-function-to-grab-text-from-buffer-not-work

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!