From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michal Nazarewicz Newsgroups: gmane.emacs.devel Subject: [PATCHv4] Add cycle-spacing command. Date: Sat, 26 Jan 2013 16:26:54 +0100 Message-ID: References: <8738y0klg9.fsf@metapensiero.it> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Trace: ger.gmane.org 1359214028 8995 80.91.229.3 (26 Jan 2013 15:27:08 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 26 Jan 2013 15:27:08 +0000 (UTC) To: emacs-devel@gnu.org, Lele Gaifax Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sat Jan 26 16:27:26 2013 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Tz7fC-0003fH-1t for ged-emacs-devel@m.gmane.org; Sat, 26 Jan 2013 16:27:26 +0100 Original-Received: from localhost ([::1]:42893 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tz7eu-0005zB-Fy for ged-emacs-devel@m.gmane.org; Sat, 26 Jan 2013 10:27:08 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:57595) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tz7eq-0005yu-17 for emacs-devel@gnu.org; Sat, 26 Jan 2013 10:27:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tz7en-0002Da-3W for emacs-devel@gnu.org; Sat, 26 Jan 2013 10:27:03 -0500 Original-Received: from mail-ea0-f178.google.com ([209.85.215.178]:52649) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tz7em-0002DM-Pt for emacs-devel@gnu.org; Sat, 26 Jan 2013 10:27:01 -0500 Original-Received: by mail-ea0-f178.google.com with SMTP id a14so579860eaa.9 for ; Sat, 26 Jan 2013 07:26:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:subject:date:message-id:x-mailer:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=zbu00oRR7t8tDSc+4UhHBmYyLND5Mtd2hDwfVRmgHDA=; b=SOVje/l2nsTPwkouTmxEHht4SRQIFVEBtbBimBJTS8PQicu1vO0u4eezgIryA1RoA8 1Tb9b8PU5bfxjeO+qJiYTUnENU1Wo4lLjDr+3MELq7Ul78ib+ysyKZZVL+Cjx3yzCDyt H/cyDuCT7OW6UNzcbjBcIHHv2OeP25jAYI8maUS9wSSbN89zeMg2bt3xSlTm6Sz98rgc TYAc2NKDUkfmbvJ7LcNiZ5nIMc3v6Q1AXlolKwUmKpJbeIAmY9hLEdxpQloo8S/Gnzb4 D7iKnuMqOeeuAeJaoaLc4sASUeXGbOah6wPRQxjvL4ZIlX7YIgmGQCBPwiuJLDc99aFK MvLA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:from:to:subject:date:message-id:x-mailer:in-reply-to :references:mime-version:content-type:content-transfer-encoding :x-gm-message-state; bh=zbu00oRR7t8tDSc+4UhHBmYyLND5Mtd2hDwfVRmgHDA=; b=OiY8uNKxSyxhGNj7w/Y3zOr01SAGS7r7VhOAB610vFjUjke9YBCNgO6H+BakpVXe+t S2Rsag2+/0NlmFgs5dPFJuvpVEFEici99JrLnzacF9xvRvhei18YXfvSPVCPdr3yOowK PivqC3GhLLgf33txhmaJ0crOd2ZtTD4ib2+zCd+c8xuEaE0A2EoQ4YpY2nHVMAbvpZhR UZ3ZCZkF4aoZz+WAgpZ/UJBeKgakhqiwF6pg482Rdw+GIdZiMpXQF6LH5BShACiIYpGH ophioa4gGFuVvx+S7BuivD8fEpIFpnHYDkmoGiyOHNSiSH+pvX36aOHlwFSxUlukk+5G d0Ig== X-Received: by 10.14.216.70 with SMTP id f46mr31172114eep.12.1359214019279; Sat, 26 Jan 2013 07:26:59 -0800 (PST) Original-Received: from mpn-glaptop.corp.google.com ([172.28.91.145]) by mx.google.com with ESMTPS id g2sm6907510eep.16.2013.01.26.07.26.57 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 26 Jan 2013 07:26:58 -0800 (PST) X-Mailer: git-send-email 1.8.1 In-Reply-To: <8738y0klg9.fsf@metapensiero.it> X-Gm-Message-State: ALoCoQlsY1yYq0jp8HNNbriqkbEcfceKcb2TVDmu77a+ix6pA6g0c1V/VOPIbC4m4L2JhELdAfADsORStQwGXWsaku0ShqjcoAovVAq4himFth/C6S+jSvYjGndbtYGGqiyCOympUIXdeM9m+fNgGtLJ+mPVsMkFb3DvvaVeRwN8h8ZlAqOem8/7sPegM4nHytQkmDowau8/AyOo/WT8eQW/gATA/SI71w== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.215.178 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:156653 Archived-At: From: Michal Nazarewicz 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 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 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 + + * simple.el: Add cycle-spacing command. + 2013-01-25 Alan Mackenzie 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)) (defun beginning-of-buffer (&optional arg) "Move point to the beginning of the buffer.