Emacs: move point to last non-whitespace character - emacs

M-m (back-to-indentation) moves point to the first non-whitespace character on the line. I'd like to do the opposite: move point to the last non-whitespace character on the line. I have been unable to find a "built-in" command for this and I'm not familiar enough with ELisp to write something, so any help would be appreciated please.

(defun my-move-end-of-line-before-whitespace ()
"Move to the last non-whitespace character in the current line."
(interactive)
(move-end-of-line nil)
(re-search-backward "^\\|[^[:space:]]"))

Normally in this situation I want to get to the last non-whitespace character and also remove the trailing space, so I use this:
M-\ runs the command delete-horizontal-space, which is an interactive
compiled Lisp function in `simple.el'.
In the rare case that I would want to preserve the whitespace I just use M-b M-f (backward-word, forward-word) which is typically close enough.

I think already phils answered to your question. Just another POW.. trailing white spaces are very annoying, invisible and prone to bugs(?). So I have a hook for before-save-hook to delete them.
;;; delete nasty hidden white spaces at the end of lines
(add-hook 'before-save-hook 'delete-trailing-whitespace)
So it your indented operation becomes simply C-e for me.

I wrote this function to bind to C-e (usually move-end-of-line). C-e works as usual, but if your pointer is already at the end of the line, it will remove trailing whitespace.
(defun my/smarter-move-end-of-line (arg)
"Move to the last non-whitespace character in the current line.
Move point to end of this line. If point is already there, delete
trailing whitespace from line, effectively moving pointer to last
non-whitespace character while also removing trailing whitespace.
If ARG is not nil or 1, move forward ARG - 1 lines first."
(interactive "^p")
(setq arg (or arg 1))
;; Move lines first
(when (/= arg 1)
(let ((line-move-visual nil))
(forward-line (1- arg))))
(let ((orig-point (point)))
(move-end-of-line 1)
(when (= orig-point (point))
(delete-horizontal-space))))
Remap C-e:
;; remap C-e to 'smarter-move-end-of-line'
(global-set-key [remap move-end-of-line]
'my/smarter-move-end-of-line)

My version: Move to end of line or last non-space (by deleting ending spaces)
(defun smart-end-of-line ()
"Move to end of line or last non-space (by deleting ending spaces)"
(interactive "^")
(let ((p (point)))
(end-of-visual-line)
(if (= p (point)) (end-of-line))
(if (= p (point)) (let (deactivate-mark) (delete-horizontal-space)))))
(global-set-key [end] 'smart-end-of-line)
(global-set-key "\C-e" 'smart-end-of-line)
The [end] and "\C-e" (control+e) keys:
Move the cursor (point) the the end of the visual line.
If it is already at the end of the visual line, then move it to end of the line.
If it is already there, then move it to last non-whitespace character of the line by deleting all those ending whitespaces.
While moving, keep the region (interactive "^").
The let (deactivate-mark) is to make sure the region is kept.
This is taken from #justinokamoto; then I add the visual line end. (Sorry for my broken English).

Related

Emacs indent/unindent current line

I've been using Emacs for a while, and I really miss a good old Geany shortcut - "C-i" and "C-u".
"C-i" indents the whole current line (keeping the mouse cursor where it is), and "C-u" unindents the whole current line.
I found many indenting commands for Emacs, some to indent a region. Basically, what I need is Vim's ">>" and "<<", but keeping the mouse cursor where it is.
My main doubt is, however, how I can indent only the current line.
Any ideas? Thank you in advance!
EDIT
Tab adds two spaces, I want to be on any position on the line and add two spaces on the beginning of the line, or remove two spaces from the beginning of the line.
That is the default behavior I have for my TAB key in emacs, which runs the command indent-for-tab-command. From one of the documentation pages:
In programming modes, adds or removes some combination of space and tab characters at the start of the line, in a way that makes sense given the text in the preceding lines. If the region is active and spans multiple lines, all those lines are indented this way. If point was initially within the current line's indentation, it is positioned after that indentation; otherwise, it remains at same point in the newly-indented text. See Program Indent.
Also worth noting is the tab-always-indent variable:
The variable tab-always-indent tweaks the behavior of the (indent-for-tab-command) command. The default value, t, gives the behavior described above. If you change the value to the symbol complete, then first tries to indent the current line, and if the line was already indented, it tries to complete the text at point (see Symbol Completion). If the value is nil, then indents the current line only if point is at the left margin or in the line's indentation; otherwise, it inserts a real tab character.
I have this in my init.el:
(defun rofrol/indent-region(numSpaces)
(progn
; default to start and end of current line
(setq regionStart (line-beginning-position))
(setq regionEnd (line-end-position))
; if there's a selection, use that instead of the current line
(when (use-region-p)
(setq regionStart (region-beginning))
(setq regionEnd (region-end))
)
(save-excursion ; restore the position afterwards
(goto-char regionStart) ; go to the start of region
(setq start (line-beginning-position)) ; save the start of the line
(goto-char regionEnd) ; go to the end of region
(setq end (line-end-position)) ; save the end of the line
(indent-rigidly start end numSpaces) ; indent between start and end
(setq deactivate-mark nil) ; restore the selected region
)
)
)
(defun rofrol/indent-lines(&optional N)
(interactive "p")
(indent-rigidly (line-beginning-position)
(line-end-position)
(* (or N 1) tab-width)))
(defun rofrol/untab-region (&optional N)
(interactive "p")
(rofrol/indent-region (* (* (or N 1) tab-width)-1)))
(defun rofrol/tab-region (N)
(interactive "p")
(if (use-region-p)
(rofrol/indent-region (* (or N 1) tab-width)) ; region was selected, call indent-region
(rofrol/indent-lines N); else insert spaces as expected
))
(global-set-key (kbd "C->") 'rofrol/tab-region)
(global-set-key (kbd "C-<") 'rofrol/untab-region)
Emacs Shift-Tab to left shift the block
How to bind keys to indent/unindent region in emacs?

Get Emacs to join lines when killing lines

When I hit C-k, Emacs kills to end-of-line. When I hit C-k again, it "kills the newline" and brings the next line up. However, the next line's indentation remains intact, and you can end up with a line that has lots of spaces in the middle.
So, from this:
previous line material
next line material
to this:
previous line material next line material
I understand I can use M-^ to join lines properly, but that requires the cursor to be on the next line. How do I modify C-k so that when it kills the newline, also kills the next line's indentation?
For C-k I don't know, but you could use the just-one-space function to transform any number of space into juste one space (it's bound on M-space)
If you give M-^ an argument (for example C-u M-^), it will join the next line to the current line.
Here's a way to plug in the behavior (I think) you want into kill-line: when killing a newline, also kill the indentation that follows. Note that this may result in no space being present after the cursor, which is why I think I'd go with M-1 M-^ or C-k M-SPC instead.
(defadvice kill-line (around kill-indentation
activate compile)
"When killing a line break, also kill any subsequent indentation."
(let ((f-v-l (symbol-function 'forward-visible-line)))
(flet ((forward-visible-line (arg)
(funcall f-v-l arg)
(skip-chars-forward " \t")))
ad-do-it)))
I have this in my .emacs:
(defun pull-line ()
"Pull the next line that contains anything up to the end of this one"
(interactive)
(save-excursion
(end-of-line)
(while (looking-at "[ \n\r\t]")
(delete-char 1))
(if (looking-back "^[[:blank:]]*[[:punct:][:alnum:]].*")
(fixup-whitespace)
(indent-according-to-mode))))
(global-set-key "\C-cp" 'pull-line)
It pulls the next non-blank line up to the this one, and if there is anything on this line it makes calls (fixup-whitespace) which does the right thing about 95% of the time, otherwise it indents it to what emacs thinks is the right level. I think I copied the concept from vim?
I use it all the time, anyway.
I just realized I also have this in my .emacs, it is more exactly what you want, although I forget that I have it since I use pull-line much more often. I think I stole this from emacswiki:
(defun kill-and-join-forward (&optional arg)
"If at end of line, join with following; otherwise kill line.
Deletes whitespace at join."
(interactive "P")
(if (and (eolp) (not (bolp)))
(progn
(delete-indentation t)
(if (looking-at " $")
(delete-char 1)))
(kill-line arg)))
(global-set-key "\C-k" 'kill-and-join-forward)
This will do it:
(defun my-kill-line (&optional arg)
(interactive "P")
(if arg
(kill-line arg)
(when (prog1 (eolp) (kill-line))
(just-one-space 1))))

Emacs Command to Delete Up to Non-Whitespace Character

I often want to make a multiline function call and reduce it down to one line. For example, convert...
function_call(
'first_arg',
'second')
to
function_call('first_arg', 'second')
Does emacs have some commands to help with this. Specifically, is there a command that will delete all whitespace from the point to the first non-whitespace character?
You might try delete-indentation, my favorite command for joining multiple lines into one line. In your example, put the cursor on the line with "second" and hit M-^ twice. Here are the docs:
M-^ runs the command delete-indentation, which is an interactive compiled Lisp function in simple.el.
It is bound to M-^.
(delete-indentation &optional arg)
Join this line to previous and fix up whitespace at join. If there is a fill prefix, delete it from the beginning of this line. With argument, join this line to following line.
Take a look at the fixup-whitespace function. It comes with Emacs, in simple.el. Its docs are:
Fixup white space between objects around point.
Leave one space or none, according to the context.
A similar function, just-one-space, that
Deletes all spaces and tabs around point, leaving one space
is typically bound to M-SPC.
Specifically, is there a command that will delete all whitespace from the point to the first non-whitespace character?
There's a command that does almost that:
M-\ runs the command delete-horizontal-space
which is an interactive compiled Lisp function in `simple.el'.
It is bound to M-\.
(delete-horizontal-space &optional backward-only)
Delete all spaces and tabs around point.
If backward-only is non-nil, only delete them before point.
You can always use M-z to delete upto a character.
For eg in your case:
M-z ' to delete upto the single quote (unfortunately this will delete the single quote as well, but that is a minor inconvenience).
I use the following macro to "pull" the next line onto the end of the current line, compressing whitespace.
(defun pull-next-line()
(interactive)
(move-end-of-line 1)
(kill-line)
(just-one-space))
This is exactly the opposite of #jrockway's move-line-up and of delete-indentation, which I find more natural. The just-one-space command in the macro is exactly #Mike's M-SPACE.
I bind pull-next-line to M-J (in analogy with Vim's J, for "join", command) using the following in my .emacs.
(global-set-key (kbd "M-J") 'pull-next-line)
Example. Calling pull-next-line on the first line of
function_call(
'first_arg',
'second')
yields
function_call( 'first_arg',
'second')
Calling it a second time yields
function_call( 'first_arg', 'second')
Alt-space will reduce a string of whitespace to a single space character, but it won't delete the newline. Still, that should help a little.
To delete everything from point to the first non-whitespace (or newline), type a non-whitespace char, Alt-space, backspace (to remove final whitespace char), then backspace (to delete the char you added.
To turn the multi-line function declaration into a single-line declaration, use a combination of Alt-space, backspace, and Alt-E (goto-endofline) commands.
A rather drastic way of doing this is Hungry-Delete mode:
Hungry-Delete is a minor-mode that causes deletion to delete all whitespace in the direction you are deleting.
A slightly different approach would be creating a keyboard macro to do the job for you.
so, for creating the macro stage a general scenario like so:
foo
bar
[a line with "foo" then a couple of lines later and with some white spaces, write "bar"]
then standing anywhere between foo and bar, do the following:
C-x ( ; start recording macro
M-b ; move backwards to the beginning of foo
END ; move to the end of foo
C-space ; place mark
C-M-f ; move to the end of bar
HOME ; move to the beginning of the line
C-w ; yank out all the white space
M-SPACE ; leave only one space
C-x ) ; end recording the macro
M-x name-last-kbd-macro ; name it, call it jline or something
Now you can always remove all whitespace between two words with M-x one-line
Make sure you remember to save your keyboard macro by issuing M-x insert-kbd-macro somewhere in your .emacs file - this is how it looks:
(fset 'jline
[?\M-b end ?\C- ?\C-\M-f home ?\C-w escape ? ])
I do this:
(defun move-line-up ()
"Removes leading spaces from the current line, and then moves
the current line to the end of the previous line."
(interactive)
(let (start end)
(save-excursion
(beginning-of-line)
; get first non-space character, only look on this line
(let ((search-end (save-excursion (end-of-line) (point))))
(re-search-forward "[^[:space:]]" search-end))
(setq end (1- (point)))
(previous-line)
(end-of-line)
(setq start (point))
(delete-region start end))
(goto-char start)))
(defun move-next-line-up ()
"Moves the next line to the end of the current line"
(interactive)
(next-line)
(move-line-up))
And bind these as:
(global-set-key (kbd "C-x ,") 'move-line-up)
(global-set-key (kbd "C-x .") 'move-next-line-up)
So to solve your problem, on the line that says "second)", just run C-x , C-x ,
If you want all of your deletes to act that way, you might check out greedy-delete.

Does anyone have an Emacs macro for indenting (and unindenting) blocks of text?

Does anyone have an Emacs macro for indenting (and unindenting) blocks of text?
And I mean "indent" in the commonly-understood sense, not in Emacspeak. In other words, I want to mark a region, press C-u 2, run this macro, and have it add two spaces before every line in the region.
Or press C-u -2 before running the macro and have it remove two spaces from the start of each line in the region. Bonus points if it complains if the lines don't have enough leading whitespace.
indent-rigidly (bound to C-x TAB) does what you want. It's in indent.el, which should be part of the standard emacs distribution.
Also, to have it complain/abort when there's not enough whitespace somewhere, you can do something like this: (quick ugly hack of the original indent-rigidly code)
(defun enough-whitespace-to-indent-p (start end arg)
(save-excursion
(goto-char end)
(setq end (point-marker))
(goto-char start)
(or (bolp) (forward-line 1))
(while (and (< (point) end)
(>= (+ (current-indentation) arg) 0))
(forward-line 1))
(>= (point) end)))
(defun indent-rigidly-and-be-picky (start end arg)
(interactive "r\np")
(if (or (plusp arg) (enough-whitespace-to-indent-p start end arg))
(indent-rigidly start end arg)
(message "Not enough whitespace to unindent!")))
Can also use the world of rectangles.
To insert two spaces:
C-x r t SPC SPC RET
Deleting two spaces is
C-x r d
provided that you've defined the rectangle to cover two spaces. There's also a nice addition to rectangle editing in the CUA package. The CUA package covers more than just rectangles, so if you just want the rectangle portion, check out this description (full disclosure, link is to my blog).
Use indent-rigidly bound by default to C-x TAB

Smart home in Emacs

Can you have smart behavior for the home key in Emacs? By smart I mean that instead of going to the character number 0, it should go to the first non-blank character, and go to 0 on a second pressing, and back to the first non-blank in a third and so on.
Having smart end would be nice as well.
(defun smart-beginning-of-line ()
"Move point to first non-whitespace character or beginning-of-line.
Move point to the first non-whitespace character on this line.
If point was already at that position, move point to beginning of line."
(interactive "^") ; Use (interactive) in Emacs 22 or older
(let ((oldpos (point)))
(back-to-indentation)
(and (= oldpos (point))
(beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
I'm not quite sure what smart end would do. Do you normally have a lot of trailing whitespace?
Note: The major difference between this function and Robert Vuković's is that his always moves to the first non-blank character on the first keypress, even if the cursor was already there. Mine would move to column 0 in that case.
Also, he used (beginning-of-line-text) where I used (back-to-indentation). Those are very similar, but there are some differences between them. (back-to-indentation) always moves to the first non-whitespace character on a line. (beginning-of-line-text) sometimes moves past non-whitespace characters that it considers insignificant. For instance, on a comment-only line, it moves to the first character of the comment's text, not the comment marker. But either function could be used in either of our answers, depending on which behavior you prefer.
This works with GNU Emacs, I didn't tried it with XEmacs.
(defun My-smart-home () "Odd home to beginning of line, even home to beginning of text/code."
(interactive)
(if (and (eq last-command 'My-smart-home)
(/= (line-beginning-position) (point)))
(beginning-of-line)
(beginning-of-line-text))
)
(global-set-key [home] 'My-smart-home)
Thanks for this handy function. I use it all the time now and love it. I've made just one small change:
(interactive)
becomes:
(interactive "^")
From emacs help:
If the string begins with ^' andshift-select-mode' is non-nil, Emacs first calls the function `handle-shift-select'.
Basically this makes shift-home select from the current position to the start of the line if you use shift-select-mode. It's especially useful in the minibuffer.
Note that there is already a back-to-indentation function which does what you want the first smart-home function to do, i.e. go to the first non-whitespace character on the line. It is bound by default to M-m.
There is now a package that does just that, mwim (Move Where I Mean)
My version: move to begining of visual line, first non-whitespace, or beginning of line.
(defun smart-beginning-of-line ()
"Move point to beginning-of-line or first non-whitespace character"
(interactive "^")
(let ((p (point)))
(beginning-of-visual-line)
(if (= p (point)) (back-to-indentation))
(if (= p (point)) (beginning-of-line))))
(global-set-key [home] 'smart-beginning-of-line)
(global-set-key "\C-a" 'smart-beginning-of-line)
The [home] and "\C-a" (control+a) keys:
Move the cursor (point) the the beginning of the visual line.
If it is already at the beginnng of the visual line, then move it to first non-whitespace character of the line.
If it is already there, then move it to the beginning of the line.
While moving, keep the region (interactive "^").
This is taken from #cjm and #thomas; then I add the visual line stuff. (Sorry for my broken English).
I adapt #Vucovic code to jump to beggining-of-line first:
(defun my-smart-beginning-of-line ()
"Move point to beginning-of-line. If repeat command it cycle
position between `back-to-indentation' and `beginning-of-line'."
(interactive "^")
(if (and (eq last-command 'my-smart-beginning-of-line)
(= (line-beginning-position) (point)))
(back-to-indentation)
(beginning-of-line)))
(global-set-key [home] 'my-smart-beginning-of-line)