From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Michal Nazarewicz Newsgroups: gmane.emacs.bugs Subject: bug#18730: [PATCH] tildify.el: Add `auto-tildify' and `auto-tildify-mode'. Date: Wed, 15 Oct 2014 10:01:26 +0200 Organization: Google Inc Message-ID: NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: ger.gmane.org 1413360144 32497 80.91.229.3 (15 Oct 2014 08:02:24 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 15 Oct 2014 08:02:24 +0000 (UTC) Cc: Milan Zamazal To: 18730@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Oct 15 10:02:16 2014 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1XeJXE-0004DR-Ds for geb-bug-gnu-emacs@m.gmane.org; Wed, 15 Oct 2014 10:02:16 +0200 Original-Received: from localhost ([::1]:42613 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJXE-0002tF-2z for geb-bug-gnu-emacs@m.gmane.org; Wed, 15 Oct 2014 04:02:16 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40229) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJX6-0002t3-EY for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:02:13 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XeJX1-0001WW-8K for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:02:08 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:52280) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJX1-0001Vs-5H for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:02:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1XeJX0-0001ug-0Z for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:02:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Michal Nazarewicz Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 15 Oct 2014 08:02:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 18730 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.14133601117330 (code B ref -1); Wed, 15 Oct 2014 08:02:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 15 Oct 2014 08:01:51 +0000 Original-Received: from localhost ([127.0.0.1]:43844 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XeJWo-0001u7-IH for submit@debbugs.gnu.org; Wed, 15 Oct 2014 04:01:51 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:38421) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1XeJWl-0001tu-Oq for submit@debbugs.gnu.org; Wed, 15 Oct 2014 04:01:48 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XeJWg-0000oO-Ik for submit@debbugs.gnu.org; Wed, 15 Oct 2014 04:01:47 -0400 Original-Received: from lists.gnu.org ([208.118.235.17]:59173) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJWg-0000oG-GA for submit@debbugs.gnu.org; Wed, 15 Oct 2014 04:01:42 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:40117) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJWb-0002sb-DA for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:01:42 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XeJWU-0000kz-CN for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:01:37 -0400 Original-Received: from mail-wi0-x231.google.com ([2a00:1450:400c:c05::231]:57871) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XeJWU-0000kp-1g for bug-gnu-emacs@gnu.org; Wed, 15 Oct 2014 04:01:30 -0400 Original-Received: by mail-wi0-f177.google.com with SMTP id fb4so1124352wid.4 for ; Wed, 15 Oct 2014 01:01:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:cc:subject:organization:user-agent:face:date :message-id:mime-version:content-type:content-transfer-encoding; bh=iMGQvzgwAMm9YKrrTgs8RercLauhuonVsZk/LIbWgMw=; b=m3m7cyHkfn3sRd9xanuS4h61DLXiKXnU+sJlikZT6dR3puzfOWU53lle8N5B2o0aJm DRAgwq82rysQ0rd5H5cNYWFS4EJ7uStHVwBF6IXSk2CIxVBrr5760xjlcpHlBCa3OVYe gMPq6rXiISJF2uohhuPq6OS5j/HJa5TzxeBKxO+ftxSwtwKJVgvYpymcurx2usDEeCX8 R/0V7Y37r14Ef5KDqUwzZSeBZ2QGHedJrhpc07YSdj7YfEizOaDZzIDkrWeP0H529Qfb Ru/In9Oum5OlUByWOi7iK9PylfhoqlfW1yErbJJ4XjDpbfI+q9YeczxSV7dA0BLtUEDl pBXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:organization :user-agent:face:date:message-id:mime-version:content-type :content-transfer-encoding; bh=iMGQvzgwAMm9YKrrTgs8RercLauhuonVsZk/LIbWgMw=; b=Wq8H3/nTeK0piqk+jWV/E52pmLTlIwXC0TDOlWYiFrG3CorAlWmPdlh1sWFAEFs10T XFCcd4JWKgx0TnSnwDVphmQjXmMr/f2Hmw7wjcT0WCl7QUd99u/nx+QTUTW20tad4BJc uT1NawmYdNJ0Jt1ow2OHCNON7X/Id/q0ysXvATT6F1KTlrrTRIDRpJnIyHT0ORGXfQZc kB1ktFMeZdEVCLZBkz4yFF+Ct93Wcpkh5O6T0HpJpzZHs/d2U4DR2M9UUj4+SvzycvcJ DfUbRiMwFIEN2BKgKFZ2kyKYyXuHUR94TBqkdimonppbqZ/Yx/eFXRCvFxAX96zWAksW xWFg== X-Gm-Message-State: ALoCoQlPZmdPAgc0i38TBd33wcyukEI1bq2O70y7PCCpsROua2AqagGEJvx356SVc50c1ZW7/QpK X-Received: by 10.194.216.232 with SMTP id ot8mr10582178wjc.74.1413360089113; Wed, 15 Oct 2014 01:01:29 -0700 (PDT) Original-Received: from mpn-glaptop.roam.corp.google.com ([62.156.150.204]) by mx.google.com with ESMTPSA id q9sm2413921wix.6.2014.10.15.01.01.27 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 15 Oct 2014 01:01:28 -0700 (PDT) User-Agent: Notmuch/0.17+15~gb65ca8e (http://notmuchmail.org) Emacs/24.4.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-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:94526 The `auto-tildify' function can be used as a `post-self-insert-hook' to automatically convert spaces into hard spaces. It is configured via two new customize variables: `auto-tildify-pattern-alist' and `auto-tildify-check-envs'. `auto-tildify-mode' makes use of that function to enable eletric behaviour of space character. --- etc/NEWS | 6 +++ lisp/textmodes/tildify.el | 96 +++++++++++++++++++++++++++++++++++++= +++- test/automated/tildify-tests.el | 32 ++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) diff --git a/etc/NEWS b/etc/NEWS index e336ff5..7ef73a4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -254,6 +254,12 @@ These emulations of old editors are believed to be no = longer relevant * New Modes and Packages in Emacs 25.1 =20 +** `auto-tildify-mode' allows to automatically add hard spaces as one types +the text. Breaking line after a single-character words are forbidden +by Czech and Polish typography (and may be discouraged in other +languages), so `auto-tildify-mode' makes it easier to create +a typographically-correct documents. + * Incompatible Lisp Changes in Emacs 25.1 =20 diff --git a/lisp/textmodes/tildify.el b/lisp/textmodes/tildify.el index 50fee2f..aed060a 100644 --- a/lisp/textmodes/tildify.el +++ b/lisp/textmodes/tildify.el @@ -4,7 +4,7 @@ =20 ;; Author: Milan Zamazal ;; Michal Nazarewicz -;; Version: 4.5.3 +;; Version: 4.6 ;; Keywords: text, TeX, SGML, wp =20 ;; This file is part of GNU Emacs. @@ -344,6 +344,100 @@ replacements done and response is one of symbols: t (= all right), nil (t t)))))) =20 =20 +;;; *** Auto Tildify *** + +(defcustom auto-tildify-pattern-alist + '((t . "[,:;(][ \t]*[a]\\|\\<[AIKOSUVWZikosuvwz]")) + "Alist specifying whether to insert hard space at point. + +Each alist item is of the form (MAJOR-MODE . REGEXP) or +\(MAJOR-MODE . SYMBOL). + +MAJOR-MODE defines major mode, for which the item applies. It can be eith= er: +- a symbol equal to the major mode of the buffer to be fixed +- t for default item, this applies to all major modes not defined in anoth= er + alist item + +REGEXP is a regular expression matching the part of a text that +needs a hard space to be inserted instead of a space. The regexp +is always case sensitive, regardless of the current +`case-fold-search' setting. + +The form (MAJOR-MODE . SYMBOL) defines alias item for MAJOR-MODE. For this +mode, the item for the mode SYMBOL is looked up in the alist instead." + :group 'tildify + :type '(repeat (cons (choice (const :tag "Default" t) + (symbol :tag "For mode ")) + (choice (regexp :tag "Regexp ") + (symbol :tag "Like mode"))))) + +(defcustom auto-tildify-check-envs t + "Should `auto-tildify' check if point is inside ignored environment." + :group 'tildify + :type 'boolean) + + +;;;###autoload +(defun auto-tildify () + "Convert space before point into a hard space if the context is right. + +If + * character before point is a space character, + * character before that has =E2=80=9Cw=E2=80=9D character syntax (i.e. it= 's + a word constituent), + * pattern from `auto-tildify-pattern-alist' matches when + `looking-back' (no more than 10 characters) from before the space + character, and + * `auto-tildify-check-envs' is nil or point is not inside of an + environment to ignore +replace the space character with a hard space defined in +`auto-tildify-string'. + +Return t if conversion happened, nil otherwise. + +This function is meant to be used as a `post-self-insert-hook'." + (interactive) + (let ((p (point)) case-fold-search space pattern) + (when (and (> (- p (point-min)) 2) + (eq (preceding-char) ?\s) + (eq (char-syntax (char-before (1- p))) ?w) + (setq space (tildify-mode-alist tildify-string-alist)) + (not (string-equal " " space)) + (setq pattern (tildify-mode-alist auto-tildify-pattern-alis= t)) + (save-excursion + (goto-char (1- p)) + (looking-back pattern (max (point-min) (- p 10)))) + (or (not auto-tildify-check-envs) + (catch 'found + (tildify-foreach-region-outside-env (- p 2) (1- p) + (lambda (beg end) (throw 'found t)))))) + (delete-char -1) + (insert space) + t))) + +;;;###autoload +(define-minor-mode auto-tildify-mode + "Adds electric behaviour to space character. + +When space is inserted into a buffer in a position where hard +space is required instead, that space character is replaced by +a hard space correct for given mode. + +Converting of the space is done by `auto-tildify'." + nil " ~" nil + (when auto-tildify-mode + (when (let ((space (tildify-mode-alist tildify-string-alist))) + (or (not space) (string-equal " " space))) + (message "Hard space for %s is a single space character, auto-tildif= y won't have any effect." major-mode) + (setq auto-tildify-mode nil)) + (when (not (tildify-mode-alist auto-tildify-pattern-alist)) + (message "No auto-pattern defined for %s, auto-tildify won't have an= y effect." major-mode) + (setq auto-tildify-mode nil))) + (if auto-tildify-mode + (add-hook 'post-self-insert-hook 'auto-tildify nil t) + (remove-hook 'post-self-insert-hook 'auto-tildify t))) + + ;;; *** Announce *** =20 (provide 'tildify) diff --git a/test/automated/tildify-tests.el b/test/automated/tildify-tests= .el index 53c2e62..f8a4d8c 100644 --- a/test/automated/tildify-tests.el +++ b/test/automated/tildify-tests.el @@ -132,6 +132,38 @@ latter is missing, SENTENCE will be used in all placeh= older positions." (should (string-equal "close-foo" (tildify-find-env beg-re pairs))))= )) =20 =20 +(defun auto-tildify-test--test (modes nbsp env-open) + (with-temp-buffer + (dolist (mode modes) + (erase-buffer) + (funcall mode) + (let ((header (concat "Testing `auto-tildify' in " + (symbol-name mode) "\n"))) + (insert header "Lorem v ") + (should (auto-tildify)) + (should (string-equal (concat header "Lorem v" nbsp) (buffer-strin= g)))) + (erase-buffer) + (let ((header (concat "Testing `auto-tildify' in " + (symbol-name mode) "\n"))) + (insert header env-open "Lorem v ") + (should (not (auto-tildify))) + (should (string-equal (concat header env-open "Lorem v ") + (buffer-string))))))) + +(ert-deftest auto-tildify-test-html () + "Tests auto-tildification in an HTML document" + (auto-tildify-test--test '(html-mode sgml-mode) " " "
"))
+
+(ert-deftest auto-tildify-test-xml ()
+  "Tests auto-tildification in an XML document"
+  (auto-tildify-test--test '(nxml-mode) " " "