* [PATCH] Add smart-space command.
@ 2012-12-04 22:36 Michal Nazarewicz
2012-12-04 22:55 ` Drew Adams
2012-12-10 14:57 ` [PATCHv2] Add cycle-spacing command Michal Nazarewicz
0 siblings, 2 replies; 8+ messages in thread
From: Michal Nazarewicz @ 2012-12-04 22:36 UTC (permalink / raw)
To: emacs-devel
Hello everyone,
The patch below adds a smart-space command which is sort of
a generalised just-one-space. The main difference is that it behaves
differently depending on how many times it has been called, and cycles
between three states:
1. just one space
2. no space at all
3. original spacing
I've been using various versions of this command for years now, and
every now and then, someone asks about something like that, so I thought
I'd contribute.
----------------- >8 ---------------------------------------------------
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: mina86@mina86.com-20121204215056-c7379szmw0d8dj1m
# target_branch: bzr://bzr.savannah.gnu.org/emacs/trunk
# testament_sha1: 70c3c769cbc683fc01816ddbe5cec6e7d5e9fcf8
# timestamp: 2012-12-04 23:09:38 +0100
# source_branch: .
# base_revision_id: eggert@cs.ucla.edu-20121204204229-wbbjjgyv88jj2icz
#
# Begin patch
=== modified file 'etc/NEWS'
--- etc/NEWS 2012-12-04 17:07:09 +0000
+++ etc/NEWS 2012-12-04 21:50:56 +0000
@@ -74,6 +74,11 @@
it works like the utility `uniq'. Otherwise by default it deletes
duplicate lines everywhere in the region without regard to adjacency.
+** New `smart-space' command allows cycling between having just one space,
+no spaces, or reverting to the original spacing. Like `just-one-space'
+command it can handle or ignore newlines and use leave different number
+of spaces.
+
** Tramp
+++
*** New connection method "adb", which allows to access Android
=== modified file 'lisp/ChangeLog'
--- lisp/ChangeLog 2012-12-04 17:04:01 +0000
+++ lisp/ChangeLog 2012-12-04 21:50:56 +0000
@@ -1,3 +1,7 @@
+2012-12-04 Michal Nazarewicz <mina86@mina86.com>
+
+ * simple.el: Add smart-space command.
+
2012-12-04 Stefan Monnier <monnier@iro.umontreal.ca>
* obsolete/terminal.el, obsolete/longlines.el: Add obsolecence info.
=== modified file 'lisp/simple.el'
--- lisp/simple.el 2012-12-03 01:08:31 +0000
+++ lisp/simple.el 2012-12-04 21:50:56 +0000
@@ -742,25 +742,80 @@
(skip-chars-backward " \t")
(constrain-to-field nil orig-pos)))))
+(defvar smart-space--context nil
+ "Store context used in consecutive calls to `smart-space' command.
+The first time this function is run, it saves the original point
+position and original spacing around the point in this variable.")
+
+(defun smart-space (&optional n preserve-nl-back single-shot)
+ "Manipulate spaces around the point in a smart way.
+
+When run as an interactive command, the first time it's called
+in a sequence, deletes all spaces and tabs around point leaving
+one (or N spaces). If this does not change content of the
+buffer, skips to the second step:
+
+When run for the second time in a sequence, deletes all the
+spaces it has previously inserted.
+
+When run for the third time, returns the whitespace and point in
+a state encountered when it had been run for the first time.
+
+For example, if buffer contains \"foo ^ bar\" with \"^\" donating the
+point, calling `smart-space' command will replace two spaces with
+a single space, calling it again immediately after, will remove all
+spaces, and calling it for the third time will bring two spaces back
+together.
+
+If N is negative, delete newlines as well. However, if
+PRESERVE-NL-BACK is t new line characters prior to the point
+won't be removed.
+
+If SINGLE-SHOT is non-nil, will only perform the first step. In
+other words, it will work just like `just-on-space' command."
+ (interactive "*p")
+ (let ((orig-pos (point))
+ (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+ (n (abs (or n 1))))
+ (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
+ (constrain-to-field nil orig-pos)
+ (cond
+ ;; Command run for the first time or single-shot is non-nil
+ ((or single-shot
+ (not (equal last-command this-command))
+ (not smart-space--context))
+ (let* ((start (point))
+ (n (- n (skip-chars-forward " " (+ n (point)))))
+ (mid (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (setq smart-space--context ;; Save for later
+ ;; Special handling for case where there was no space at all
+ (unless (= start end)
+ (cons orig-pos (buffer-substring start (point)))))
+ ;; If this run causes no change in buffer content, delete all spaces,
+ ;; otherwise delete all excees spaces.
+ (delete-region (if (and (not single-shot) (zerop n) (= mid end))
+ start mid) end)
+ (dotimes (_ n)
+ (insert ?\s))))
+
+ ;; Command run for the second time
+ ((not (equal orig-pos (point)))
+ (delete-region (point) orig-pos))
+
+ ;; Command run for the third time
+ (t
+ (insert (cdr smart-space--context))
+ (goto-char (car smart-space--context))
+ (setq smart-space--context nil)))))
+
(defun just-one-space (&optional n)
"Delete all spaces and tabs around point, leaving one space (or N spaces).
If N is negative, delete newlines as well."
(interactive "*p")
- (unless n (setq n 1))
- (let ((orig-pos (point))
- (skip-characters (if (< n 0) " \t\n\r" " \t"))
- (n (abs n)))
- (skip-chars-backward skip-characters)
- (constrain-to-field nil orig-pos)
- (dotimes (i n)
- (if (= (following-char) ?\s)
- (forward-char 1)
- (insert ?\s)))
- (delete-region
- (point)
- (progn
- (skip-chars-forward skip-characters)
- (constrain-to-field nil orig-pos t)))))
+ (smart-space n nil t))
\f
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer.
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH] Add smart-space command.
2012-12-04 22:36 [PATCH] Add smart-space command Michal Nazarewicz
@ 2012-12-04 22:55 ` Drew Adams
2012-12-04 23:11 ` Michal Nazarewicz
2012-12-10 14:57 ` [PATCHv2] Add cycle-spacing command Michal Nazarewicz
1 sibling, 1 reply; 8+ messages in thread
From: Drew Adams @ 2012-12-04 22:55 UTC (permalink / raw)
To: 'Michal Nazarewicz', emacs-devel
> The patch below adds a smart-space command which is sort of
> a generalised just-one-space. The main difference is that it behaves
> differently depending on how many times it has been called, and cycles
> between three states:
>
> 1. just one space
> 2. no space at all
> 3. original spacing
I have nothing special to say about the command, and I haven't tried it or
looked at the code. But from the description I would suggest perhaps renaming
it to suggest more of what it does: `cycle-spacing' or some such.
Personally, I dislike "smart" names - they often say nothing about what the
function does. They tend to suggest only "this command is an improvement over
the command I'm replacing it by".
At best, they sometimes suggest that the command does something different
depending on the context (aka context-sensitive, ~aka DWIM).
In this case, the command does not seem to be deciding its behavior based on the
textual context. From your desription, it is the user who controls the behavior
by explicitly repeating the command. The command is flexible, not smart.
Wrt adding a command that does what you describe: I think it's a good idea. The
cycling might even include using a hard (nobreak) space. Or include
`fixup-whitespace'. Or `delete-horizontal-space'. The cycling choices could
even be customizable.
Just one opinion.
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH] Add smart-space command.
2012-12-04 22:55 ` Drew Adams
@ 2012-12-04 23:11 ` Michal Nazarewicz
0 siblings, 0 replies; 8+ messages in thread
From: Michal Nazarewicz @ 2012-12-04 23:11 UTC (permalink / raw)
To: Drew Adams, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 1580 bytes --]
>> The patch below adds a smart-space command which is sort of
>> a generalised just-one-space. The main difference is that it behaves
>> differently depending on how many times it has been called, and cycles
>> between three states:
>>
>> 1. just one space
>> 2. no space at all
>> 3. original spacing
On Tue, Dec 04 2012, Drew Adams wrote:
> I have nothing special to say about the command, and I haven't tried it or
> looked at the code. But from the description I would suggest perhaps renaming
> it to suggest more of what it does: `cycle-spacing' or some such.
Sure, that sounds fine by me. Truth to be said, I could not came up
with a good name so I escaped into the “smart” realm. ;)
> Wrt adding a command that does what you describe: I think it's a good idea. The
> cycling might even include using a hard (nobreak) space. Or include
> `fixup-whitespace'. Or `delete-horizontal-space'. The cycling choices could
> even be customizable.
The second state is `delete-horizontal-space' (with backward-only being
nil) essentially, but yes, I thought about making something even more
configurable, like accepting a list of states or something, but I didn't
want to make the function too complex, and rather get it to do what
I think would be the most useful thing.
--
Best regards, _ _
.o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michał “mina86” Nazarewicz (o o)
ooo +----<email/xmpp: mpn@google.com>--------------ooO--(_)--Ooo--
[-- Attachment #2.1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2.2: Type: application/pgp-signature, Size: 835 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCHv2] Add cycle-spacing command.
2012-12-04 22:36 [PATCH] Add smart-space command Michal Nazarewicz
2012-12-04 22:55 ` Drew Adams
@ 2012-12-10 14:57 ` Michal Nazarewicz
2013-01-17 11:41 ` [PATCHv3] " Michal Nazarewicz
1 sibling, 1 reply; 8+ messages in thread
From: Michal Nazarewicz @ 2012-12-10 14:57 UTC (permalink / raw)
To: emacs-devel, Drew Adams
From: Michal Nazarewicz <mina86@mina86.com>
This commit adds a cycle-spacing command which is, in a sense,
generalisation of the just-on-space command. When run continuously,
it cycles between having only one space, having no spaces and original
spacing.
---
etc/NEWS | 5 +++
lisp/ChangeLog | 4 ++
lisp/simple.el | 86 ++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 80 insertions(+), 15 deletions(-)
v2: changed name to cycle-spacing
diff --git a/etc/NEWS b/etc/NEWS
index 77e7e47..8112573 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -92,6 +92,11 @@ when its arg ADJACENT is non-nil (when called interactively with C-u C-u)
it works like the utility `uniq'. Otherwise by default it deletes
duplicate lines everywhere in the region without regard to adjacency.
+** New `cycle-spacing' command allows cycling between having just one
+space, no spaces, or reverting to the original spacing. Like
+`just-one-space' command it can handle or ignore newlines and use
+leave different number of spaces.
+
** Tramp
+++
*** New connection method "adb", which allows to access Android
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7f05613..7ac779a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2012-12-10 Michal Nazarewicz <mina86@mina86.com>
+
+ * simple.el: Add cycle-spacing command.
+
2012-12-10 Eli Zaretskii <eliz@gnu.org>
* subr.el (w32notify-handle-event): New function.
diff --git a/lisp/simple.el b/lisp/simple.el
index 78b7657..dcb8cf7 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -742,25 +742,81 @@ If BACKWARD-ONLY is non-nil, only delete them before point."
(skip-chars-backward " \t")
(constrain-to-field nil orig-pos)))))
+(defvar cycle-spacing--context nil
+ "Store context used in consecutive calls to `cycle-spacing' command.
+The first time this function is run, it saves the original point
+position and original spacing around the point in this
+variable.")
+
+(defun cycle-spacing (&optional n preserve-nl-back single-shot)
+ "Manipulate spaces around the point in a smart way.
+
+When run as an interactive command, the first time it's called
+in a sequence, deletes all spaces and tabs around point leaving
+one (or N spaces). If this does not change content of the
+buffer, skips to the second step:
+
+When run for the second time in a sequence, deletes all the
+spaces it has previously inserted.
+
+When run for the third time, returns the whitespace and point in
+a state encountered when it had been run for the first time.
+
+For example, if buffer contains \"foo ^ bar\" with \"^\" donating the
+point, calling `cycle-spacing' command will replace two spaces with
+a single space, calling it again immediately after, will remove all
+spaces, and calling it for the third time will bring two spaces back
+together.
+
+If N is negative, delete newlines as well. However, if
+PRESERVE-NL-BACK is t new line characters prior to the point
+won't be removed.
+
+If SINGLE-SHOT is non-nil, will only perform the first step. In
+other words, it will work just like `just-on-space' command."
+ (interactive "*p")
+ (let ((orig-pos (point))
+ (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+ (n (abs (or n 1))))
+ (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
+ (constrain-to-field nil orig-pos)
+ (cond
+ ;; Command run for the first time or single-shot is non-nil
+ ((or single-shot
+ (not (equal last-command this-command))
+ (not cycle-spacing--context))
+ (let* ((start (point))
+ (n (- n (skip-chars-forward " " (+ n (point)))))
+ (mid (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (setq cycle-spacing--context ;; Save for later
+ ;; Special handling for case where there was no space at all
+ (unless (= start end)
+ (cons orig-pos (buffer-substring start (point)))))
+ ;; If this run causes no change in buffer content, delete all spaces,
+ ;; otherwise delete all excees spaces.
+ (delete-region (if (and (not single-shot) (zerop n) (= mid end))
+ start mid) end)
+ (dotimes (_ n)
+ (insert ?\s))))
+
+ ;; Command run for the second time
+ ((not (equal orig-pos (point)))
+ (delete-region (point) orig-pos))
+
+ ;; Command run for the third time
+ (t
+ (insert (cdr cycle-spacing--context))
+ (goto-char (car cycle-spacing--context))
+ (setq cycle-spacing--context nil)))))
+
(defun just-one-space (&optional n)
"Delete all spaces and tabs around point, leaving one space (or N spaces).
If N is negative, delete newlines as well, leaving -N spaces."
(interactive "*p")
- (unless n (setq n 1))
- (let ((orig-pos (point))
- (skip-characters (if (< n 0) " \t\n\r" " \t"))
- (n (abs n)))
- (skip-chars-backward skip-characters)
- (constrain-to-field nil orig-pos)
- (dotimes (i n)
- (if (= (following-char) ?\s)
- (forward-char 1)
- (insert ?\s)))
- (delete-region
- (point)
- (progn
- (skip-chars-forward skip-characters)
- (constrain-to-field nil orig-pos t)))))
+ (cycle-spacing n nil t))
\f
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer.
--
1.7.7.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHv3] Add cycle-spacing command.
2012-12-10 14:57 ` [PATCHv2] Add cycle-spacing command Michal Nazarewicz
@ 2013-01-17 11:41 ` Michal Nazarewicz
2013-01-17 13:06 ` Lele Gaifax
0 siblings, 1 reply; 8+ messages in thread
From: Michal Nazarewicz @ 2013-01-17 11:41 UTC (permalink / raw)
To: emacs-devel, Drew Adams
From: Michal Nazarewicz <mina86@mina86.com>
This commit adds a cycle-spacing command which is, in a sense,
generalisation of the just-on-space command. When run continuously,
it cycles between having only one space, having no spaces and original
spacing.
---
So, any interest in this at all?
etc/NEWS | 5 +++
lisp/ChangeLog | 4 ++
lisp/simple.el | 86 ++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 80 insertions(+), 15 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index 0471683..8400cd0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -142,6 +142,11 @@ when its arg ADJACENT is non-nil (when called interactively with C-u C-u)
it works like the utility `uniq'. Otherwise by default it deletes
duplicate lines everywhere in the region without regard to adjacency.
+** New `cycle-spacing' command allows cycling between having just one
+space, no spaces, or reverting to the original spacing. Like
+`just-one-space' command it can handle or ignore newlines and use
+leave different number of spaces.
+
** Tramp
+++
*** New connection method "adb", which allows to access Android
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 684beb5..096a2a3 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-17 Michal Nazarewicz <mina86@mina86.com>
+
+ * simple.el: Add cycle-spacing command.
+
2013-01-17 Jürgen Hötzel <juergen@archlinux.org>
* eshell/esh-util.el (eshell-path-env): Make it buffer local, in
diff --git a/lisp/simple.el b/lisp/simple.el
index 847c07a..989b504 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -742,25 +742,81 @@ If BACKWARD-ONLY is non-nil, only delete them before point."
(skip-chars-backward " \t")
(constrain-to-field nil orig-pos)))))
+(defvar cycle-spacing--context nil
+ "Store context used in consecutive calls to `cycle-spacing' command.
+The first time this function is run, it saves the original point
+position and original spacing around the point in this
+variable.")
+
+(defun cycle-spacing (&optional n preserve-nl-back single-shot)
+ "Manipulate spaces around the point in a smart way.
+
+When run as an interactive command, the first time it's called
+in a sequence, deletes all spaces and tabs around point leaving
+one (or N spaces). If this does not change content of the
+buffer, skips to the second step:
+
+When run for the second time in a sequence, deletes all the
+spaces it has previously inserted.
+
+When run for the third time, returns the whitespace and point in
+a state encountered when it had been run for the first time.
+
+For example, if buffer contains \"foo ^ bar\" with \"^\" donating the
+point, calling `cycle-spacing' command will replace two spaces with
+a single space, calling it again immediately after, will remove all
+spaces, and calling it for the third time will bring two spaces back
+together.
+
+If N is negative, delete newlines as well. However, if
+PRESERVE-NL-BACK is t new line characters prior to the point
+won't be removed.
+
+If SINGLE-SHOT is non-nil, will only perform the first step. In
+other words, it will work just like `just-on-space' command."
+ (interactive "*p")
+ (let ((orig-pos (point))
+ (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+ (n (abs (or n 1))))
+ (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
+ (constrain-to-field nil orig-pos)
+ (cond
+ ;; Command run for the first time or single-shot is non-nil
+ ((or single-shot
+ (not (equal last-command this-command))
+ (not cycle-spacing--context))
+ (let* ((start (point))
+ (n (- n (skip-chars-forward " " (+ n (point)))))
+ (mid (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (setq cycle-spacing--context ;; Save for later
+ ;; Special handling for case where there was no space at all
+ (unless (= start end)
+ (cons orig-pos (buffer-substring start (point)))))
+ ;; If this run causes no change in buffer content, delete all spaces,
+ ;; otherwise delete all excees spaces.
+ (delete-region (if (and (not single-shot) (zerop n) (= mid end))
+ start mid) end)
+ (dotimes (i n)
+ (insert ?\s))))
+
+ ;; Command run for the second time
+ ((not (equal orig-pos (point)))
+ (delete-region (point) orig-pos))
+
+ ;; Command run for the third time
+ (t
+ (insert (cdr cycle-spacing--context))
+ (goto-char (car cycle-spacing--context))
+ (setq cycle-spacing--context nil)))))
+
(defun just-one-space (&optional n)
"Delete all spaces and tabs around point, leaving one space (or N spaces).
If N is negative, delete newlines as well, leaving -N spaces."
(interactive "*p")
- (unless n (setq n 1))
- (let ((orig-pos (point))
- (skip-characters (if (< n 0) " \t\n\r" " \t"))
- (n (abs n)))
- (skip-chars-backward skip-characters)
- (constrain-to-field nil orig-pos)
- (dotimes (_ n)
- (if (= (following-char) ?\s)
- (forward-char 1)
- (insert ?\s)))
- (delete-region
- (point)
- (progn
- (skip-chars-forward skip-characters)
- (constrain-to-field nil orig-pos t)))))
+ (cycle-spacing n nil t))
\f
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer.
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCHv3] Add cycle-spacing command.
2013-01-17 11:41 ` [PATCHv3] " Michal Nazarewicz
@ 2013-01-17 13:06 ` Lele Gaifax
2013-01-26 15:26 ` [PATCHv4] " Michal Nazarewicz
0 siblings, 1 reply; 8+ messages in thread
From: Lele Gaifax @ 2013-01-17 13:06 UTC (permalink / raw)
To: emacs-devel
Michal Nazarewicz <mpn@google.com> writes:
> diff --git a/lisp/simple.el b/lisp/simple.el
> ...
> +For example, if buffer contains \"foo ^ bar\" with \"^\" donating the
Probably you meant “denoting” here?
bye, lele.
--
nickname: Lele Gaifax | Quando vivrò di quello che ho pensato ieri
real: Emanuele Gaifas | comincerò ad aver paura di chi mi copia.
lele@metapensiero.it | -- Fortunato Depero, 1929.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCHv4] Add cycle-spacing command.
2013-01-17 13:06 ` Lele Gaifax
@ 2013-01-26 15:26 ` Michal Nazarewicz
2013-01-26 17:14 ` Stephen J. Turnbull
0 siblings, 1 reply; 8+ messages in thread
From: Michal Nazarewicz @ 2013-01-26 15:26 UTC (permalink / raw)
To: emacs-devel, Lele Gaifax
From: Michal Nazarewicz <mina86@mina86.com>
This commit adds a cycle-spacing command which is, in a sense,
generalisation of the just-on-space command. When run continuously,
it cycles between having only one space, having no spaces and original
spacing.
---
> Michal Nazarewicz <mpn@google.com> writes:
>> diff --git a/lisp/simple.el b/lisp/simple.el
>> ...
>> +For example, if buffer contains \"foo ^ bar\" with \"^\" donating the
On Thu, Jan 17 2013, Lele Gaifax <lele@metapensiero.it> wrote:
> Probably you meant “denoting” here?
Right, thanks.
etc/NEWS | 5 ++++
lisp/ChangeLog | 4 +++
lisp/simple.el | 86 ++++++++++++++++++++++++++++++++++++++++++++++++----------
3 files changed, 80 insertions(+), 15 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index 3e8bd3e..5959bc6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -157,6 +157,11 @@ when its arg ADJACENT is non-nil (when called interactively with C-u C-u)
it works like the utility `uniq'. Otherwise by default it deletes
duplicate lines everywhere in the region without regard to adjacency.
+** New `cycle-spacing' command allows cycling between having just one
+space, no spaces, or reverting to the original spacing. Like
+`just-one-space' command it can handle or ignore newlines and use
+leave different number of spaces.
+
** Tramp
+++
*** New connection method "adb", which allows to access Android
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 17a4a99..0ac59ff 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2013-01-26 Michal Nazarewicz <mina86@mina86.com>
+
+ * simple.el: Add cycle-spacing command.
+
2013-01-25 Alan Mackenzie <acm@muc.de>
AWK Mode: Fix indentation bug at top level. Bug #12274.
diff --git a/lisp/simple.el b/lisp/simple.el
index 847c07a..6533aef 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -742,25 +742,81 @@ If BACKWARD-ONLY is non-nil, only delete them before point."
(skip-chars-backward " \t")
(constrain-to-field nil orig-pos)))))
+(defvar cycle-spacing--context nil
+ "Store context used in consecutive calls to `cycle-spacing' command.
+The first time this function is run, it saves the original point
+position and original spacing around the point in this
+variable.")
+
+(defun cycle-spacing (&optional n preserve-nl-back single-shot)
+ "Manipulate spaces around the point in a smart way.
+
+When run as an interactive command, the first time it's called
+in a sequence, deletes all spaces and tabs around point leaving
+one (or N spaces). If this does not change content of the
+buffer, skips to the second step:
+
+When run for the second time in a sequence, deletes all the
+spaces it has previously inserted.
+
+When run for the third time, returns the whitespace and point in
+a state encountered when it had been run for the first time.
+
+For example, if buffer contains \"foo ^ bar\" with \"^\" denoting the
+point, calling `cycle-spacing' command will replace two spaces with
+a single space, calling it again immediately after, will remove all
+spaces, and calling it for the third time will bring two spaces back
+together.
+
+If N is negative, delete newlines as well. However, if
+PRESERVE-NL-BACK is t new line characters prior to the point
+won't be removed.
+
+If SINGLE-SHOT is non-nil, will only perform the first step. In
+other words, it will work just like `just-on-space' command."
+ (interactive "*p")
+ (let ((orig-pos (point))
+ (skip-characters (if (and n (< n 0)) " \t\n\r" " \t"))
+ (n (abs (or n 1))))
+ (skip-chars-backward (if preserve-nl-back " \t" skip-characters))
+ (constrain-to-field nil orig-pos)
+ (cond
+ ;; Command run for the first time or single-shot is non-nil
+ ((or single-shot
+ (not (equal last-command this-command))
+ (not cycle-spacing--context))
+ (let* ((start (point))
+ (n (- n (skip-chars-forward " " (+ n (point)))))
+ (mid (point))
+ (end (progn
+ (skip-chars-forward skip-characters)
+ (constrain-to-field nil orig-pos t))))
+ (setq cycle-spacing--context ;; Save for later
+ ;; Special handling for case where there was no space at all
+ (unless (= start end)
+ (cons orig-pos (buffer-substring start (point)))))
+ ;; If this run causes no change in buffer content, delete all spaces,
+ ;; otherwise delete all excees spaces.
+ (delete-region (if (and (not single-shot) (zerop n) (= mid end))
+ start mid) end)
+ (dotimes (i n)
+ (insert ?\s))))
+
+ ;; Command run for the second time
+ ((not (equal orig-pos (point)))
+ (delete-region (point) orig-pos))
+
+ ;; Command run for the third time
+ (t
+ (insert (cdr cycle-spacing--context))
+ (goto-char (car cycle-spacing--context))
+ (setq cycle-spacing--context nil)))))
+
(defun just-one-space (&optional n)
"Delete all spaces and tabs around point, leaving one space (or N spaces).
If N is negative, delete newlines as well, leaving -N spaces."
(interactive "*p")
- (unless n (setq n 1))
- (let ((orig-pos (point))
- (skip-characters (if (< n 0) " \t\n\r" " \t"))
- (n (abs n)))
- (skip-chars-backward skip-characters)
- (constrain-to-field nil orig-pos)
- (dotimes (_ n)
- (if (= (following-char) ?\s)
- (forward-char 1)
- (insert ?\s)))
- (delete-region
- (point)
- (progn
- (skip-chars-forward skip-characters)
- (constrain-to-field nil orig-pos t)))))
+ (cycle-spacing n nil t))
\f
(defun beginning-of-buffer (&optional arg)
"Move point to the beginning of the buffer.
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCHv4] Add cycle-spacing command.
2013-01-26 15:26 ` [PATCHv4] " Michal Nazarewicz
@ 2013-01-26 17:14 ` Stephen J. Turnbull
0 siblings, 0 replies; 8+ messages in thread
From: Stephen J. Turnbull @ 2013-01-26 17:14 UTC (permalink / raw)
To: Michal Nazarewicz; +Cc: Lele Gaifax, emacs-devel
Michal Nazarewicz writes:
> +** New `cycle-spacing' command allows cycling between having just one
> +space, no spaces, or reverting to the original spacing. Like
> +`just-one-space' command it can handle or ignore newlines and use
> +leave different number of spaces.
Typo: "use leave". You probably meant just "leave".
> +If SINGLE-SHOT is non-nil, will only perform the first step. In
> +other words, it will work just like `just-on-space' command."
Typo: I think you mean "`just-one-space' command."
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-01-26 17:14 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-04 22:36 [PATCH] Add smart-space command Michal Nazarewicz
2012-12-04 22:55 ` Drew Adams
2012-12-04 23:11 ` Michal Nazarewicz
2012-12-10 14:57 ` [PATCHv2] Add cycle-spacing command Michal Nazarewicz
2013-01-17 11:41 ` [PATCHv3] " Michal Nazarewicz
2013-01-17 13:06 ` Lele Gaifax
2013-01-26 15:26 ` [PATCHv4] " Michal Nazarewicz
2013-01-26 17:14 ` Stephen J. Turnbull
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.