emacs delete-trailing-whitespace except current line - emacs

I recently added Emacs (delete-trailing-whitespace) function to my 'before-save-hook for some programming modes, but I find it rather frustrating that it deletes whitespace from the line I am currently editing. Any suggestions as to how to fix this problem?

Since delete-trailing-whitespace respects narrowing, one solution is to narrow the buffer to the portion before the current line and call it, then narrow to the portion after the current line and call it again:
(defun delete-trailing-whitespace-except-current-line ()
(interactive)
(let ((begin (line-beginning-position))
(end (line-end-position)))
(save-excursion
(when (< (point-min) begin)
(save-restriction
(narrow-to-region (point-min) (1- begin))
(delete-trailing-whitespace)))
(when (> (point-max) end)
(save-restriction
(narrow-to-region (1+ end) (point-max))
(delete-trailing-whitespace))))))
Put this function on your before-save-hook instead of delete-trailing-whitespace.

This wrapper for delete-trailing-whitespace can be used to do what you want:
(defun delete-trailing-whitespace-except-current-line ()
"do delete-trailing-whitespace, except preserve whitespace of current line"
(interactive)
(let ((current-line (buffer-substring (line-beginning-position) (line-end-position)))
(backward (- (line-end-position) (point))))
(delete-trailing-whitespace)
(when (not (string-equal (buffer-substring (line-beginning-position) (line-end-position))
current-line))
(delete-region (line-beginning-position) (line-end-position))
(insert current-line)
(backward-char backward))))

I ran into the same problem, and found out that ws-butler perfectly solves it.
There is a simple sample config code:
;; autoload ws-butler on file open
(add-hook 'find-file-hook #'ws-butler-global-mode)
(setq require-final-newline t)

I simply have a wrapper to make two calls to `delete-trailing-whitespace':
(defun modi/delete-trailing-whitespace-buffer ()
"Delete trailing whitespace in the whole buffer, except on the current line.
The current line exception is because we do want to remove any whitespace
on the current line on saving the file (`before-save-hook') while we are
in-between typing something.
Do not do anything if `do-not-delete-trailing-whitespace' is non-nil."
(interactive)
(when (not (bound-and-true-p do-not-delete-trailing-whitespace))
(delete-trailing-whitespace (point-min) (line-beginning-position))
(delete-trailing-whitespace (line-end-position) (point-max))))
(add-hook 'before-save-hook #'modi/delete-trailing-whitespace-buffer)

Related

Command to uncomment multiple lines without selecting them

Is there a command in emacs to uncomment an entire comment block without having to mark it first?
For instance, let's say the point is inside a comment in the following code:
(setq doing-this t)
;; (progn |<--This is the point
;; (er/expand-region 1)
;; (uncomment-region (region-beginning) (region-end)))
I would like a command that turns that into this:
(setq doing-this t)
(progn
(er/expand-region 1)
(uncomment-region (region-beginning) (region-end)))
It's fairly easy to write a command that (un)comments a single line, but I've yet to find one that uncomments as many lines as possible. Is there one available?
A quick reply --- code could be improved and made more useful. You might want to extend it to other kinds of comments, besides ;;;, for instance.
(defun uncomment-these-lines ()
(interactive)
(let ((opoint (point))
beg end)
(save-excursion
(forward-line 0)
(while (looking-at "^;;; ") (forward-line -1))
(unless (= opoint (point))
(forward-line 1)
(setq beg (point)))
(goto-char opoint)
(forward-line 0)
(while (looking-at "^;;; ") (forward-line 1))
(unless (= opoint (point))
(setq end (point)))
(when (and beg end)
(comment-region beg end '(4))))))
The key is comment-region. FWIW, I bind comment-region to C-x C-;. Just use it with C-u to uncomment.
You can use Emacs' comment handling functions to make a generalised version of Drew's command.
(defun uncomment-current ()
(interactive)
(save-excursion
(goto-char (point-at-eol))
(goto-char (nth 8 (syntax-ppss)))
(uncomment-region
(progn
(forward-comment -10000)
(point))
(progn
(forward-comment 10000)
(point)))))

How could I improve this solution to the "create index entries" exercise of Emacs Lisp Intro?

I've programmed this solution for the exercise from section 11.4 (Looping Exercise):
(defun texinfo-index-dfns-in-par ()
"Create an index entry at the beginning of the paragraph for every '#dfn'."
(interactive)
(save-excursion
(forward-paragraph)
(let ((bound (point)))
(backward-paragraph)
(let ((insert-here (point)))
(while (search-forward "#dfn{" bound t)
(let* ((start (point))
(end (1- (search-forward "}" bound)))
(dfn (buffer-substring start end)))
(save-excursion
(goto-char insert-here)
(newline)
(setq insert-here (point))
(insert "#cindex " dfn)
(while (< insert-here (line-beginning-position))
(join-line))
(end-of-line)
(setq insert-here (point))
(forward-paragraph)
(setq bound (point)))))))))
Though it's working, it feels much to convoluted to me. I'd like to know how this code could be simplified. I'm also interested in other possible improvements.
Edit:
Tyler's answer was great. With narrowing I could write a much shorter and cleaner version:
(defun texinfo-index-dfns-in-par ()
"Create an index entry at the beginning of the paragraph for every '#dfn'."
(interactive)
(save-excursion
(mark-paragraph)
(save-restriction
(narrow-to-region (point) (mark))
(while (search-forward "#dfn{" nil t)
(let ((start (point))
(end (1- (search-forward "}"))))
(save-excursion
(goto-char (point-min))
(insert "\n#cindex " (buffer-substring start end))
(while (> (line-number-at-pos) 2) (join-line))
(narrow-to-region (line-end-position) (point-max))))))))
One thing to look at is narrowing. You can use narrowing to get around a lot of the bouncing back and forth you're doing.
(mark-paragraph)
(narrow-to-region)
Will limit the scope of your function to the current paragraph and move point to the beginning. You can then start your forward search without worrying about moving past the current paragraph. When you're done,
(widen)
restores the rest of the buffer to view.
You could replace your search-forwards and buffer-substring with an re-search-forward and match-string (note: untested):
(while (re-search-forward "#dfn{\\([^}]+\\)}" nil t)
(save-excursion
(goto-char (point-min))
(insert "\n#cindex " (match-string 1))
(while (> (line-number-at-pos) 2) (join-line))
(narrow-to-region (line-end-position) (point-max))))

Disable auto-fill-mode locally (or un fill-paragraph) with emacs

I use M-q for fill-paragraph, can I do the un-fill-paragraph in auto-fill-mode?
With org mode, I sometimes enter [[Very long HTML][Name with spaces]], and for the 'Name with spaces' the auto-fill mode break the whole line based on the inserted space, which makes it very ugly.
Is there a command something like un-fill-paragraph? Or, is there a way disable auto-fill-mode temporarily/locally?
Emacs does not record what was your line before calling fill-paragraph. So the only thing you can do is C-_ which runs the command undo. It can undo your fill-paragraph command but only if it is the preceding command call.
If you want to put a multi-line paragraph on one line you could do like this :
Select the region
C-M-% C-q C-j RET SPACE RET !
Xah Lee has updated his code since monotux's answer, and I refactored it somewhat for readability:
(defun my-toggle-fill-paragraph ()
;; Based on http://xahlee.org/emacs/modernization_fill-paragraph.html
"Fill or unfill the current paragraph, depending upon the current line length.
When there is a text selection, act on the region.
See `fill-paragraph' and `fill-region'."
(interactive)
;; We set a property 'currently-filled-p on this command's symbol
;; (i.e. on 'my-toggle-fill-paragraph), thus avoiding the need to
;; create a variable for remembering the current fill state.
(save-excursion
(let* ((deactivate-mark nil)
(line-length (- (line-end-position) (line-beginning-position)))
(currently-filled (if (eq last-command this-command)
(get this-command 'currently-filled-p)
(< line-length fill-column)))
(fill-column (if currently-filled
most-positive-fixnum
fill-column)))
(if (region-active-p)
(fill-region (region-beginning) (region-end))
(fill-paragraph))
(put this-command 'currently-filled-p (not currently-filled)))))
To remake a long line out of a paragraph in Org mode, I gave myself a new command. Here is the associated Emacs Lisp code:
(defun fp-unfill-paragraph (&optional justify region)
(interactive (progn
(barf-if-buffer-read-only)
(list (if current-prefix-arg 'full) t)))
(interactive)
(let ((fill-column 100000))
(fill-paragraph justify region)))
(global-set-key "\C-ceu" 'fp-unfill-paragraph)
Of course, you adjust the command keybinding as you see fit!
I use the following snippet to fill and un-fill paragraphs (using only M-q), it is really, really handy. I borrowed it from Xah Lee, but removed some comments and whitespace in order to make it fit in here. The link in the first comment goes to his original code.
;; http://xahlee.org/emacs/modernization_fill-paragraph.html
(defun compact-uncompact-block ()
"Remove or add line endings on the current block of text.
This is similar to a toggle for fill-paragraph and unfill-paragraph
When there is a text selection, act on the region.
When in text mode, a paragraph is considered a block. When in programing
language mode, the block defined by between empty lines.
Todo: The programing language behavior is currently not done.
Right now, the code uses fill* functions, so does not work or work well
in programing lang modes. A proper implementation to compact is replacing
newline chars by space when the newline char is not inside string.
"
(interactive)
(let (bds currentLineCharCount currentStateIsCompact
(bigFillColumnVal 4333999) (deactivate-mark nil))
(save-excursion
(setq currentLineCharCount
(progn
(setq bds (bounds-of-thing-at-point 'line))
(length (buffer-substring-no-properties (car bds) (cdr bds)))))
(setq currentStateIsCompact
(if (eq last-command this-command)
(get this-command 'stateIsCompact-p)
(if (> currentLineCharCount fill-column) t nil)))
(if (and transient-mark-mode mark-active)
(if currentStateIsCompact
(fill-region (region-beginning) (region-end))
(let ((fill-column bigFillColumnVal))
(fill-region (region-beginning) (region-end)))
)
(if currentStateIsCompact
(fill-paragraph nil)
(let ((fill-column bigFillColumnVal))
(fill-paragraph nil))))
(put this-command 'stateIsCompact-p
(if currentStateIsCompact
nil t)))))
(global-set-key (kbd "M-q") 'compact-uncompact-block)

How to execute emacs grep-find link in the same window?

When I use grep-find it opens another window (area in the frame) with a list of results that I can select. When I select one it opens the target file in a different window than grep-find is in.
How can I get the target file to open in the same window as the grep results (replacing the grep results window with what I am actually looking for).
How can I keep grep-find from opening a separate window (have it so it opens in the current window). My goal is I look for something, I find it, I go to it, all within the same window. I would like to add this to my .emacs file.
It doesn't look like there is any way to configure the compile package to do what you're asking. And there's no easy way to use advice to tweak the behavior. I think you have to resort to editing the function which actually jumps to the error, which you can do with the following addition to your .emacs (tested in Emacs 23.1):
(eval-after-load "compile"
'(defun compilation-goto-locus (msg mk end-mk)
"Jump to an error corresponding to MSG at MK.
All arguments are markers. If END-MK is non-nil, mark is set there
and overlay is highlighted between MK and END-MK."
;; Show compilation buffer in other window, scrolled to this error.
(let* ((from-compilation-buffer (eq (window-buffer (selected-window))
(marker-buffer msg)))
;; Use an existing window if it is in a visible frame.
(pre-existing (get-buffer-window (marker-buffer msg) 0))
(w (if (and from-compilation-buffer pre-existing)
;; Calling display-buffer here may end up (partly) hiding
;; the error location if the two buffers are in two
;; different frames. So don't do it if it's not necessary.
pre-existing
(let ((display-buffer-reuse-frames t)
(pop-up-windows t))
;; Pop up a window.
(display-buffer (marker-buffer msg)))))
(highlight-regexp (with-current-buffer (marker-buffer msg)
;; also do this while we change buffer
(compilation-set-window w msg)
compilation-highlight-regexp)))
;; Ideally, the window-size should be passed to `display-buffer' (via
;; something like special-display-buffer) so it's only used when
;; creating a new window.
(unless pre-existing (compilation-set-window-height w))
(switch-to-buffer (marker-buffer mk))
;; was
;; (if from-compilation-buffer
;; ;; If the compilation buffer window was selected,
;; ;; keep the compilation buffer in this window;
;; ;; display the source in another window.
;; (let ((pop-up-windows t))
;; (pop-to-buffer (marker-buffer mk) 'other-window))
;; (if (window-dedicated-p (selected-window))
;; (pop-to-buffer (marker-buffer mk))
;; (switch-to-buffer (marker-buffer mk))))
;; If narrowing gets in the way of going to the right place, widen.
(unless (eq (goto-char mk) (point))
(widen)
(goto-char mk))
(if end-mk
(push-mark end-mk t)
(if mark-active (setq mark-active)))
;; If hideshow got in the way of
;; seeing the right place, open permanently.
(dolist (ov (overlays-at (point)))
(when (eq 'hs (overlay-get ov 'invisible))
(delete-overlay ov)
(goto-char mk)))
(when highlight-regexp
(if (timerp next-error-highlight-timer)
(cancel-timer next-error-highlight-timer))
(unless compilation-highlight-overlay
(setq compilation-highlight-overlay
(make-overlay (point-min) (point-min)))
(overlay-put compilation-highlight-overlay 'face 'next-error))
(with-current-buffer (marker-buffer mk)
(save-excursion
(if end-mk (goto-char end-mk) (end-of-line))
(let ((end (point)))
(if mk (goto-char mk) (beginning-of-line))
(if (and (stringp highlight-regexp)
(re-search-forward highlight-regexp end t))
(progn
(goto-char (match-beginning 0))
(move-overlay compilation-highlight-overlay
(match-beginning 0) (match-end 0)
(current-buffer)))
(move-overlay compilation-highlight-overlay
(point) end (current-buffer)))
(if (or (eq next-error-highlight t)
(numberp next-error-highlight))
;; We want highlighting: delete overlay on next input.
(add-hook 'pre-command-hook
'compilation-goto-locus-delete-o)
;; We don't want highlighting: delete overlay now.
(delete-overlay compilation-highlight-overlay))
;; We want highlighting for a limited time:
;; set up a timer to delete it.
(when (numberp next-error-highlight)
(setq next-error-highlight-timer
(run-at-time next-error-highlight nil
'compilation-goto-locus-delete-o)))))))
(when (and (eq next-error-highlight 'fringe-arrow))
;; We want a fringe arrow (instead of highlighting).
(setq next-error-overlay-arrow-position
(copy-marker (line-beginning-position)))))))
The eval-afer-load portion just ensures that you re-define it after Emacs defined it, so that your change takes hold.
You can add a binding (e.g. Alt-m) and do the following
(define-key grep-mode-map "\M-m" (lambda()
(interactive)
(compile-goto-error)
(delete-other-windows)
(kill-buffer "*grep*")))
I didn't find a way to replace the standard "Enter" / Mouse-click binding with a custom function
There is an another approach:
(defun eab/compile-goto-error ()
(interactive)
(let ((cwc (current-window-configuration)))
(funcall
`(lambda ()
(defun eab/compile-goto-error-internal ()
(let ((cb (current-buffer))
(p (point)))
(set-window-configuration ,cwc)
(switch-to-buffer cb)
(goto-char p ))))))
(compile-goto-error)
(run-with-timer 0.01 nil 'eab/compile-goto-error-internal))
I had the same question, and found this answer over at emacs.stackexchange https://emacs.stackexchange.com/a/33908/20000
(defun my-compile-goto-error-same-window ()
(interactive)
(let ((display-buffer-overriding-action
'((display-buffer-reuse-window
display-buffer-same-window)
(inhibit-same-window . nil))))
(call-interactively #'compile-goto-error)))
(defun my-compilation-mode-hook ()
(local-set-key (kbd "o") #'my-compile-goto-error-same-window))
(add-hook 'compilation-mode-hook #'my-compilation-mode-hook)
Pressing o in the *grep* buffer will open the location and file in the same frame.
I found this an elegant solution without deleting frames or too much lisp code and just hooking into compilation-mode-hook.

How to write an Emacs function to wrap the marked region with specified text

I'm not too familiar with elisp, and am trying to learn. In emacs, I'd like to be able to do the following:
Mark via C-space
Go to where I want the the marking to end, so I have a region that is highlighted, suppose it is "highlighted text"
Hit a key-sequence
Have emacs ask me to input some text, say "plot", and
Have that highlighted text change to be "plot(highlighted text)". That is, I'd like to wrap the highlited text with parentheses and precede it with the text I input.
(defun wrap-text ()
)
I suppose the input of the function would be the highlighted text, but I don't know where to start looking. The other hard part would be the input text part. Could someone guide me? Thanks.
For your case, this should work:
(defun wrap-text (b e txt)
"simple wrapper"
(interactive "r\nMEnter text to wrap with: ")
(save-restriction
(narrow-to-region b e)
(goto-char (point-min))
(insert txt)
(insert "(")
(goto-char (point-max))
(insert ")")))
(global-set-key (kbd "C-x M-w") 'wrap-text)
Something a bit closer to your version, but with some changes :
you can use 'let' to create a local-variable
region-beginning and region-end gives you the equivalent of what trey did with
Here is an example :
(defun wrap-in-function ()
"Wrap marked region with a specified PREFIX and closing parentheses."
(interactive)
(let ((prefix (read-from-minibuffer "function: ")))
(save-excursion
(goto-char (region-beginning))
(insert (concat prefix "(")))
(save-excursion
(goto-char (region-end))
(insert ")"))))
Another difference between the two versions is the position of the point after you called the function ; trey version might be better to use (matter of taste).
EDIT : edited following vinh remarks.
this requires 'cl but is otherwise pretty tiny. been using it for a few years.
(require 'cl) ;;if you haven't elsewhere
(defun decorate-region( beg end prefix suffix )
(interactive "r\nMPrefix: \nMSuffix: ")
(cl-set-buffer-substring beg end (concat prefix
(buffer-substring beg end)
suffix)))
thanks trey jackson. i didn't know u posted a solution so i went to #emacs on the freenode for help. after some research, i came up with the following:
(defun ess-R-wrap-content-vqn ()
"Wrap marked region with a specified PREFIX and closing parentheses."
(interactive)
(set (make-local-variable 'prefix) (read-from-minibuffer "function: "))
(set (make-local-variable 'prefix) (concat prefix "("))
(save-excursion (goto-char (region-beginning)) (insert prefix))
(save-excursion (goto-char (region-end)) (insert ")"))
)
(define-key ess-mode-map "\C-c\M-w" 'ess-R-wrap-content-vqn) ;; w is for wrap
i thought stackoverflow was going to notify me when a solution is posted. again, thanks. learning a little more of elisp from this.