Emacs indent/unindent current line - emacs

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?

Related

Emacs: move point to last non-whitespace character

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

How can I delete the current line in Emacs?

What is the emacs equivalent of vi's dd? I want to delete the current line. Tried CTRL + k but it only deletes from current position.
C-a # Go to beginning of line
C-k # Kill line from current point
There is also
C-S-backspace # Ctrl-Shift-Backspace
which invokes M-x kill-whole-line.
If you'd like to set a different global key binding, you'd put this in ~/.emacs:
(global-set-key "\C-cd" 'kill-whole-line) # Sets `C-c d` to `M-x kill-whole-line`
If you want to delete a number of whole lines, you can prefix the command with a number:
C-u 5 C-S-backspace # deletes 5 whole lines
M-5 C-S-backspace # deletes 5 whole lines
C-u C-S-backspace # delete 4 whole lines. C-u without a number defaults to 4
C-u -5 C-S-backspace # deletes previous 5 whole lines
M--5 C-S-backspace # deletes previous 5 whole lines
Sometimes I also find C-x z helpful:
C-S-backspace # delete 1 whole line
C-x z # repeat last command
z # repeat last command again.
# Press z as many times as you wish.
# Any other key acts normally, and ends the repeat command.
In case you don't want to kill the line (which would put it into the OS clipboard and kill ring) but simply delete it:
(defun delete-current-line ()
"Delete (not kill) the current line."
(interactive)
(save-excursion
(delete-region
(progn (forward-visible-line 0) (point))
(progn (forward-visible-line 1) (point)))))
Another method to delete the line without placing it into the kill ring:
(defun delete-current-line ()
"Deletes the current line"
(interactive)
(delete-region
(line-beginning-position)
(line-end-position)))
This will leave the point at the beginning of a blank line. To get rid of this also, you may wish to add something like (delete-blank-lines) to the end of the function, as in this example, which is perhaps a little less intuitive:
(defun delete-current-line ()
"Deletes the current line"
(interactive)
(forward-line 0)
(delete-char (- (line-end-position) (point)))
(delete-blank-lines))
Rather than having separate key to delete line, or having to invoke
prefix-argument. You can use crux-smart-kill-line
which will "kill to the end of the line and kill whole line on the next
call". But if you prefer delete instead of kill, you can use the
code below.
For point-to-string operation (kill/delete) I recommend to use zop-to-char
(defun aza-delete-line ()
"Delete from current position to end of line without pushing to `kill-ring'."
(interactive)
(delete-region (point) (line-end-position)))
(defun aza-delete-whole-line ()
"Delete whole line without pushing to kill-ring."
(interactive)
(delete-region (line-beginning-position) (line-end-position)))
(defun crux-smart-delete-line ()
"Kill to the end of the line and kill whole line on the next call."
(interactive)
(let ((orig-point (point)))
(move-end-of-line 1)
(if (= orig-point (point))
(aza-delete-whole-line)
(goto-char orig-point)
(aza-delete-line))))
source
The fastest/simplest way to delete (kill) a full line, from any point
on the line, without selecting anything, is:
C-w ; kill-region
It is versatile in deleting whatever is selected, or a line by default
if nothing is selected.
Given the question, you're probably also interested in replicating
Vim's "yank", yy (though in Emacs parlance a "yank" is confusingly
Vim's "put", p). This is:
M-w ; kill-ring-save
Nice and congruent, and pretty easy to remember. Even slightly
similar to Vim's i_CTRL-W.
Once you've put something in the kill ring with either of the above,
you'll likely want to "yank" (paste) it:
M-y ; yank-pop
(Note that C-S-backspace may not work in terminal Emacs.)
Install package whole-line-or-region and then run (whole-line-or-region-global-mode). This will make C-w kill the whole line if no region (selection) is active.
See the Package's GitHub page https://github.com/purcell/whole-line-or-region

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

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)