Subject: Re: bug#2887: Suggestions for simple.el

From: Arni Magnusson <[email-masked]>
Date: Sat, 18 Apr 2009 00:08:46 +0000 (GMT)

Thanks Stefan, for forwarding my suggestions to emacs-devel. The 
discussion raised many good points. After considering the viewpoints we 
have heard so far, here are my (revised) opinions:

`backward-delete-word'
`delete-word'

I think Emacs should provide a simple way for beginning users to have 
C-backspace and C-delete behave like they would expect, i.e. leaving the 
clipboard intact. There are different ways to provide this, using a 
variable and/or functions. Users should not need to write their own 
functions for something this fundamental.

`kill-line-or-region'

C-k should probably be bound to this function. This would be appreciated 
by many `transient-mark-mode' users. I haven't used Emacs without 
`transient-mark-mode', but don't those people still want C-w bound to 
`kill-region'?

`pull-line-down'
`pull-line-up'

These are admittedly simple tricks of lesser importance, but anyone trying 
out the existing `transpose-lines' will read its documentation twice and 
try to master pulling lines up or down, before giving up. I find myself 
using these almost every day, with code, data, and config files.

`pos-at-beginning-of-line'
`pos-at-end-of-line'

You're right, it's best to avoid `goto-line'. I have reimplemented these 
functions (see attachment) to improve the speed. I think they bridge an 
obvious gap in Emacs Lisp, making it considerably easier to read and write 
functions that operate on buffer text.

`zap-back-to-char'
`zap-up-to-char'

I believe these more useful than the existing `zap-to-char', which often 
deletes the beginning of that important location, an opening brace or the 
like.

`delete-trailing-white'

> I think [ \t\r] is a good default, and if we introduce a config var 
> (which I'm not sure is worth the trouble), there's no reason to keep the 
> special treatment of formfeed.

I agree that hardwiring [ \t\r] works fastest and is easy to use and 
maintain. Attached is my proposed upgrade of this function, where cleaned 
lines are counted.

`delete-all-blank-lines'

Vertical analog to `delete-trailing-white', which I use about as often. 
Anyone trying out the existing `delete-blank-lines' will wonder whether 
there is a keybinding to delete all blank lines, instead of just around 
the point.

`delete-indentation-nospace'

Similar to `delete-indentation' but leaves no space between the joined 
lines. I find myself using these almost every day, with prose, code, data, 
and config files. I have bound the two functions to neighboring 
keybindings.

`goto-longest-line'

I should probably withdraw this suggestion. After seeing Drew Adam's 
version, I have concluded that my version is too clunky to be in 
simple.el, and Drew's version is too large to be in simple.el. Despite 
being a vertical analog to `end-of-buffer', simple.el should probably not 
provide this functionality.

`downcase-word-or-region'
`upcase-word-or-region'

M-l and M-u could be bound to this function. This would be appreciated by 
many `transient-mark-mode' users. I haven't used Emacs without 
`transient-mark-mode', but don't those people still want C-x C-l and C-x 
C-u bound to `downcase-region' and `upcase-region'?

---

By suggesting so many functions at once, I've taken more of your time than 
I should. I'm very grateful for your hard work maintaining Emacs, and 
discussions like this are worthwhile if they lead to improved editing 
efficiency for users.

The functions are all very short, very convenient in my opinion, and 
importantly they rhyme with functions that are already in simple.el.

> This said, I think those new commands, unbound to any key, shouldn't be 
> placed in simple.el (which is preloaded) but into some other file. I'm 
> tempted to say "misc.el", where we could stuff any number of "commands 
> that users might like, but for which we couldn't come up with a good 
> key-binding".

Ooo, I'm afraid misc.el might be a regrettable move in the long run. I 
think descriptive package names are the way to go, as the base Emacs 
distribution continues to grow. Perhaps simple.el could be split into 
something like base-buffers.el, base-mark.el, etc. As it stands, after 
careful examination of the base packages, I believe my suggested functions 
belong in simple.el.

There are many commands in simple.el that are not bound to keys, 
including:

* Variations of existing bound functions
   `next-error-no-select', `previous-error-no-select'
   `newline-and-indent', `reindent-then-newline-and-indent'
   `undo-only'

* Modify buffer text
   `forward-to-indentation', `backward-to-indentation'
   `fixup-whitespace'

* Information
   `what-line', `what-cursor-position'
   `blink-matching-open'

* Others that I have bound
   `copy-region-as-kill'
   `insert-buffer'

My suggested commands are mainly in one category:

* Variations of existing bound functions
   `backward-delete-word', `delete-word'
   `kill-line-or-region'
   `pull-line-down', `pull-line-up'
   `zap-back-to-char', `zap-up-to-char'
   `delete-indentation-nospace'
   `downcase-word-or-region', `upcase-word-or-region'

* Modify buffer text
   `delete-all-blank-lines'

There are mainly two ways users can find out about such unbound commands: 
docstring cross-references, and brief entries in the Emacs/Emacs Lisp 
manuals. The latter manual mentions practically all commands in simple.el.

Again, my apologies for the length of this message. If any of my 
suggestions end up being accepted, I could add some cross-references to 
their docstrings.

Best regards,

Arni

10,16c10,13
<       (while (re-search-forward "\\s-$" nil t)
< 	(skip-syntax-backward "-" (save-excursion (forward-line 0) (point)))
< 	;; Don't delete formfeeds, even if they are considered whitespace.
< 	(save-match-data
< 	  (if (looking-at ".*\f")
< 	      (goto-char (match-end 0))))
< 	(delete-region (point) (match-end 0))))))
---
>       (let ((count 0))
>         (while (re-search-forward "[ \t\r]+$" nil t)
>           (replace-match "")(setq count (1+ count)))
>         (message "Cleaned %d lines" count)))))