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: [PATCH] Add smart-space command. Date: Tue, 04 Dec 2012 23:36:14 +0100 Organization: Google Inc Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1354660600 23391 80.91.229.3 (4 Dec 2012 22:36:40 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 4 Dec 2012 22:36:40 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Dec 04 23:36:53 2012 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 1Tg16h-0001C4-5o for ged-emacs-devel@m.gmane.org; Tue, 04 Dec 2012 23:36:51 +0100 Original-Received: from localhost ([::1]:56382 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg16V-0001Mk-DU for ged-emacs-devel@m.gmane.org; Tue, 04 Dec 2012 17:36:39 -0500 Original-Received: from eggs.gnu.org ([208.118.235.92]:55054) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg16J-0001MS-2z for emacs-devel@gnu.org; Tue, 04 Dec 2012 17:36:37 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Tg16B-0002jk-Dr for emacs-devel@gnu.org; Tue, 04 Dec 2012 17:36:26 -0500 Original-Received: from mail-ea0-f169.google.com ([209.85.215.169]:61416) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Tg16B-0002jc-2e for emacs-devel@gnu.org; Tue, 04 Dec 2012 17:36:19 -0500 Original-Received: by mail-ea0-f169.google.com with SMTP id a12so2079479eaa.0 for ; Tue, 04 Dec 2012 14:36:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:organization:user-agent:x-face:face:x-pgp:x-pgp-fp :date:message-id:mime-version:content-type; bh=JWq+fh1S1jEgt4r/e1+zj6RwvLxFaJXas2Oid2M/v2M=; b=Rx8KomTBLEq84wFrfdkOFsenjozM0y8iN0163Qu/RpIIuRyjDva3njjxCAr4WXNF35 36kihgdsJcTd0BiHwgoQ8J3sxxSZkHe8jO1ee+4p4lccEjrjjETyhXO8QhsodsZqmFf1 hDJjzKaL+89yHn6qis0uMOTMjyllI9SCCUoBVtntTmIbcU4yX1n0RcEDYZLATbmKapDa 3sTKkvCRELwpJEMCEj3QkzK5eAfTrHcxa/VRn/L064D5LsqH8B/W0hdMyvoz6Vsz0kY6 EkkRmFml8za0ok9heLq5pdeSSmYgqJpBIEczeQ6EdFMKwSC/THqS9q8JpuSfkquOeqcn akjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:organization:user-agent:x-face:face:x-pgp:x-pgp-fp :date:message-id:mime-version:content-type:x-gm-message-state; bh=JWq+fh1S1jEgt4r/e1+zj6RwvLxFaJXas2Oid2M/v2M=; b=SwCDfKjWwZ2a1OUQFGil6NHjVYycNUmVb3LNye0bPxbfjHZo9cn8xn1GZpJ7bDxv5X +dyvmt6ueAHqYor7jLrtoi/DKqXqFMG2z76TYTnd1NVz7jPzjM0LGS8W81eeEq8Kisq2 Qtpf1z9iWZhOtSMMl7O06IlJG+qXnC7EI1LWiR1b9FwcMBXoWM0nf4mt0dRsukWGXTW4 8BBNKpE/+80z0Wn60mG6654RUPyCYkPBHqmfUMVkcotlGZk+tixuZVRV4ET7yYB1hPdV ESF18XY5PPRLX1etgtGUhN5C0WXc+3HmkGNsg5YA6JL56HUE+jN8dEIgmHEsUFNIkdxu SLEg== Original-Received: by 10.14.175.198 with SMTP id z46mr53127767eel.26.1354660577699; Tue, 04 Dec 2012 14:36:17 -0800 (PST) Original-Received: from mpn-glaptop ([2620:0:105f:5:8c95:2fd8:feb2:1f3c]) by mx.google.com with ESMTPS id f49sm5294474eep.12.2012.12.04.14.36.16 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 04 Dec 2012 14:36:16 -0800 (PST) User-Agent: Notmuch/ (http://notmuchmail.org) Emacs/24.2.50.1 (x86_64-unknown-linux-gnu) X-Face: PbkBB1w#)bOqd`iCe"Ds{e+!C7`pkC9a|f)Qo^BMQvy\q5x3?vDQJeN(DS?|-^$uMti[3D*#^_Ts"pU$jBQLq~Ud6iNwAw_r_o_4]|JO?]}P_}Nc&"p#D(ZgUb4uCNPe7~a[DbPG0T~!&c.y$Ur,=N4RT>]dNpd; KFrfMCylc}gc??'U2j,!8%xdD Face: iVBORw0KGgoAAAANSUhEUgAAADAAAAAwBAMAAAClLOS0AAAAJFBMVEWbfGlUPDDHgE57V0jUupKjgIObY0PLrom9mH4dFRK4gmjPs41MxjOgAAACQElEQVQ4jW3TMWvbQBQHcBk1xE6WyALX1069oZBMlq+ouUwpEQQ6uRjttkWP4CmBgGM0BQLBdPFZYPsyFUo6uEtKDQ7oy/U96XR2Ux8ehH/89Z6enqxBcS7Lg81jmSuujrfCZcLI/TYYvbGj+jbgFpHJ/bqQAUISj8iLyu4LuFHJTosxsucO4jSDNE0Hq3hwK/ceQ5sx97b8LcUDsILfk+ovHkOIsMbBfg43VuQ5Ln9YAGCkUdKJoXR9EclFBhixy3EGVz1K6eEkhxCAkeMMnqoAhAKwhoUJkDrCqvbecaYINlFKSRS1i12VKH1XpUd4qxL876EkMcDvHj3s5RBajHHMlA5iK32e0C7VgG0RlzFPvoYHZLRmAC0BmNcBruhkE0KsMsbEc62ZwUJDxWUdMsMhVqovoT96i/DnX/ASvz/6hbCabELLk/6FF/8PNpPCGqcZTGFcBhhAaZZDbQPaAB3+KrWWy2XgbYDNIinkdWAFcCpraDE/knwe5DBqGmgzESl1p2E4MWAz0VUPgYYzmfWb9yS4vCvgsxJriNTHoIBz5YteBvg+VGISQWUqhMiByPIPpygeDBE6elD973xWwKkEiHZAHKjhuPsFnBuArrzxtakRcISv+XMIPl4aGBUJm8Emk7qBYU8IlgNEIpiJhk/No24jHwkKTFHDWfPniR 4iw5vJaw2nzSjfq2zffcE/GDjRC2dn0J0XwPAbDL84TvaFCJEU4Oml9pRyEUhR3Cl2t01AoEjRbs0sYugp14/4X5n4pU4EHHnMAAAAAElFTkSuQmCC X-PGP: 50751FF4 X-PGP-FP: AC1F 5F5C D418 88F8 CC84 5858 2060 4012 5075 1FF4 X-Gm-Message-State: ALoCoQkBg3m0QNeLPYhmfQNPDFGDCTYpib03LwD9DeCkh7Zbex6XRgRnO1DAtZLyCPO3c9lTEViw0m6w1oY6fbTxs1BfKOnQW+aJly4naBiduRpyYyEZZlcRICBrYoTcIkq2d9CFlQ4Z9Bsv6qrcNfdU4ZLy70pZHhXB53BalayT5ZsGnrtSaHI6VQ9MmCLx5xzx+kelfJAG/mwADf208H0mMFk4Imq13g== X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 209.85.215.169 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:155267 Archived-At: 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 + + * simple.el: Add smart-space command. + 2012-12-04 Stefan Monnier * 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)) (defun beginning-of-buffer (&optional arg) "Move point to the beginning of the buffer.