all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#2887: Suggestions for simple.el
@ 2009-04-04 13:32 Arni Magnusson
  2009-04-04 14:21 ` Stefan Monnier
  2020-09-19 21:50 ` Lars Ingebrigtsen
  0 siblings, 2 replies; 27+ messages in thread
From: Arni Magnusson @ 2009-04-04 13:32 UTC (permalink / raw)
  To: bug-gnu-emacs

[-- Attachment #1: Type: text/plain, Size: 986 bytes --]

Dear Emacs maintainers,

I would like to suggest adding a few functions to the simple.el library. I
do this with hesitation - since I know the idea is to keep it simple and
let users write extensions to suit their preferences - but I believe a
large number of Emacs users would appreciate having access to these
functions out of the box.

I just finished teaching an Emacs workshop, where I ended up distributing
these functions to my colleagues, but I found it hard to explain whey
they're not already in simple.el.

Please see the attached file suggestions-simple.el. Instead of giving
detailed reasons for including each function, I have only briefly
commented on which functionality I'm extending, or which gap I'm bridging.

I have used these functions a lot, but I am sure the Emacs maintainers can
see ways to improve them in terms of robustness, speed, function names,
documentation, etc. I would be happy to discuss any further details with
you.

All the best,

Arni Magnusson

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: suggestions-simple.el --]
[-- Type: text/x-emacs-lisp; name="suggestions-simple.el", Size: 4086 bytes --]

;; simple::backward-kill-word
;; subr::backward-delete-char
(defun backward-delete-word (N) "Delete previous N words." (interactive "*p")(delete-word (- N)))
;; simple::kill-word
;; C::delete-char
(defun delete-word (N) "Delete following N words." (interactive "*p")
  (delete-region (point)(save-excursion (forward-word N)(point))))



;; simple::kill-line
;; simple::kill-region
(defun kill-line-or-region () "Kill region if selected, otherwise kill line." (interactive)
  (if (and mark-active transient-mark-mode)(kill-region (point)(mark))(kill-line)))



;; simple::transpose-lines
;; simple::kill-whole-line
(defun pull-line-down (N) "Pull line down N times." (interactive "*p")
  (let ((col (current-column)))(kill-whole-line 1)(forward-line N)(yank 1)(pop kill-ring)(forward-line -1)
       (move-to-column col)))
;; simple::transpose-lines
;; simple::kill-whole-line
(defun pull-line-up (N) "Pull line up N times." (interactive "*p")
  (let ((col (current-column)))(kill-whole-line 1)(forward-line (- N))(yank 1)(pop kill-ring)(forward-line -1)
       (move-to-column col)))



;; simple::goto-line
;; C::point
(defun pos-at-beginning-of-line (N) "Return the position at beginning of line N." (save-excursion (goto-line N)(point)))
(defun pos-at-end-of-line (N) "Return the position at end of line N." (save-excursion (goto-line N)(end-of-line)(point)))



;; simple::zap-to-char
;; C::delete-region
(defun zap-back-to-char (char) "Delete region back to, but not including, CHAR." (interactive "cZap back to char: ")
  (let ((case-fold-search nil))
    (delete-region (point)(progn (search-backward (char-to-string char))(forward-char)(point)))))
;; simple::zap-to-char
;; C::delete-region
(defun zap-up-to-char (char) "Delete region up to, but not including, CHAR." (interactive "cZap to char: ")
  (let ((case-fold-search nil))
    (delete-region (point)(progn (search-forward (char-to-string char))(backward-char)(point)))))



;; simple::delete-trailing-whitespace
;; whitespace::whitespace-buffer
(defun clean-trails () "Delete ^M glyphs, spaces, and tabs from line ends." (interactive) ; \r means ^M
  (save-excursion (goto-char (point-min)) ; unlike delete-trailing-whitespace, clean-trails removes ^M (\r) in lisp-mode
                  (let ((count 0))(while (re-search-forward "[\r\t ]+$" nil t)(replace-match "")(setq count (+ count 1)))
                       (message "Cleaned %d lines" count))))
;; simple::delete-blank-lines
;; whitespace::whitespace-buffer
(defun delete-all-blank-lines () "Delete all blank lines in buffer." (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((count 0))(while (search-forward "\n\n" nil t)(goto-char (point-min))
                           (while (search-forward "\n\n" nil t)(replace-match "\n")(setq count (+ count 1)))
                           (goto-char (point-min)))
         (if (= (following-char) 10)(progn (delete-char 1)(setq count (+ count 1))))
         (message "Deleted %d blank lines" count))))



;; simple::delete-indentation
(defun delete-indentation-nospace () "Join this line to previous with no whitespace at join." (interactive)
  (delete-indentation)(delete-horizontal-space))



;; simple::end-of-buffer
;; simple::goto-line
(defun goto-longest-line () "Go to longest line in buffer." (interactive)
  (let ((line 1)(length 0))
    (save-excursion
      (goto-char (point-min))(end-of-line)(setq length (current-column))
      (while (not (eobp))
        (progn (end-of-line 2)
               (if (> (current-column) length)(progn (setq line (line-number-at-pos))(setq length (current-column)))))))
    (goto-line line)(message "Line %d is %d characters" line length)))



;; C::downcase-region
;; C::downcase-word
;; belongs in simple
(defun downcase-word-or-region (N) "Downcase N words or region." (interactive "*p")
  (if (and mark-active transient-mark-mode)(downcase-region (point)(mark))(downcase-word N)))
(defun upcase-word-or-region (N) "Upcase N words or region." (interactive "*p")
  (if (and mark-active transient-mark-mode)(upcase-region (point)(mark))(upcase-word N)))

^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-04 13:32 bug#2887: Suggestions for simple.el Arni Magnusson
@ 2009-04-04 14:21 ` Stefan Monnier
  2009-04-04 23:35   ` Arni Magnusson
  2020-09-19 21:50 ` Lars Ingebrigtsen
  1 sibling, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2009-04-04 14:21 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

> Please see the attached file suggestions-simple.el. Instead of giving
> detailed reasons for including each function, I have only briefly
> commented on which functionality I'm extending, or which gap I'm bridging.

I'd rather see detailed reasons for each function/command you suggest.
E.g. why do you need a backward-delete-word when we already provide
backward-kill-word?


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-04 14:21 ` Stefan Monnier
@ 2009-04-04 23:35   ` Arni Magnusson
  2009-04-05  3:27     ` Stefan Monnier
  0 siblings, 1 reply; 27+ messages in thread
From: Arni Magnusson @ 2009-04-04 23:35 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

Thank you, Stefan, for the prompt reply and interest. Please find below my
list of raisons d'être.

Arni



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

Users can delete words while leaving the kill-ring unchanged. For example,
the user has copied a table from somewhere and is now deleting some words
before yanking the table where it belongs. It would be frustrating for the
user to yank and see recently deleted words instead of the table.



`kill-line-or-region'

Users can bind C-k to kill lines and regions (do what I mean), as an
alternative to the default C-k and C-w setup.



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

Users can move lines up and down more effectively thank with
`transpose-lines'.



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

Useful when writing a variety of editing functions. Should be in simple.el
for the same resons as `line-beginning-position' and `line-end-position'
are there.



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

Zapping is typically to delete garbage until some important location. The
existing `zap-to-char' often deletes the beginning of that important
location, an opening brace or the like.



`clean-trails'

Like `delete-trailing-white', but reports how many lines were cleaned, and
deletes ^M as well. Many programs and programmers write files with
trailing spaces and ^M glyphs. It's nice to be able to clean those and get
body count in one keystroke.



`delete-all-blank-lines'

It's often useful to get rid of extra vertical spacing in source code,
output files, etc., sometimes undoing after enjoying the squeezed view.
Without this command, it would take a lot of keystrokes to delete all
blank lines while retaining the cursor buffer position.



`delete-indentation-nospace'

The `delete-indentation' command is very useful, but it often creates an
unwanted space. Users will probably bind this command to a keystroke close
to the `delete-indentation' keystroke.



`goto-longest-line'

Users can find out the maximum width (columns) of a text file, to check
the coding style or for some other reason. Sometimes it's easiest to call
"wc -L" via `shell-command' or `dired-do-shell-command', but
`goto-longest-line' will often be quicker and moves the cursor to the
longest line, for closer examination.

I remember when I wrote this command I thought about implementing a
separate non-interactive function called `longest-line' that would just
return the line number. Then `goto-longest-line' would call `longest-line'
to do the calculations, and other functions might call `longest-line' with
some other purpose than moving the cursor to it. I would be happy to
contribute a two-function implementation instead, since `longest-line'
might be useful for many users.



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

Users can bind M-l and M-u to downcase/upcase words or regions (do what I
mean), as an alternative to the default C-x C-l, C-x C-u, M-l, and M-u
setup.








^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-04 23:35   ` Arni Magnusson
@ 2009-04-05  3:27     ` Stefan Monnier
  2009-04-05 14:26       ` Leo
  2009-04-05 20:17       ` Arni Magnusson
  0 siblings, 2 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-05  3:27 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

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

> Users can delete words while leaving the kill-ring unchanged. For example,
> the user has copied a table from somewhere and is now deleting some words
> before yanking the table where it belongs. It would be frustrating for the
> user to yank and see recently deleted words instead of the table.

Which leads to the following questions:
- is it really that important given that the user could get the same
  result by yanking first and deleting the words afterwards?
- why is this important for *kill-word, but not for all the other
  kill operations?
- the most important one: who's going to do M-x delete-word rather than
  work around the problem some other way?  I.e. such a command is
  basically useless unless it's bound to a key, so the problem is not so
  much the command as it is to find a key for it.

> `kill-line-or-region'

> Users can bind C-k to kill lines and regions (do what I mean), as an
> alternative to the default C-k and C-w setup.

That might be OK.  Many people who'd like it, might prefer to just use
some variant of delete-selection-mode, tho.

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

> Users can move lines up and down more effectively thank with
> `transpose-lines'.

Can you summarize the difference?

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

> Useful when writing a variety of editing functions. Should be in simple.el
> for the same resons as `line-beginning-position' and `line-end-position'
> are there.

Actually, line-*-position are in the C code (and if they were written in
Lisp, they should be in subr.el rather than in simple.el).  The problem
with pos-at-*-of-line is that goto-line is costly, so Elisp generally
shouldn't encourage its use.

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

> Zapping is typically to delete garbage until some important location.
> The existing `zap-to-char' often deletes the beginning of that
> important location, an opening brace or the like.

I never use zap-to-char, so I'll let other people judge if that can
be useful.

> `clean-trails'

> Like `delete-trailing-white', but reports how many lines were cleaned, and
> deletes ^M as well. Many programs and programmers write files with
> trailing spaces and ^M glyphs. It's nice to be able to clean those and get
> body count in one keystroke.

The report of number of lines cleaned sounds like a good addition to
delete-trailing-whitespace.  Not sure about ^M since I basically never
bumped into it (or rather I always handle it via eol-conversion), but if
it's useful, it would also be beter to incorporate it into
delete-trailing-whitespace than create a new command for it.

> `delete-all-blank-lines'

> It's often useful to get rid of extra vertical spacing in source code,
> output files, etc., sometimes undoing after enjoying the squeezed view.
> Without this command, it would take a lot of keystrokes to delete all
> blank lines while retaining the cursor buffer position.

I've never needed such a command, so again, I'll let other people judge
if it is sufficiently generally useful to find its way in Emacs.

> `delete-indentation-nospace'

> The `delete-indentation' command is very useful, but it often creates an
> unwanted space. Users will probably bind this command to a keystroke close
> to the `delete-indentation' keystroke.

delete-indentation tries to guess when spaces are wanted.  Maybe we
could improve the guess instead?

> `goto-longest-line'

> Users can find out the maximum width (columns) of a text file, to check
> the coding style or for some other reason. Sometimes it's easiest to call
> "wc -L" via `shell-command' or `dired-do-shell-command', but
> `goto-longest-line' will often be quicker and moves the cursor to the
> longest line, for closer examination.

> I remember when I wrote this command I thought about implementing a
> separate non-interactive function called `longest-line' that would just
> return the line number. Then `goto-longest-line' would call `longest-line'
> to do the calculations, and other functions might call `longest-line' with
> some other purpose than moving the cursor to it. I would be happy to
> contribute a two-function implementation instead, since `longest-line'
> might be useful for many users.

There's no point not moving to the line, even if used from Elisp (since
it's just as easy to wrap the call in a save-excursion if needed), so
the command works as well from Lisp.

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

> Users can bind M-l and M-u to downcase/upcase words or regions (do what I
> mean), as an alternative to the default C-x C-l, C-x C-u, M-l, and M-u
> setup.

That sounds OK.

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


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-05  3:27     ` Stefan Monnier
@ 2009-04-05 14:26       ` Leo
  2009-04-05 20:17       ` Arni Magnusson
  1 sibling, 0 replies; 27+ messages in thread
From: Leo @ 2009-04-05 14:26 UTC (permalink / raw)
  To: bug-gnu-emacs

On 2009-04-05 04:27 +0100, Stefan Monnier wrote:
>> `zap-back-to-char'
>> `zap-up-to-char'
>
>> Zapping is typically to delete garbage until some important location.
>> The existing `zap-to-char' often deletes the beginning of that
>> important location, an opening brace or the like.
>
> I never use zap-to-char, so I'll let other people judge if that can
> be useful.

I think those functions are already in emacs. Take a look at its lisp
dir, i think it is misc.el.

-- 
.:  Leo  :.  [ sdl.web AT gmail.com ]  .: I use Emacs :.

               www.git-scm.com
    git - the one true version control system








^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-05  3:27     ` Stefan Monnier
  2009-04-05 14:26       ` Leo
@ 2009-04-05 20:17       ` Arni Magnusson
  2009-04-05 21:59         ` Lennart Borgman
  2009-04-06  2:14         ` Stefan Monnier
  1 sibling, 2 replies; 27+ messages in thread
From: Arni Magnusson @ 2009-04-05 20:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

Thank you, Stefan, for the insightful comments. We're discussing quite a
few things at once, but I'll try to be concise:

>> `backward-delete-word'
>> `delete-word'
>
>> Users can delete words while leaving the kill-ring unchanged. For
>> example, the user has copied a table from somewhere and is now
>> deleting some words before yanking the table where it belongs. It
>> would be frustrating for the user to yank and see recently deleted
>> words instead of the table.
>
> Which leads to the following questions:
>
> - is it really that important given that the user could get the same
>   result by yanking first and deleting the words afterwards?

The default behavior of practically all editors is to delete words without
altering the clipboard. The principle of least surprise says Emacs should
at least make it easy for users to bind C-backspace to
`backward-delete-word' and C-delete to `delete-word', if that's the
behavior they prefer.

> - why is this important for *kill-word, but not for all the other kill
>   operations?

Because deleting words is probably the most common deletion, after
deleting characters. It would frustrate many more users if `delete-char'
would alter the kill ring.

> - the most important one: who's going to do M-x delete-word rather
>   than work around the problem some other way? I.e. such a command is
>   basically useless unless it's bound to a key, so the problem is not
>   so much the command as it is to find a key for it.

The Emacs manual and the documentation of `kill-word' and
`backward-kill-word' could mention that some users may prefer binding
C-backspace to `backward-delete-word' and C-delete to `delete-word'.



>> `kill-line-or-region'
>
>> Users can bind C-k to kill lines and regions (do what I mean), as an
>> alternative to the default C-k and C-w setup.
>
> That might be OK. Many people who'd like it, might prefer to just use
> some variant of delete-selection-mode, tho.

Again, the important distinction between killing and deleting. Even in
`delete-selection-mode', the `kill-line-or-region' command is useful for
yanking the text later.



>> `pull-line-down'
>> `pull-line-up'
>
>> Users can move lines up and down more effectively thank with
>> `transpose-lines'.
>
> Can you summarize the difference?

To move a line 3 down, call `pull-line-down' 3 times or with a numerical
argument of 3. Likewise with `pull-line-up'. Most Emacs users would
probably do this by killing and yanking, but it's considerably quicker
using the pull-line-* commands. The `transpose-lines' command may be
useful in some circumstances, but not in the tasks described above.



>> `pos-at-beginning-of-line'
>> `pos-at-end-of-line'
>
>> Useful when writing a variety of editing functions. Should be in
>> simple.el for the same resons as `line-beginning-position' and
>> `line-end-position' are there.
>
> Actually, line-*-position are in the C code (and if they were written
> in Lisp, they should be in subr.el rather than in simple.el). The
> problem with pos-at-*-of-line is that goto-line is costly, so Elisp
> generally shouldn't encourage its use.

My commands that call pos-at-*-of-line work faster than I can blink my
eyes, but I understand your concern. To optimize the speed the functions
would probably need to be implemented in C code, but that's beyond my
programming capabilities. Still, if I'm not mistaken, Emacs Lisp
programmers would have to use something just as expensive to perform this
task, so pos-at-*-of-line would save them some typing and thinking.


>> `zap-back-to-char'
>> `zap-up-to-char'
>
>> Zapping is typically to delete garbage until some important location.
>> The existing `zap-to-char' often deletes the beginning of that
>> important location, an opening brace or the like.
>
> I never use zap-to-char, so I'll let other people judge if that can be
> useful.

It's a common task to delete everything between the point and another
location. Zapping is best if that location contains a somewhat rare
character, usually some kind of symbol or parenthesis. In my experience
the character itself should usually not be deleted as well.



>> `clean-trails'
>
>> Like `delete-trailing-white', but reports how many lines were
>> cleaned, and deletes ^M as well. Many programs and programmers write
>> files with trailing spaces and ^M glyphs. It's nice to be able to
>> clean those and get body count in one keystroke.
>
> The report of number of lines cleaned sounds like a good addition to
> delete-trailing-whitespace. Not sure about ^M since I basically never
> bumped into it (or rather I always handle it via eol-conversion), but
> if it's useful, it would also be beter to incorporate it into
> delete-trailing-whitespace than create a new command for it.

Yes, it would be a nice improvement to upgrade the
`delete-trailing-whitespace' command so it counts cleaned lines.

Files with mixed Unix/Dos line endings are sometimes created when people
using different OS's work together on a project. Many programs choke on
input files that contain mixed Unix/Dos line endings, often without
helpful error messages.

If the Emacs maintainers decide to make `delete-trailing-whitespace' also
delete trailing ^M in mixed line-ending files, it would make me (and
presumably many other users) happy, but it might create a
backwards-compatibility issue.

Adding an &optional ctrl-M flag to `delete-trailing-whitespace' (non-nil
to remove trailing ^M as well) would not enable to users to bind a simple
keystroke to do that. What I propose is a separate function
`delete-trailing-whitespace-M' that removes both trailing whitespace and
trailing ^M in files with mixed line endings. A bulky solution, but I
think users will appreciate it.



>> `delete-all-blank-lines'
>
>> It's often useful to get rid of extra vertical spacing in source
>> code, output files, etc., sometimes undoing after enjoying the
>> squeezed view. Without this command, it would take a lot of
>> keystrokes to delete all blank lines while retaining the cursor
>> buffer position.
>
> I've never needed such a command, so again, I'll let other people
> judge if it is sufficiently generally useful to find its way in Emacs.

It's often a good way to get an overview of code that is vertically
stretched. I remove all comments (one keystroke) and all blank lines
(another keystroke), absorb the information and undo. I also use it on
certain program input files where blank lines would be problematic.



>> `delete-indentation-nospace'
>
>> The `delete-indentation' command is very useful, but it often creates
>> an unwanted space. Users will probably bind this command to a
>> keystroke close to the `delete-indentation' keystroke.
>
> delete-indentation tries to guess when spaces are wanted. Maybe we
> could improve the guess instead?

These functions are used in a wide variety of situations (text, code,
data), making guesswork practically hopeless. I use `delete-indentation'
and `delete-indentation-nospace' a lot, and I'm not sure which one I use
more frequently.



>> `goto-longest-line'
>
>> Users can find out the maximum width (columns) of a text file, to
>> check the coding style or for some other reason. Sometimes it's
>> easiest to call "wc -L" via `shell-command' or
>> `dired-do-shell-command', but `goto-longest-line' will often be
>> quicker and moves the cursor to the longest line, for closer
>> examination.
>
>> I remember when I wrote this command I thought about implementing a
>> separate non-interactive function called `longest-line' that would
>> just return the line number. Then `goto-longest-line' would call
>> `longest-line' to do the calculations, and other functions might call
>> `longest-line' with some other purpose than moving the cursor to it.
>> I would be happy to contribute a two-function implementation instead,
>> since `longest-line' might be useful for many users.
>
> There's no point not moving to the line, even if used from Elisp
> (since it's just as easy to wrap the call in a save-excursion if
> needed), so the command works as well from Lisp.

Good call, one function it is.



>> `downcase-word-or-region'
>> `upcase-word-or-region'
>
>> Users can bind M-l and M-u to downcase/upcase words or regions (do
>> what I mean), as an alternative to the default C-x C-l, C-x C-u, M-l,
>> and M-u setup.
>
> That sounds OK.

Great.



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

I would slip them into simple.el, since they load very fast and rhyme with
what's already there. Allow me to propose the following bindings that are
undefined in Emacs 22.3.1:

C-x C-backspace  backward-delete-word
C-x C-delete     delete-word
C-;              kill-line-or-region
M-n              pull-line-down
M-p              pull-line-up
C-,              zap-back-to-char
C-.              zap-up-to-char
C-'              clean-trails
C-"              delete-all-blank-lines
M-&              delete-indentation-nospace
C-=              goto-longest-line
M-down           downcase-word-or-region
M-up             upcase-word-or-region








^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-05 20:17       ` Arni Magnusson
@ 2009-04-05 21:59         ` Lennart Borgman
  2009-04-06  2:14         ` Stefan Monnier
  1 sibling, 0 replies; 27+ messages in thread
From: Lennart Borgman @ 2009-04-05 21:59 UTC (permalink / raw)
  To: Arni Magnusson, 2887

On Sun, Apr 5, 2009 at 10:17 PM, Arni Magnusson <arnima@hafro.is> wrote:
>>> It's often useful to get rid of extra vertical spacing in source
>>> code, output files, etc., sometimes undoing after enjoying the
>>> squeezed view. Without this command, it would take a lot of
>>> keystrokes to delete all blank lines while retaining the cursor
>>> buffer position.
>>
>> I've never needed such a command, so again, I'll let other people
>> judge if it is sufficiently generally useful to find its way in Emacs.
>
> It's often a good way to get an overview of code that is vertically
> stretched. I remove all comments (one keystroke) and all blank lines
> (another keystroke), absorb the information and undo. I also use it on
> certain program input files where blank lines would be problematic.

I can see the idea, but I would suggest a minor mode that hide
comments and blank lines instead.

That would allow editing the file with comments and blank line hidden.

> M-down           downcase-word-or-region
> M-up             upcase-word-or-region

Key bindings is a scarce resource. Those two bindings are already used
by windmove.el for moving between windows (and that is something that
perhaps should be on by default).






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-05 20:17       ` Arni Magnusson
  2009-04-05 21:59         ` Lennart Borgman
@ 2009-04-06  2:14         ` Stefan Monnier
  2009-04-06  3:02           ` Drew Adams
  2009-04-07  2:46           ` Arni Magnusson
  1 sibling, 2 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-06  2:14 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

> The Emacs manual and the documentation of `kill-word' and
> `backward-kill-word' could mention that some users may prefer binding
> C-backspace to `backward-delete-word' and C-delete to `delete-word'.

The Emacs manual is already "too large" to contain all the info we want
to put in it, so mentioning such things is unlikely.
But it's probably a good idea to add those commands to misc.el.
Then the EmacsWiki can mention them.

> My commands that call pos-at-*-of-line work faster than I can blink my
> eyes, but I understand your concern.

Try them on 200MB buffers.

> To optimize the speed the functions would probably need to be
> implemented in C code, but that's beyond my programming
> capabilities.

The core loop is in goto-line and is already written in C.

> Still, if I'm not mistaken, Emacs Lisp programmers would
> have to use something just as expensive to perform this task, so
> pos-at-*-of-line would save them some typing and thinking.

The point is to force them to use goto-line explicitly, so as to
hopefully make the cost more obvious.

> It's a common task to delete everything between the point and another
> location. Zapping is best if that location contains a somewhat rare
> character, usually some kind of symbol or parenthesis. In my experience
> the character itself should usually not be deleted as well.

I tend to use C-s for that (as well as for movement).  But I understand
that other people have other habits.

> Yes, it would be a nice improvement to upgrade the
> `delete-trailing-whitespace' command so it counts cleaned lines.

Feel free to provide a patch for it (tho, since we're in the pretest,
there's no hurry: it won't be installed right now).

> Files with mixed Unix/Dos line endings are sometimes created when people
> using different OS's work together on a project.  Many programs choke on
> input files that contain mixed Unix/Dos line endings, often without
> helpful error messages.

I understand the problem, yes.  I just don't know it enough to
understand which kind of solution is more handy.  The few times I've had
such a thing, I just did M-% C-q C-m RET RET !.  For such rare
occurrences, anything more specialized would be useless because
I wouldn't remember it.  Obviously, if it happens commonly to you,
you'll want another solution.

> If the Emacs maintainers decide to make `delete-trailing-whitespace' also
> delete trailing ^M in mixed line-ending files, it would make me (and
> presumably many other users) happy, but it might create a
> backwards-compatibility issue.

It might, but I'm not sure it'd be such a big deal.  The docstring
explicitly mentions that a form-feed is not considered as whitespace by
this function, so that might be taken to mean that "every other
whitespace-like chars" (such as C-m) would be considered as whitespace.

> These functions are used in a wide variety of situations (text, code,
> data), making guesswork practically hopeless. I use `delete-indentation'
> and `delete-indentation-nospace' a lot, and I'm not sure which one I use
> more frequently.

What bindings do you use?

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

> I would slip them into simple.el, since they load very fast and rhyme with
> what's already there.

As mentioned, simple.el is preloaded, so anything we add to it increases
the size of Emacs for everyone, whether they use it or not.

> Allow me to propose the following bindings that are
> undefined in Emacs 22.3.1:

There's a good reason why they're undefined: most of those keys can't be
pressed under a tty.


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-06  2:14         ` Stefan Monnier
@ 2009-04-06  3:02           ` Drew Adams
  2009-04-07  2:46           ` Arni Magnusson
  1 sibling, 0 replies; 27+ messages in thread
From: Drew Adams @ 2009-04-06  3:02 UTC (permalink / raw)
  To: 'Stefan Monnier', 2887, 'Arni Magnusson'

> But it's probably a good idea to add those commands to misc.el.
> Then the EmacsWiki can mention them.

Huh? What kind of reasoning is that?

If that's the reason, just put the code on EmacsWiki - no reason to add it to
Emacs. Sheesh.







^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-06  2:14         ` Stefan Monnier
  2009-04-06  3:02           ` Drew Adams
@ 2009-04-07  2:46           ` Arni Magnusson
  2009-04-07 14:02             ` Stefan Monnier
  1 sibling, 1 reply; 27+ messages in thread
From: Arni Magnusson @ 2009-04-07  2:46 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

>> My commands that call pos-at-*-of-line work faster than I can blink
>> my eyes, but I understand your concern.
>
> Try them on 200MB buffers.

When I'm editing a 212MB text file, many things become sluggish, but
pos-at-*-of-line is not one of them:

  M-x benchmark (pos-at-end-of-line 1000000)    ; 0.157s
  10 M-x benchmark (pos-at-end-of-line 1000000) ; 0.719s

This speed is similar to line-*-position:

  M-x benchmark (line-end-position 1000000)    ; 0.172s
  10 M-x benchmark (line-end-position 1000000) ; 0.734s



>> Yes, it would be a nice improvement to upgrade the
>> `delete-trailing-whitespace' command so it counts cleaned lines.
>
> Feel free to provide a patch for it (tho, since we're in the pretest,
> there's no hurry: it won't be installed right now).

Here is a candidate upgrade of `delete-trailing-whitespace':

(defun delete-trailing-whitespace ()
  "Delete all the trailing whitespace across the current buffer.
All whitespace after the last non-whitespace character in a line is deleted.
This respects narrowing, created by \\[narrow-to-region] and friends.
A formfeed is not considered whitespace by this function."
  (interactive "*")
  (save-match-data
    (save-excursion
      (goto-char (point-min))
      (let ((count 0)(table (syntax-table)))
        (modify-syntax-entry ?\f "." table) ; never delete formfeeds
        (modify-syntax-entry ?\n "." table) ; never delete newline
        (with-syntax-table table
          (while (re-search-forward "\\s-+$" nil t)
            (replace-match "")(setq count (1+ count)))
          (message "Cleaned %d lines" count))))))

Although the code is substantially different, it performs precisely the
same deletions as the existing revision 1.985, and the computational speed
is comparable. The user-visible difference is that it reports how many
lines were cleaned. The code is clear and extensible.

One possible change is to add one important line, while still fulfilling
the current documentation:

  (modify-syntax-entry ?\r " " table) ; always delete trailing ^M

And here's a version that deletes only trailing spaces, tabs, and ^M glyphs:

(defun delete-trailing-whitespace ()
  "Delete all the trailing whitespace across the current buffer.
All whitespace after the last non-whitespace character in a line is deleted.
This respects narrowing, created by \\[narrow-to-region] and friends.
A formfeed is not considered whitespace by this function."
  (interactive "*")
  (save-match-data
    (save-excursion
      (goto-char (point-min))
      (let ((count 0))
        (while (re-search-forward "[ \r\t]+$" nil t)
          (replace-match "")(setq count (1+ count)))
        (message "Cleaned %d lines" count)))))

This performs 4x faster than the first candidate upgrade, because the
regexp matches only 3 characters, whereas "\\s-+$" matches 147 different
characters in text-mode. The syntax table definitions of whitespace can be
confusing, e.g. the ^M glyph is considered whitespace in text-mode but not
in emacs-lisp-mode...

After this explanatory introduction, my real proposal is to define a
variable to determine the behavior of `delete-trailing-whitespace':

(defvar trailing-whitespace-regexp "\\s-+$"
  "Regular expression describing what `delete-trailing-whitespace'
should delete. Note that regardless of the value of
`trailing-whitespace-regexp', `delete-trailing-whitespace' will never
delete formfeed and newline characters.

The default value \"\\\\s-+$\" uses the current syntax table definitions
of whitespace, but an expression like \"[ \\r\\t]+$\" is faster and
consistent across modes.")

(defun delete-trailing-whitespace ()
  "Delete all trailing whitespace, as defined by
`trailing-whitespace-regexp', in the current buffer. All whitespace
after the last non-whitespace character in a line is deleted. This
respects narrowing, created by \\[narrow-to-region] and friends.

Note that regardless of the value of `trailing-whitespace-regexp',
`delete-trailing-whitespace' will never delete formfeed and newline
characters."
  (interactive "*")
  (save-match-data
    (save-excursion
      (goto-char (point-min))
      (let ((count 0)(table (syntax-table)))
        (modify-syntax-entry ?\f "." table) ; never delete formfeeds
        (modify-syntax-entry ?\n "." table) ; never delete newline
        (with-syntax-table table
          (while (re-search-forward whitespace-regexp nil t)
            (replace-match "")(setq count (1+ count)))
          (message "Cleaned %d lines" count))))))

This version of `delete-trailing-whitespace' can mimic my `clean-trails',
making that function unnecessary.



>> These functions are used in a wide variety of situations (text, code,
>> data), making guesswork practically hopeless. I use
>> `delete-indentation' and `delete-indentation-nospace' a lot, and I'm
>> not sure which one I use more frequently.
>
> What bindings do you use?

M-j and C-M-j, overriding the defaults.



>> Allow me to propose the following bindings that are undefined in
>> Emacs 22.3.1:
>
> There's a good reason why they're undefined: most of those keys can't
> be pressed under a tty.

Good point. Here are some undefined keystrokes in Emacs 22.3.1 that seem
to get through:

  C-x j    backward-delete-word
  C-x C-j  delete-word
  C-x x    kill-line-or-region
  M-n      pull-line-down
  M-p      pull-line-up
  C-M-z    zap-back-to-char
  C-M-m    zap-up-to-char
  C-x C-a  delete-all-blank-lines
  M-&      delete-indentation-nospace
  C-x w    goto-longest-line
  C-x y    downcase-word-or-region
  C-x C-y  upcase-word-or-region

Thank you for your patience and thoughtful responses,

Arni








^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07  2:46           ` Arni Magnusson
@ 2009-04-07 14:02             ` Stefan Monnier
  2009-04-07 16:09               ` Drew Adams
                                 ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-07 14:02 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

> The default behavior of practically all editors is to delete words
> without altering the clipboard. The principle of least surprise says
> Emacs should at least make it easy for users to bind C-backspace to
> `backward-delete-word' and C-delete to `delete-word', if that's the
> behavior they prefer.

But do those editors offer the equivalent of M-y?

> When I'm editing a 212MB text file, many things become sluggish, but
> pos-at-*-of-line is not one of them:
>   M-x benchmark (pos-at-end-of-line 1000000)    ; 0.157s

This timing means that if a command calls this function for lines near
point, that command becomes sluggish when you get to the end of the
buffer.  If it calls it 100 times, the command becomes
completely unusable.

> This speed is similar to line-*-position:
>   M-x benchmark (line-end-position 1000000)    ; 0.172s
>   10 M-x benchmark (line-end-position 1000000) ; 0.734s

Of course.  But line-end-position is usually called with small args
because it's a relative position.

> Here is a candidate upgrade of `delete-trailing-whitespace':

Please send it as a patch so we can see what's changed rather than only
see the end result.

> This performs 4x faster than the first candidate upgrade, because the
> regexp matches only 3 characters, whereas "\\s-+$" matches 147 different
> characters in text-mode.

Actually, it isn't quite for that reason, it's much worse: \s- is
a regexp that may potentially match *any* character (depending on the
syntax-table text-property), so contrary to [ \t\r] which can use
a "fastmap" to quickly skip over irrelevant chars, \s- has to spend
a lot more time on each char.

> The syntax table definitions of whitespace can be confusing, e.g. the
> ^M glyph is considered whitespace in text-mode but not in
> emacs-lisp-mode...

Agreed.

> After this explanatory introduction, my real proposal is to define a
> variable to determine the behavior of `delete-trailing-whitespace':

> (defvar trailing-whitespace-regexp "\\s-+$"
>   "Regular expression describing what `delete-trailing-whitespace'
> should delete. Note that regardless of the value of
> `trailing-whitespace-regexp', `delete-trailing-whitespace' will never
> delete formfeed and newline characters.

> The default value \"\\\\s-+$\" uses the current syntax table definitions
> of whitespace, but an expression like \"[ \\r\\t]+$\" is faster and
> consistent across modes.")

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.

>       (let ((count 0)(table (syntax-table)))
>         (modify-syntax-entry ?\f "." table) ; never delete formfeeds
>         (modify-syntax-entry ?\n "." table) ; never delete newline
>         (with-syntax-table table
>           (while (re-search-forward whitespace-regexp nil t)
>             (replace-match "")(setq count (1+ count)))
>           (message "Cleaned %d lines" count))))))

This modifies the current syntax-table (because `syntax-table' returns
the table itself, not a copy).

> Good point. Here are some undefined keystrokes in Emacs 22.3.1 that seem
> to get through:

>   C-x j    backward-delete-word
>   C-x C-j  delete-word
>   C-x x    kill-line-or-region
>   M-n      pull-line-down
>   M-p      pull-line-up
>   C-M-z    zap-back-to-char
>   C-M-m    zap-up-to-char
>   C-x C-a  delete-all-blank-lines
>   M-&      delete-indentation-nospace
>   C-x w    goto-longest-line
>   C-x y    downcase-word-or-region
>   C-x C-y  upcase-word-or-region

> Thank you for your patience and thoughtful responses,

I think I will prefer to leave those unbound for now, waiting for more
generally useful commands, or more general agreement that they are
generally useful.  Note that for some of them (e.g. kill-line-or-region
or downcase-word-or-region), you might want to try and argue that their
functionality should simply be folded into the kill-line
resp. downcase-word (which might let us free up C-x C-u and C-x C-l, and
maybe even C-w).


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 14:02             ` Stefan Monnier
  2009-04-07 16:09               ` Drew Adams
@ 2009-04-07 16:09               ` Drew Adams
  2009-04-18  0:08               ` Arni Magnusson
  2 siblings, 0 replies; 27+ messages in thread
From: Drew Adams @ 2009-04-07 16:09 UTC (permalink / raw)
  To: 'Stefan Monnier', 2887, 'Arni Magnusson'; +Cc: emacs-devel

> >   C-x j    backward-delete-word
> >   C-x C-j  delete-word
> >   C-x x    kill-line-or-region
> >   M-n      pull-line-down
> >   M-p      pull-line-up
> >   C-M-z    zap-back-to-char
> >   C-M-m    zap-up-to-char
> >   C-x C-a  delete-all-blank-lines
> >   M-&      delete-indentation-nospace
> >   C-x w    goto-longest-line
> >   C-x y    downcase-word-or-region
> >   C-x C-y  upcase-word-or-region
> 
> I think I will prefer to leave those unbound for now, waiting for more
> generally useful commands, or more general agreement that they are
> generally useful.

So it sounds as if you're actually going to add these things to Emacs (even if
you don't bind them by default)?

If so, that's quite surprising, especially since the policy has always been
_not_ to add functions simply because they _might_ be generally useful. Not to
mention the tradition of case-by-case discussion in emacs-devel first, including
discussion of rationale (e.g. use cases).

Whatever. In that case, below is my version of `goto-longest-line', published
under that name over two years ago.

I also sent it to emacs-devel on two occasions: 2008-1-23 (thread "find longest
lines during isearch") and 2008-06-21 (thread "Another neat Eclispe'ism").
http://lists.gnu.org/archive/html/emacs-devel/2008-01/msg01611.html
http://lists.gnu.org/archive/html/emacs-devel/2008-06/msg01442.html

My version has these advantages:

* If the region is active, it is restricted to the region.

* If repeated, it goes to the longest line after the cursor.

* You can use it to search from point forward only, by using `C-SPC' first.

* It highlights the line (using `hl-line-highlight').

* It returns, as a list: the line #, its length, a list of other lines just as
long (there can be more than one "longest line"), and the number of lines
checked.

* Interactively, it echoes all of that info. Example messages:
  Line 234: 76 chars, (459 lines measured)
  Line 234: 76 chars, Others: {239, 313} (459 lines measured)

I bind [(control end)] to this command in `isearch-mode-map' (when
`window-system'). This is the way I typically call it: `C-s C-end'. Repeatedly
move to longest line after point: `C-x C-end C-end...'. And `C-g' returns you to
the point where searching starts, so you can use it to see where long lines are
without necessarily moving there and staying. I also bind it to `C-x L', but I
typically use it from Isearch.

A related command is `goto-long-line', which goes to the first line that is at
least N chars long. N is the `fill-column' by default, or provided explicitly by
`C-u'.

If you are really interested in adding general, miscellaneous commands and
functions that might be useful ("waiting for more generally useful commands"), I
have plenty more, and there are hundreds more by others, on Emacs Wiki and
elsewhere. 

The `goto-long*-line' commands and others are here:
http://www.emacswiki.org/emacs/misc-cmds.el. And there is a wiki page loaded
with commands for finding, visualizing, and moving to long lines:
http://www.emacswiki.org/emacs/FindLongLines.

I really didn't think this was how Emacs development proceeded, but apparently
there has been a change (?).

FWIW, I think emacs-devel is the proper place to discuss additions and other
changes to Emacs. It's OK for enhancement suggestions to be submitted to the
bugs list, but concrete discussion about adding or changing Emacs code should be
done in emacs-devel, IMO. And such discussion should precede actually making
changes.

;---------------8<-----------------------
(defun goto-longest-line (beg end)
  "Go to the first of the longest lines in the region or buffer.
If the region is active, it is checked.
If not, the buffer (or its restriction) is checked.

Returns a list of three elements:

 (LINE LINE-LENGTH OTHER-LINES LINES-CHECKED)

LINE is the first of the longest lines measured.
LINE-LENGTH is the length of LINE.
OTHER-LINES is a list of other lines checked that are as long as LINE.
LINES-CHECKED is the number of lines measured.

Interactively, a message displays this information.

If there is only one line in the active region, then the region is
deactivated after this command, and the message mentions only LINE and
LINE-LENGTH.  

If this command is repeated, it checks for the longest line after the
cursor.  That is *not* necessarily the longest line other than the
current line.  That longest line could be before or after the current
line.

To search only from the current line forward, not throughout the
buffer, you can use `C-SPC' to set the mark, then use this
\(repeatedly)."
  (interactive
   (if (or (not mark-active) (null (mark)))
       (list (point-min) (point-max))
     (if (< (point) (mark))
         (list (point) (mark))
       (list (mark) (point)))))
  (when (and (not mark-active) (= beg end))
    (error "The buffer is empty"))
  (when (and mark-active (> (point) (mark))) (exchange-point-and-mark))
  (when (< end beg) (setq end (prog1 beg (setq beg end))))
  (when (eq this-command last-command)
    (forward-line 1) (setq beg (point)))
  (goto-char beg)
  (when (eobp) (error "End of buffer"))
  (cond ((<= end (save-excursion
                   (goto-char beg) (forward-line 1) (point)))
         (beginning-of-line)
         (when (require 'hl-line nil t)
           (let ((hl-line-mode t)) (hl-line-highlight))
           (add-hook 'pre-command-hook #'hl-line-unhighlight nil t))
         (let ((lineno (line-number-at-pos))
               (chars (save-excursion (end-of-line) (current-column))))
           (message "Only line %d: %d chars" lineno chars)
           (let ((visible-bell t)) (ding))
           (setq mark-active nil)
           (list lineno chars nil 1)))
        (t
         (let* ((start-line (line-number-at-pos))
                (max-width 0)
                (line start-line)
                long-lines col)
           (when (eobp) (error "End of buffer"))
           (while (and (not (eobp)) (< (point) end))
             (end-of-line)
             (setq col (current-column))
             (when (>= col max-width)
               (if (= col max-width)
                   (setq long-lines (cons line long-lines))
                 (setq long-lines (list line)))
               (setq max-width col))
             (forward-line 1)
             (setq line (1+ line)))
           (setq long-lines (nreverse long-lines))
           (let ((lines long-lines))
             (while (and lines (> start-line (car lines))) (pop lines))
             (goto-char (point-min))
             (when (car lines) (forward-line (1- (car lines)))))
           (when (require 'hl-line nil t)
             (let ((hl-line-mode t)) (hl-line-highlight))
             (add-hook 'pre-command-hook #'hl-line-unhighlight nil t))
           (when (interactive-p)
             (let ((others (cdr long-lines)))
               (message
                "Line %d: %d chars%s (%d lines measured)"
                (car long-lines) max-width
                (concat
                 (and others
                      (format ", Others: {%s}"
                              (mapconcat
                               (lambda (line) (format "%d" line))
                               (cdr long-lines) ", "))))
                (- line start-line))))
           (list (car long-lines) max-width (cdr long-lines)
                 (- line start-line))))))







^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: bug#2887: Suggestions for simple.el
  2009-04-07 14:02             ` Stefan Monnier
@ 2009-04-07 16:09               ` Drew Adams
  2009-04-07 17:18                 ` Stefan Monnier
                                   ` (3 more replies)
  2009-04-07 16:09               ` Drew Adams
  2009-04-18  0:08               ` Arni Magnusson
  2 siblings, 4 replies; 27+ messages in thread
From: Drew Adams @ 2009-04-07 16:09 UTC (permalink / raw)
  To: 'Stefan Monnier', 2887, 'Arni Magnusson'; +Cc: emacs-devel

> >   C-x j    backward-delete-word
> >   C-x C-j  delete-word
> >   C-x x    kill-line-or-region
> >   M-n      pull-line-down
> >   M-p      pull-line-up
> >   C-M-z    zap-back-to-char
> >   C-M-m    zap-up-to-char
> >   C-x C-a  delete-all-blank-lines
> >   M-&      delete-indentation-nospace
> >   C-x w    goto-longest-line
> >   C-x y    downcase-word-or-region
> >   C-x C-y  upcase-word-or-region
> 
> I think I will prefer to leave those unbound for now, waiting for more
> generally useful commands, or more general agreement that they are
> generally useful.

So it sounds as if you're actually going to add these things to Emacs (even if
you don't bind them by default)?

If so, that's quite surprising, especially since the policy has always been
_not_ to add functions simply because they _might_ be generally useful. Not to
mention the tradition of case-by-case discussion in emacs-devel first, including
discussion of rationale (e.g. use cases).

Whatever. In that case, below is my version of `goto-longest-line', published
under that name over two years ago.

I also sent it to emacs-devel on two occasions: 2008-1-23 (thread "find longest
lines during isearch") and 2008-06-21 (thread "Another neat Eclispe'ism").
http://lists.gnu.org/archive/html/emacs-devel/2008-01/msg01611.html
http://lists.gnu.org/archive/html/emacs-devel/2008-06/msg01442.html

My version has these advantages:

* If the region is active, it is restricted to the region.

* If repeated, it goes to the longest line after the cursor.

* You can use it to search from point forward only, by using `C-SPC' first.

* It highlights the line (using `hl-line-highlight').

* It returns, as a list: the line #, its length, a list of other lines just as
long (there can be more than one "longest line"), and the number of lines
checked.

* Interactively, it echoes all of that info. Example messages:
  Line 234: 76 chars, (459 lines measured)
  Line 234: 76 chars, Others: {239, 313} (459 lines measured)

I bind [(control end)] to this command in `isearch-mode-map' (when
`window-system'). This is the way I typically call it: `C-s C-end'. Repeatedly
move to longest line after point: `C-x C-end C-end...'. And `C-g' returns you to
the point where searching starts, so you can use it to see where long lines are
without necessarily moving there and staying. I also bind it to `C-x L', but I
typically use it from Isearch.

A related command is `goto-long-line', which goes to the first line that is at
least N chars long. N is the `fill-column' by default, or provided explicitly by
`C-u'.

If you are really interested in adding general, miscellaneous commands and
functions that might be useful ("waiting for more generally useful commands"), I
have plenty more, and there are hundreds more by others, on Emacs Wiki and
elsewhere. 

The `goto-long*-line' commands and others are here:
http://www.emacswiki.org/emacs/misc-cmds.el. And there is a wiki page loaded
with commands for finding, visualizing, and moving to long lines:
http://www.emacswiki.org/emacs/FindLongLines.

I really didn't think this was how Emacs development proceeded, but apparently
there has been a change (?).

FWIW, I think emacs-devel is the proper place to discuss additions and other
changes to Emacs. It's OK for enhancement suggestions to be submitted to the
bugs list, but concrete discussion about adding or changing Emacs code should be
done in emacs-devel, IMO. And such discussion should precede actually making
changes.

;---------------8<-----------------------
(defun goto-longest-line (beg end)
  "Go to the first of the longest lines in the region or buffer.
If the region is active, it is checked.
If not, the buffer (or its restriction) is checked.

Returns a list of three elements:

 (LINE LINE-LENGTH OTHER-LINES LINES-CHECKED)

LINE is the first of the longest lines measured.
LINE-LENGTH is the length of LINE.
OTHER-LINES is a list of other lines checked that are as long as LINE.
LINES-CHECKED is the number of lines measured.

Interactively, a message displays this information.

If there is only one line in the active region, then the region is
deactivated after this command, and the message mentions only LINE and
LINE-LENGTH.  

If this command is repeated, it checks for the longest line after the
cursor.  That is *not* necessarily the longest line other than the
current line.  That longest line could be before or after the current
line.

To search only from the current line forward, not throughout the
buffer, you can use `C-SPC' to set the mark, then use this
\(repeatedly)."
  (interactive
   (if (or (not mark-active) (null (mark)))
       (list (point-min) (point-max))
     (if (< (point) (mark))
         (list (point) (mark))
       (list (mark) (point)))))
  (when (and (not mark-active) (= beg end))
    (error "The buffer is empty"))
  (when (and mark-active (> (point) (mark))) (exchange-point-and-mark))
  (when (< end beg) (setq end (prog1 beg (setq beg end))))
  (when (eq this-command last-command)
    (forward-line 1) (setq beg (point)))
  (goto-char beg)
  (when (eobp) (error "End of buffer"))
  (cond ((<= end (save-excursion
                   (goto-char beg) (forward-line 1) (point)))
         (beginning-of-line)
         (when (require 'hl-line nil t)
           (let ((hl-line-mode t)) (hl-line-highlight))
           (add-hook 'pre-command-hook #'hl-line-unhighlight nil t))
         (let ((lineno (line-number-at-pos))
               (chars (save-excursion (end-of-line) (current-column))))
           (message "Only line %d: %d chars" lineno chars)
           (let ((visible-bell t)) (ding))
           (setq mark-active nil)
           (list lineno chars nil 1)))
        (t
         (let* ((start-line (line-number-at-pos))
                (max-width 0)
                (line start-line)
                long-lines col)
           (when (eobp) (error "End of buffer"))
           (while (and (not (eobp)) (< (point) end))
             (end-of-line)
             (setq col (current-column))
             (when (>= col max-width)
               (if (= col max-width)
                   (setq long-lines (cons line long-lines))
                 (setq long-lines (list line)))
               (setq max-width col))
             (forward-line 1)
             (setq line (1+ line)))
           (setq long-lines (nreverse long-lines))
           (let ((lines long-lines))
             (while (and lines (> start-line (car lines))) (pop lines))
             (goto-char (point-min))
             (when (car lines) (forward-line (1- (car lines)))))
           (when (require 'hl-line nil t)
             (let ((hl-line-mode t)) (hl-line-highlight))
             (add-hook 'pre-command-hook #'hl-line-unhighlight nil t))
           (when (interactive-p)
             (let ((others (cdr long-lines)))
               (message
                "Line %d: %d chars%s (%d lines measured)"
                (car long-lines) max-width
                (concat
                 (and others
                      (format ", Others: {%s}"
                              (mapconcat
                               (lambda (line) (format "%d" line))
                               (cdr long-lines) ", "))))
                (- line start-line))))
           (list (car long-lines) max-width (cdr long-lines)
                 (- line start-line))))))





^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 16:09               ` Drew Adams
@ 2009-04-07 17:18                 ` Stefan Monnier
  2009-04-07 17:18                 ` Stefan Monnier
                                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-07 17:18 UTC (permalink / raw)
  To: Drew Adams; +Cc: 2887, emacs-devel, 'Arni Magnusson'

> So it sounds as if you're actually going to add these things to Emacs
> (even if you don't bind them by default)?

No.


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: bug#2887: Suggestions for simple.el
  2009-04-07 16:09               ` Drew Adams
  2009-04-07 17:18                 ` Stefan Monnier
@ 2009-04-07 17:18                 ` Stefan Monnier
  2009-04-07 17:22                 ` Chong Yidong
  2009-04-07 17:22                 ` Chong Yidong
  3 siblings, 0 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-07 17:18 UTC (permalink / raw)
  To: Drew Adams; +Cc: 2887, emacs-devel, 'Arni Magnusson'

> So it sounds as if you're actually going to add these things to Emacs
> (even if you don't bind them by default)?

No.


        Stefan




^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 16:09               ` Drew Adams
                                   ` (2 preceding siblings ...)
  2009-04-07 17:22                 ` Chong Yidong
@ 2009-04-07 17:22                 ` Chong Yidong
  3 siblings, 0 replies; 27+ messages in thread
From: Chong Yidong @ 2009-04-07 17:22 UTC (permalink / raw)
  To: Drew Adams; +Cc: 2887, emacs-devel, 'Arni Magnusson'

"Drew Adams" <drew.adams@oracle.com> writes:

>> I think I will prefer to leave those unbound for now, waiting for more
>> generally useful commands, or more general agreement that they are
>> generally useful.
>
> So it sounds as if you're actually going to add these things to Emacs
> (even if you don't bind them by default)?
>
> If so, that's quite surprising, especially since the policy has always
> been _not_ to add functions simply because they _might_ be generally
> useful.

I don't think that's what Stefan was saying (but he can speak for
himself).  You're right, of course, that it's not a good idea to add
functions simply because they *might* be useful, especially since
simple.el is loaded by default.

I have not looked through bug#2887 in detail, but my impression is that
most of the suggested functions aren't quite suitable for default
inclusion in Emacs.  They are, however, Valuable Excercises For the
Novice Emacs Lisp coder.  Maybe someone should set up a page on
Emacswiki for this sort of thing.






^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: bug#2887: Suggestions for simple.el
  2009-04-07 16:09               ` Drew Adams
  2009-04-07 17:18                 ` Stefan Monnier
  2009-04-07 17:18                 ` Stefan Monnier
@ 2009-04-07 17:22                 ` Chong Yidong
  2009-04-07 17:26                   ` Drew Adams
                                     ` (2 more replies)
  2009-04-07 17:22                 ` Chong Yidong
  3 siblings, 3 replies; 27+ messages in thread
From: Chong Yidong @ 2009-04-07 17:22 UTC (permalink / raw)
  To: Drew Adams
  Cc: 2887, emacs-devel, 'Stefan Monnier',
	'Arni Magnusson'

"Drew Adams" <drew.adams@oracle.com> writes:

>> I think I will prefer to leave those unbound for now, waiting for more
>> generally useful commands, or more general agreement that they are
>> generally useful.
>
> So it sounds as if you're actually going to add these things to Emacs
> (even if you don't bind them by default)?
>
> If so, that's quite surprising, especially since the policy has always
> been _not_ to add functions simply because they _might_ be generally
> useful.

I don't think that's what Stefan was saying (but he can speak for
himself).  You're right, of course, that it's not a good idea to add
functions simply because they *might* be useful, especially since
simple.el is loaded by default.

I have not looked through bug#2887 in detail, but my impression is that
most of the suggested functions aren't quite suitable for default
inclusion in Emacs.  They are, however, Valuable Excercises For the
Novice Emacs Lisp coder.  Maybe someone should set up a page on
Emacswiki for this sort of thing.




^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 17:22                 ` Chong Yidong
@ 2009-04-07 17:26                   ` Drew Adams
  2009-04-07 17:26                   ` Drew Adams
  2009-04-07 21:43                   ` Stefan Monnier
  2 siblings, 0 replies; 27+ messages in thread
From: Drew Adams @ 2009-04-07 17:26 UTC (permalink / raw)
  To: 'Chong Yidong'; +Cc: 2887, emacs-devel, 'Arni Magnusson'

> most of the suggested functions aren't quite suitable for default
> inclusion in Emacs.  They are, however, Valuable Excercises For the
> Novice Emacs Lisp coder.  Maybe someone should set up a page on
> Emacswiki for this sort of thing.

Feel free to act on your own suggestion - anyone can edit EmacsWiki. 







^ permalink raw reply	[flat|nested] 27+ messages in thread

* RE: bug#2887: Suggestions for simple.el
  2009-04-07 17:22                 ` Chong Yidong
  2009-04-07 17:26                   ` Drew Adams
@ 2009-04-07 17:26                   ` Drew Adams
  2009-04-07 21:43                   ` Stefan Monnier
  2 siblings, 0 replies; 27+ messages in thread
From: Drew Adams @ 2009-04-07 17:26 UTC (permalink / raw)
  To: 'Chong Yidong'
  Cc: 2887, emacs-devel, 'Stefan Monnier',
	'Arni Magnusson'

> most of the suggested functions aren't quite suitable for default
> inclusion in Emacs.  They are, however, Valuable Excercises For the
> Novice Emacs Lisp coder.  Maybe someone should set up a page on
> Emacswiki for this sort of thing.

Feel free to act on your own suggestion - anyone can edit EmacsWiki. 





^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 17:22                 ` Chong Yidong
  2009-04-07 17:26                   ` Drew Adams
  2009-04-07 17:26                   ` Drew Adams
@ 2009-04-07 21:43                   ` Stefan Monnier
  2 siblings, 0 replies; 27+ messages in thread
From: Stefan Monnier @ 2009-04-07 21:43 UTC (permalink / raw)
  To: Chong Yidong; +Cc: 2887

Actually, I do think that a "find longest line" command would be a good
addition to misc.el: it's not terribly hard to write, but it's not
trivial either.


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-07 14:02             ` Stefan Monnier
  2009-04-07 16:09               ` Drew Adams
  2009-04-07 16:09               ` Drew Adams
@ 2009-04-18  0:08               ` Arni Magnusson
  2009-04-18 19:32                 ` Stefan Monnier
  2 siblings, 1 reply; 27+ messages in thread
From: Arni Magnusson @ 2009-04-18  0:08 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

[-- Attachment #1: Type: TEXT/PLAIN, Size: 5540 bytes --]

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

[-- Attachment #2: Type: TEXT/PLAIN, Size: 294 bytes --]

(defun pos-at-beginning-of-line (N) "Return the position at beginning of line N."
  (save-excursion (goto-char (point-min))(line-beginning-position N)))

(defun pos-at-end-of-line (N) "Return the position at end of line N."
  (save-excursion (goto-char (point-min))(line-end-position N)))

[-- Attachment #3: Type: TEXT/PLAIN, Size: 2368 bytes --]

(defun backward-delete-word (N) "Delete previous N words." (interactive "*p")(delete-word (- N)))
(defun delete-word (N) "Delete following N words." (interactive "*p")
  (delete-region (point)(save-excursion (forward-word N)(point))))

(defun kill-line-or-region () "Kill region if selected, otherwise kill line." (interactive)
  (if (and mark-active transient-mark-mode)(kill-region (point)(mark))(kill-line)))

(defun pull-line-down (N) "Pull line down N times." (interactive "*p")
  (let ((col (current-column)))(kill-whole-line 1)(forward-line N)(yank 1)(pop kill-ring)(forward-line -1)
       (move-to-column col)))
(defun pull-line-up (N) "Pull line up N times." (interactive "*p")
  (let ((col (current-column)))(kill-whole-line 1)(forward-line (- N))(yank 1)(pop kill-ring)(forward-line -1)
       (move-to-column col)))

(defun zap-back-to-char (char) "Delete region back to, but not including, CHAR." (interactive "cZap back to char: ")
  (let ((case-fold-search nil))
    (delete-region (point)(progn (search-backward (char-to-string char))(forward-char)(point)))))
(defun zap-up-to-char (char) "Delete region up to, but not including, CHAR." (interactive "cZap to char: ")
  (let ((case-fold-search nil))
    (delete-region (point)(progn (search-forward (char-to-string char))(backward-char)(point)))))

(defun delete-all-blank-lines () "Delete all blank lines in buffer." (interactive)
  (save-excursion
    (goto-char (point-min))
    (let ((count 0))(while (search-forward "\n\n" nil t)(goto-char (point-min))
                           (while (search-forward "\n\n" nil t)(replace-match "\n")(setq count (+ count 1)))
                           (goto-char (point-min)))
         (if (= (following-char) 10)(progn (delete-char 1)(setq count (+ count 1))))
         (message "Deleted %d blank lines" count))))

(defun delete-indentation-nospace () "Join this line to previous with no whitespace at join." (interactive)
  (delete-indentation)(delete-horizontal-space))

(defun downcase-word-or-region (N) "Downcase N words or region." (interactive "*p")
  (if (and mark-active transient-mark-mode)(downcase-region (point)(mark))(downcase-word N)))
(defun upcase-word-or-region (N) "Upcase N words or region." (interactive "*p")
  (if (and mark-active transient-mark-mode)(upcase-region (point)(mark))(upcase-word N)))

[-- Attachment #4: Type: TEXT/PLAIN, Size: 535 bytes --]

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

[-- Attachment #5: Type: TEXT/PLAIN, Size: 586 bytes --]

(defun delete-trailing-whitespace ()
  "Delete all the trailing whitespace across the current buffer.
All whitespace after the last non-whitespace character in a line is deleted.
This respects narrowing, created by \\[narrow-to-region] and friends.
A formfeed is not considered whitespace by this function."
  (interactive "*")
  (save-match-data
    (save-excursion
      (goto-char (point-min))
      (let ((count 0))
        (while (re-search-forward "[ \t\r]+$" nil t)
          (replace-match "")(setq count (1+ count)))
        (message "Cleaned %d lines" count)))))

[-- Attachment #6: Type: TEXT/PLAIN, Size: 721 bytes --]

(defun delete-trailing-whitespace ()
  "Delete all the trailing whitespace across the current buffer.
All whitespace after the last non-whitespace character in a line is deleted.
This respects narrowing, created by \\[narrow-to-region] and friends.
A formfeed is not considered whitespace by this function."
  (interactive "*")
  (save-match-data
    (save-excursion
      (goto-char (point-min))
      (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))))))

^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-18  0:08               ` Arni Magnusson
@ 2009-04-18 19:32                 ` Stefan Monnier
  2009-04-19  1:13                   ` Arni Magnusson
  0 siblings, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2009-04-18 19:32 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

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

I think the difference between these and the standard commands is too
small to deserve a separate command.  There are plenty of ways to get
around the problem of "kill when I only want delete" (typically, doing
the kill after the C-y, or using M-y, ...).

I would only consider some general "kill-next-kill" feature which would
allow to turn any killing command into a deleting one
(e.g. a kill-next-kill command which would cause the subsequent
commands's effect on the kill-ring to be cancelled).

> `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'?

Yes, we couldn't really get rid of C-w, I think, but users of
transient-mark-mode could use that key for other things.

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

I don't find transpose-lines very useful, so I might accept a proposal
that makes it more useful, but not one that adds yet more refinements.

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

The reimplementation doesn't change anything: its performance will still
suck on large files.  It's just fundamentally an operation that is slow
and that we should generally avoid, so I don't want to add yet more ways
(additionally to goto-line) to do that.

The "obvious gap" that you talk about is only "obvious" if you think in
terms of lines, which is almost always the wrong way to think about the
text in Emacs.

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

Maybe a better approach would be to add config var to zap-to-char
whether it also zaps the char or not.  In any case, I'd rather wait for
other people to support this option, since I have no idea how common
it is.

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

Thanks.  We'll consider using it for Emacs-23.2.

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

Can someone figure out a way to tweak flush-lines such that it can be
used for that purpose without having to jump through as many hooks?
Maybe we can just say that if you call flush-lines with an empty
argument (which currently would flush *all* lines) it will flush all
empty lines.

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

Here again, I'm not sure the difference is worth the trouble.
I'd rather make fixup-whitespace customizable so you can specify when to
keep a space and when not to.  You can then customize it to never keep
a space, and then use M-^ for delete-indentation-nospace and M-^ SPC
when you do want a space.

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

Yes, I think it would be a good change.

> 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'?

It's possible, but it's less sure than with C-w because those commands
are used much less frequently, so it might be OK to just tell people to
use C-u C-x C-x M-u instead of C-x C-u.


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-18 19:32                 ` Stefan Monnier
@ 2009-04-19  1:13                   ` Arni Magnusson
  2009-04-19  1:40                     ` Arni Magnusson
  2009-04-19  3:14                     ` Stefan Monnier
  0 siblings, 2 replies; 27+ messages in thread
From: Arni Magnusson @ 2009-04-19  1:13 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

>> `backward-delete-word'
>> `delete-word'
>
> I would only consider some general "kill-next-kill" feature which would 
> allow to turn any killing command into a deleting one (e.g. a 
> kill-next-kill command which would cause the subsequent commands's 
> effect on the kill-ring to be cancelled).

This would mean two keystrokes to delete a word, right? First 
`kill-next-kill' and then `kill-word'. It's an idea, but I still believe 
that many users would appreciate binding single keystrokes to the 
functions I suggested. They would most likely bind them to C-backspace and 
C-delete.



>> `pos-at-beginning-of-line'
>> `pos-at-end-of-line'
>
> The reimplementation doesn't change anything: its performance will still 
> suck on large files.  It's just fundamentally an operation that is slow 
> and that we should generally avoid, so I don't want to add yet more ways 
> (additionally to goto-line) to do that.

I don't understand, I think these functions are blazing fast. In practice, 
I would probably not use Emacs to perform 100,000 iterations on a 200 MB 
file - but that's why I'm surprised to see that it takes less than a 
second:

   100000 M-x benchmark (pos-at-end-of-line 10)  ; 0.421s

I'm using a small arg of 10, because that's the case where you predicted 
that `line-end-position' would be much faster.

   100000 M-x benchmark (line-end-position 10)  ; 0.220s

This is necessarily faster, since `pos-at-end-of-line' calls 
`line-end-position', but the (save-excursion (goto-char (point-min)) 
overhead is not as great as one might expect.

With few iterations and large arg, the speed is also comparable:

   10 M-x benchmark (pos-at-end-of-line 100000)  ; 0.156s
   10 M-x benchmark (line-end-position 100000)   ; 0.156s

Most things become more sluggish with a 200 MB file. Overall, I think 
these functions make it considerably easier to read and write functions 
that operate on buffer text - with minimal performance cost. In practice, 
I use it without iteration, and with a 1 MB source code file it doesn't 
register in a benchmark (0.000000s).

I hesitate to introduce another function to the discussion, but here's an 
example where I use `pos-at-beginning-of-line' and `pos-at-end-of-line'. 
Since you're the maintainer of newcomment.el, it might pique your 
interest:

(defun comment-line-or-region ()
   "Comment line or region."
   (interactive)
   (require 'newcomment)
   (if (and mark-active transient-mark-mode)
       (comment-region
        (pos-at-beginning-of-line (line-number-at-pos (region-beginning)))
        (pos-at-end-of-line (line-number-at-pos (region-end))))
     (comment-region (line-beginning-position)(line-end-position))))

Same idea as `kill-line-or-region'. Without the `pos-at-beginning-of-line' 
and `pos-at-end-of-line',

       (comment-region
        (region-beginning)
        (region-end))

it would misbehave when the region consists of a partially selected first 
and/or last line. Someone like you might be able to improve this function, 
but it's served me well and has no discernible speed lag.



>> `delete-all-blank-lines'
>
> Can someone figure out a way to tweak flush-lines such that it can be 
> used for that purpose without having to jump through as many hooks? 
> Maybe we can just say that if you call flush-lines with an empty 
> argument (which currently would flush *all* lines) it will flush all 
> empty lines.

This is definitely an idea, making better use of the default value of the 
regexp. But do you really mean flush all empty lines, or just the empty 
lines below the point? The idea behind `delete-all-blank-lines' is to 
really delete all empty lines, without moving the point, in one keystroke. 
I could probably edit `flush-lines' to do exactly that, although it 
operates only on text after the point for non-default regexps.



Phew, it looks like the rest of our discussion threads have closed 
successfully, meaning that we have fully understood each others' ideas, 
and the decisions will depend on your good judgement and the Emacs elders.


Cheers,

Arni






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-19  1:13                   ` Arni Magnusson
@ 2009-04-19  1:40                     ` Arni Magnusson
  2009-04-19  3:14                     ` Stefan Monnier
  1 sibling, 0 replies; 27+ messages in thread
From: Arni Magnusson @ 2009-04-19  1:40 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887

> [...] understood each others' ideas [...]

Whoa, that should have been each other's ideas. Lisp programmers need to 
be extra careful with their apostrophes :)

Arni






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-19  1:13                   ` Arni Magnusson
  2009-04-19  1:40                     ` Arni Magnusson
@ 2009-04-19  3:14                     ` Stefan Monnier
  2009-04-19 13:41                       ` Arni Magnusson
  1 sibling, 1 reply; 27+ messages in thread
From: Stefan Monnier @ 2009-04-19  3:14 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

>> I would only consider some general "kill-next-kill" feature which would
>> allow to turn any killing command into a deleting one
>> (e.g. a kill-next-kill command which would cause the subsequent commands's
>> effect on the kill-ring to be cancelled).
> This would mean two keystrokes to delete a word, right?

Yes, at least.  Maybe you can amortize it so it's only N+1 for N words.

> It's an idea, but I still believe that many users would appreciate
> binding single keystrokes to the functions I suggested.

Yes, that's where we disagree.

> (defun comment-line-or-region ()
>   "Comment line or region."
>   (interactive)
>   (require 'newcomment)
>   (if (and mark-active transient-mark-mode)
>       (comment-region
>        (pos-at-beginning-of-line (line-number-at-pos (region-beginning)))
>        (pos-at-end-of-line (line-number-at-pos (region-end))))
>     (comment-region (line-beginning-position)(line-end-position))))

A perfect example of the kind of performance bug that comes up when you
think in terms of lines, as encouraged by pos-at-beginning/end-of-line.
The above should be:

 (defun comment-line-or-region ()
   "Comment line or region."
   (interactive)
   (require 'newcomment)
   (if (and mark-active transient-mark-mode)
       (comment-region
        (save-excursion (goto-char (region-beginning)) (line-beginning-position))
        (save-excursion (goto-char (region-end)) (line-end-position)))
     (comment-region (line-beginning-position) (line-end-position))))

line-number-at-pos is also a "function to avoid", just as bad as
goto-line.  Your code will walk over the whole buffer 4 times (twice to
compute the line-number at region beg and end, then twice to find the
beg/end of those 2 lines).

>>> `delete-all-blank-lines'
>> 
>> Can someone figure out a way to tweak flush-lines such that it can be used
>> for that purpose without having to jump through as many hooks? Maybe we
>> can just say that if you call flush-lines with an empty argument (which
>> currently would flush *all* lines) it will flush all empty lines.

> This is definitely an idea, making better use of the default value of the
> regexp. But do you really mean flush all empty lines, or just the empty
> lines below the point? The idea behind `delete-all-blank-lines' is to really
> delete all empty lines, without moving the point, in one keystroke. I could
> probably edit `flush-lines' to do exactly that, although it operates only on
> text after the point for non-default regexps.

I don't think the position-preservation is important enough to warrant
a different command.  So do C-SPC M-< before and C-u C-SPC afterwards if
you want to preserve point.  Or try to provide some way for flush-lines
to operate on the whole buffer, without having to move point.


        Stefan






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-19  3:14                     ` Stefan Monnier
@ 2009-04-19 13:41                       ` Arni Magnusson
  0 siblings, 0 replies; 27+ messages in thread
From: Arni Magnusson @ 2009-04-19 13:41 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 2887, bug-lisp-manual

[Arni Magnusson wrote:]

>> (defun pos-at-beginning-of-line (N)
>>   "Return the position at beginning of line N."
>>   (save-excursion
>>     (goto-char (point-min))(line-beginning-position N)))
>>
>> (defun pos-at-end-of-line (N)
>>   "Return the position at end of line N."
>>   (save-excursion
>>     (goto-char (point-min))(line-end-position N)))
>>
>> (defun comment-line-or-region ()
>>   "Comment line or region."
>>   (interactive)
>>   (require 'newcomment)
>>   (if (and mark-active transient-mark-mode)
>>       (comment-region
>>        (pos-at-beginning-of-line
>>         (line-number-at-pos (region-beginning)))
>>        (pos-at-end-of-line
>>         (line-number-at-pos (region-end))))
>>     (comment-region
>>      (line-beginning-position)(line-end-position))))

[Stefan Monnier wrote:]

> A perfect example of the kind of performance bug that comes up when you 
> think in terms of lines, as encouraged by pos-at-beginning/end-of-line. 
> The above should be:
>
> (defun comment-line-or-region ()
>   "Comment line or region."
>   (interactive)
>   (require 'newcomment)
>   (if (and mark-active transient-mark-mode)
>       (comment-region
>        (save-excursion
>          (goto-char (region-beginning))(line-beginning-position))
>        (save-excursion
>          (goto-char (region-end))(line-end-position)))
>     (comment-region
>      (line-beginning-position)(line-end-position))))
>
> line-number-at-pos is also a "function to avoid", just as bad as 
> goto-line.  Your code will walk over the whole buffer 4 times (twice to 
> compute the line-number at region beg and end, then twice to find the 
> beg/end of those 2 lines).

---

Aha, now I see what you mean. One should use relative motion in Emacs Lisp 
programs and avoid referring to absolute line numbers (`goto-line', 
`line-beginning-position', `line-end-position', `line-number-at-pos').

Thank you Stefan, for explaining this to me - now I would like to help 
others to avoid using these functions in Emacs Lisp programs, when 
possible. Couldn't this be mentioned in the docstrings and in the Emacs 
Lisp Manual? They had already helped me by tagging a warning sign on 
functions like:

   `next-line', `previous-line'
   `beginning-of-buffer', `end-of-buffer'
   `replace-string', `replace-regexp'
   `insert-file', `insert-buffer'

In my notes, I have also written that (goto-char (point-min)) is better 
than (goto-line 1), but now I can't see where this is documented.

Besides the docstrings and the function entries in the manual, there is a 
section in the manual called "Emacs Programming Tips" where the pitfalls 
of *-line-* functions could be mentioned.

Thanks,

Arni






^ permalink raw reply	[flat|nested] 27+ messages in thread

* bug#2887: Suggestions for simple.el
  2009-04-04 13:32 bug#2887: Suggestions for simple.el Arni Magnusson
  2009-04-04 14:21 ` Stefan Monnier
@ 2020-09-19 21:50 ` Lars Ingebrigtsen
  1 sibling, 0 replies; 27+ messages in thread
From: Lars Ingebrigtsen @ 2020-09-19 21:50 UTC (permalink / raw)
  To: Arni Magnusson; +Cc: 2887

"Arni Magnusson" <arnima@hafro.is> writes:

> I would like to suggest adding a few functions to the simple.el library. I
> do this with hesitation - since I know the idea is to keep it simple and
> let users write extensions to suit their preferences - but I believe a
> large number of Emacs users would appreciate having access to these
> functions out of the box.

There was a lot of discussion that followed after posting the patch, but
it didn't seem like there was a lot of enthusiasm for adding these basic
functions to Emacs eleven years ago, so it seems unlikely that there'll
be more progress here now, and I'm closing this bug report.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2020-09-19 21:50 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-04 13:32 bug#2887: Suggestions for simple.el Arni Magnusson
2009-04-04 14:21 ` Stefan Monnier
2009-04-04 23:35   ` Arni Magnusson
2009-04-05  3:27     ` Stefan Monnier
2009-04-05 14:26       ` Leo
2009-04-05 20:17       ` Arni Magnusson
2009-04-05 21:59         ` Lennart Borgman
2009-04-06  2:14         ` Stefan Monnier
2009-04-06  3:02           ` Drew Adams
2009-04-07  2:46           ` Arni Magnusson
2009-04-07 14:02             ` Stefan Monnier
2009-04-07 16:09               ` Drew Adams
2009-04-07 17:18                 ` Stefan Monnier
2009-04-07 17:18                 ` Stefan Monnier
2009-04-07 17:22                 ` Chong Yidong
2009-04-07 17:26                   ` Drew Adams
2009-04-07 17:26                   ` Drew Adams
2009-04-07 21:43                   ` Stefan Monnier
2009-04-07 17:22                 ` Chong Yidong
2009-04-07 16:09               ` Drew Adams
2009-04-18  0:08               ` Arni Magnusson
2009-04-18 19:32                 ` Stefan Monnier
2009-04-19  1:13                   ` Arni Magnusson
2009-04-19  1:40                     ` Arni Magnusson
2009-04-19  3:14                     ` Stefan Monnier
2009-04-19 13:41                       ` Arni Magnusson
2020-09-19 21:50 ` Lars Ingebrigtsen

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.