4

I'm using the slick-cut function (as answered here by itsjeyd) for killing the entire line with minimal keystrokes. It's defined like so :-

(defun slick-cut (beg end)
  (interactive
   (if mark-active
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-beginning-position 2)))))

(advice-add 'kill-region :before #'slick-cut)

But, I noticed this behaviour, whenever I kill a line, the cursor will be positioned to the beginning of the next line.

Before killing line 28 :- before killing line 28 After killing line 28 :- After killing line 28 Is there a way one can modify the slick-cut function so that, after killing a line, the cursor column position is also preserved. Like so :- enter image description here

If unable to preserve cursor position, is it possible to at least move the cursor position to the indentation level ?

Chakravarthy Raghunandan
  • 3,132
  • 2
  • 18
  • 42

2 Answers2

3

Here's a version that does what you want. Just bind it to a key.

(defun xah-cut-line-or-region ()
  "Cut current line, or text selection.
When `universal-argument' is called first, cut whole buffer (respects `narrow-to-region').

URL `http://ergoemacs.org/emacs/emacs_copy_cut_current_line.html'
Version 2016-07-29-stackoverflow"
  (interactive)
  (if current-prefix-arg
      (progn ; not using kill-region because we don't want to include previous kill
        (kill-new (buffer-string))
        (delete-region (point-min) (point-max)))
    (if (use-region-p)
        (kill-region (region-beginning) (region-end) t)      
      (progn
        (kill-region (line-beginning-position) (line-beginning-position 2))
        (back-to-indentation)))))

Notice the (back-to-indentation) in the end. That does what you want. Thanks to @kaushalmodi for suggesting this.

Xah Lee
  • 1,756
  • 12
  • 11
  • 1
    You can also just use `(back-to-indentation)` instead. That fn does exactly that: *Move point to the first non-whitespace character on this line.* – Kaushal Modi Jul 19 '16 at 15:32
  • @KaushalModi thanks. I change it to your suggestion. – Xah Lee Jul 19 '16 at 15:50
  • reposted with full code. I realized we can't just add the `back-to-indentation` to advice... – Xah Lee Jul 19 '16 at 16:00
  • 2
    @XahLee why can't we add `back-to-indentation` to slick-cut ? and what is the difference between xah-cut and slick-cut functions? I haven't any elisp yet. So, sorry for asking so many questions. – Chakravarthy Raghunandan Jul 19 '16 at 18:22
  • @ChakravarthyRaghunandan good question. slick-cut is based on emacs's “advice” feature. It determines the region, then calls kill-region via the advice mechanism. I think you can make it work by another post-command advice. But I personally avoid using advice, prefer separate function for simplicity. Thanks for asking. – Xah Lee Jul 19 '16 at 23:42
  • @XahLee there is one caveat to using `(back-to-indentation)` in xah-cut-line-or-region, whenever I invoke the command on a region, the cursor will be moved to the indent level (even if I didn't want it to). So is there a way we can modify xah-cut-line-or-region so that it invokes back-to-indentation only when no region is selected (i.e only when I want to delete the current line) ? – Chakravarthy Raghunandan Jul 28 '16 at 07:26
  • @ChakravarthyRaghunandan yeah that's easy change. I modified the code above. Turns out just move it to a branch of if. I think that should do. – Xah Lee Jul 29 '16 at 08:24
1

Here's a version that remembers column position on kill whole line.

(defun sto/kill-whole-line ()
  "Kill whole line but retain cursor position instead of moving to start of next line."
  (interactive)
  (let ((n (current-column)))
    (kill-whole-line)
    ;; do not move-to-column if that will add whitespaces at the end of line
    (if (< n (- (line-end-position) (line-beginning-position)))
      (move-to-column n t)
      (end-of-line))))

(defun sto/kill-line-or-region ()
  "If no region is selected kill the current line otherwise kill region."
  (interactive)
  (if (use-region-p)
      (kill-region (region-beginning) (region-end) t)
    (sto/kill-whole-line)))

(global-set-key (kbd "C-S-k") 'sto/kill-line-or-region)

rofrol
  • 186
  • 2
  • 8
  • 1
    Using `setq` without declaring variables with `let` clobbers the global scope. Can you improve your code, and add how to use it (how to bind it to a key)? –  Apr 21 '19 at 11:30
  • @user12563 Added changes – rofrol Aug 14 '22 at 17:58