I want to use flush-lines in a selected region, but I have troubles.

Here it is my code:

(defun delete-empty-lines ()
  "Delete empty lines in bibliography."
  ;; set point-min
  (setq m1 (make-marker))
  (goto-char (point-min))
  (search-forward "\\begin{thebibliography}" nil nil)
  (set-marker m1 (point))
  ;; set point-max
  (setq m2 (make-marker))
  (search-forward "\\end{thebibliography}" nil nil)
  (set-marker m2 (point))
  ;; set marker
  (push-mark m1 nil t)
  (push-mark m2 nil t)
  ;; color region
  (setq mark-active t)
  ;; clean empty lines
  (flush-lines "$^" m1 m2)
  ;; decolor region
  (setq mark-active nil))

The line (flush-lines "$^" m1 m2) seems to be ignored when I call my function in emacs and I do not understand why... How can I fix my code?

  • 1
    This is extraneous to your question, but all of your marker manipulations look redundant to me, and possibly a bit confused. What are you doing all that for?
    – phils
    May 25 '18 at 13:34
  • @phils I am studying elisp and I am a beginner. So, in order to automate frequently operations, I look for examples and I try to adapt them to my goals. I haved found some examples about marker manipulations and I have tried to adapt them to my script. May 25 '18 at 16:16

"$^" probably1 won't be matching anything, so no lines will ever be flushed.

That has nothing to do with using it in a script -- the same thing will be evident if you attempted that interactively.

Perhaps you want something more like this?

(defun delete-empty-lines-in-bibliography ()
  "Delete empty lines in bibliography."
    (goto-char (point-min))
      (while (search-forward "\\begin{thebibliography}" nil t)
        (let ((start (match-beginning 0)))
          (when (search-forward "\\end{thebibliography}" nil t)
              (flush-lines "^$" start (point)))))))))

Note how I am using let to remember the start position, without any need to use markers. A marker would be needed if there was any chance that the position could change before it was used, but that is not the case here, so we can safely (and sensibly) use a simpler approach.

Note also that if you do need to use markers for any valid reason, you should set them to nil when you are finished with them, otherwise they will continue to be tracked in the buffer (and hence consuming resources) after the function has finished. That is more of an issue with your code on account of your use of global variables -- m1 and m2 will continue to exist, and so garbage collection will never clean those markers up.

1 The regexp $^ matches that same two-character sequence literally, so you would only flush lines containing the text $^.

C-hig (elisp)Regexp Special explains that, "For historical compatibility, special characters are treated as ordinary ones if they are in contexts where their special meanings make no sense." and so ^ and $ are only special in certain positions:

^ can be used only at the beginning of the regular expression, or after \(, \(?: or \|.

$ can be used only at the end of the regular expression, or before \) or \|.

Outside of those positions (as in your scenario), ^ and $ just match literally, as if they had been escaped.

  • I am sorry for my mistake. I usually do M-x flush-lines RET $^ RET, so it is not clear to me why it fails in a function definition. I have not realized that I have written $^ wrongly. May 25 '18 at 16:08
  • To be clear, ^$ matches an empty line, but $^ does not match anything. See the manual for more detail: M-x elisp-index-search RET $ in regexp RET
    – phils
    May 25 '18 at 23:26
  • I've just stumbled back upon this answer of mine and seen that it's not entirely accurate. $^ actually matches that same two-character sequence literally, because $ and ^ are not special when they are not in a valid position for that behaviour.
    – phils
    Aug 12 '20 at 21:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.