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: [PATCHv3] Add cycle-spacing command. Date: Thu, 17 Jan 2013 12:41:40 +0100 Message-ID: <4a0822967f5a904ff6c1eaae77d2cc526c69858a.1358422492.git.mina86@mina86.com> References: NNTP-Posting-Host: plane.gmane.org Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Trace: ger.gmane.org 1358422921 3261 80.91.229.3 (17 Jan 2013 11:42:01 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 17 Jan 2013 11:42:01 +0000 (UTC) To: emacs-devel@gnu.org, Drew Adams Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Jan 17 12:42:19 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 1TvnrP-00082Y-Gi for ged-emacs-devel@m.gmane.org; Thu, 17 Jan 2013 12:42:19 +0100 Original-Received: from localhost ([::1]:59737 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tvnr9-00033Z-0u for ged-emacs-devel@m.gmane.org; Thu, 17 Jan 2013 06:42:03 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:51566) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tvnqz-00033F-2n for emacs-devel@gnu.org; Thu, 17 Jan 2013 06:42:01 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tvnqv-0006t4-Kt for emacs-devel@gnu.org; Thu, 17 Jan 2013 06:41:52 -0500 Original-Received: from mail-lb0-f170.google.com ([209.85.217.170]:38912) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tvnqv-0006sn-8H for emacs-devel@gnu.org; Thu, 17 Jan 2013 06:41:49 -0500 Original-Received: by mail-lb0-f170.google.com with SMTP id j14so1828879lbo.15 for ; Thu, 17 Jan 2013 03:41:47 -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 :content-type:content-transfer-encoding; bh=tYLfHLOXvygfwPHEpRgRrfi2CT51AwdlGJyVLHJd5oQ=; b=QejPUqQnusSoIfpduEvNo3CW7iKEFqp5mQqyIfagOQSNpeVUcYH5cGU7+eGZpbNJJQ Yw94RUmBW9/QTS32/wrQ9jaxWwl6Vo4AiDo84UXmxpaMI/zwCe/YJscnV4QxsH1C99K6 KxaZ+V5RgiRYfGtc0DA24Vmw7IwaeIi16PQDV6ABaYw4MrZXhfpxORZqlZGCvWojGQuc hnlPuYntnW72JB7nifhR4wwwezMpf5RNZS/cUBi7OMQ1pnZ89vw3c7GEgOjz960oIxyG O/FuXXe6K8wR5+kwldgSCywULhfwfdA2KyguQciPmxzgWVI6o45ZAMritfQkzBNK+kCw AfPw== 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 :content-type:content-transfer-encoding:x-gm-message-state; bh=tYLfHLOXvygfwPHEpRgRrfi2CT51AwdlGJyVLHJd5oQ=; b=l47U117yAR+6Rzj5QDh3kFy56yIJFHh91VzYD4gSkK73YfidoNMikk9Tm4ooqUhHTl aKiZReUffuUVaIcDsEMOI1ftjiUX3xjm2GLMoLLmaVS+kra8Hi/9C4g5FTLV46mNQhpa Zdnqa5rOKNhb6/xhprkwMAyEWKVrxp9Pc+tCAaDNB6+g+DEUj9kXgQkzaskslekZp2VS L4N5EPi60vnnxApshZn231PTW33JurrW9dFpeDHTpaiDE4hclXi9pmiO0bjeW6pWcBYo RQc4OOmQ8LtMOJfTWS3HA50oZ4YDzKWCbluC2ZttQySaZcx3hwYc0GYWiU8kCjByNGda jLCw== X-Received: by 10.112.23.136 with SMTP id m8mr2092504lbf.16.1358422907343; Thu, 17 Jan 2013 03:41:47 -0800 (PST) Original-Received: from mpn-glaptop.corp.google.com ([2620:0:105f:5:110a:234e:2060:88d1]) by mx.google.com with ESMTPS id fj2sm641662lbb.6.2013.01.17.03.41.45 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 17 Jan 2013 03:41:45 -0800 (PST) X-Mailer: git-send-email 1.7.7.3 In-Reply-To: X-Gm-Message-State: ALoCoQknvkf7jqX4H+J5UTJFVE7LhPL8ziIIPq9KkuDIY/2Oc6sFQveqrAQh/CoQTDuZMmKI81Kz6ZQ0caDZk8BYic5psCei6zdx/9hMqUSGzqmIPAmrDyjq8eclPXG/W0EJpYKWHqkMOejtscY3ID+4ztLcppoMwOrFvMDd4eEdTnjJnuoU51z8qKGq0/CLXZLD/qDkmyuS7nXOXH0R4IU26bKHjVXgtw== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.217.170 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:156441 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. --- 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 + + * simple.el: Add cycle-spacing command. + 2013-01-17 Jürgen Hötzel * 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)) (defun beginning-of-buffer (&optional arg) "Move point to the beginning of the buffer.