From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.devel Subject: Re: Word wrap for non-whitespace-seperated language Date: Thu, 5 Mar 2020 17:50:22 -0500 Message-ID: <0C001A5A-B45C-43C0-9D1E-88A6977AAEC3@gmail.com> References: <838skgvu2l.fsf@gnu.org> <3692AB81-B291-4D14-BEDE-924F020D94ED@gmail.com> <837e00vsk9.fsf@gnu.org> <9737C398-80FC-4377-91BA-C0891BD5A0F5@gmail.com> <835zfjwgyb.fsf@gnu.org> <6DE83788-5296-4C4F-A265-88B33A43DC93@gmail.com> Mime-Version: 1.0 (Mac OS X Mail 13.0 \(3608.60.0.2.5\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_AB90B314-7BE2-4F97-A872-ED36A44F9AB1" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="96346"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Mar 05 23:51:13 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1j9zKi-000Ov5-50 for ged-emacs-devel@m.gmane-mx.org; Thu, 05 Mar 2020 23:51:12 +0100 Original-Received: from localhost ([::1]:57100 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j9zKg-0002Vx-Oa for ged-emacs-devel@m.gmane-mx.org; Thu, 05 Mar 2020 17:51:10 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:38907) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1j9zK5-0001zN-EE for emacs-devel@gnu.org; Thu, 05 Mar 2020 17:50:34 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1j9zK3-0000Fe-9V for emacs-devel@gnu.org; Thu, 05 Mar 2020 17:50:32 -0500 Original-Received: from mail-qt1-x830.google.com ([2607:f8b0:4864:20::830]:44213) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1j9zK0-000097-FY; Thu, 05 Mar 2020 17:50:28 -0500 Original-Received: by mail-qt1-x830.google.com with SMTP id h16so350642qtr.11; Thu, 05 Mar 2020 14:50:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=98xpEyKwr5VQWPN3rfAs/PbO/LLTQNWN8XV8WeNkCHQ=; b=aTsoyvlK/0HDyBS2GtHGK0XtDecVyqzOQAFFqlnSnWt3LdWZ0DFNkBUQbBHGdEUKSC CemlsJoLvl22yY4xgsIqco6U5vewAkTHXPagbvJjfLH2Xrc9xCMvKJBJKccI2E/OpiJC ZYphppQUajl6Yh8ExGoH6bZLT7dS3MuSWFDm2U8RoKZVbbdXL4fVDsj3jAmK5KXb5Bk/ 30pr82HMHhurvKGv4goNLhy7VbsNwDaOc03oHJgWXJpZtaxDawzOMl/HFN+Hmd7wIWgW dyR3Vc2MN1Z8qLHXfVl/6fSyCUb+ASI4twOnMdZ2eKNeJYWp4pUXMWaSV+Eqip5jRkFc vSfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=98xpEyKwr5VQWPN3rfAs/PbO/LLTQNWN8XV8WeNkCHQ=; b=lIsBfa5whTDe4c6J/BnsY3v9sulYq63qySkbuVkGx29UeLK5q3sSq0YtD/zyq4vjtS j8ZkQJXw523bRSgPTmOkNPcFASj5eGtAJFrxZLZ4HOZ5NAfoJWK8lLW3Vx6cL/hT/Vs+ rv0ZbQ2F21MaiKo41rw2BY3hhBgBmXtCAJCp2KqFUiuZIgfQTMCf/4fNsO4Cgd/8wD+K D+YYlncRqsJ/ro0LGWx2pKajQQGIsOzfjpmwBnhbYIWm6av8hFZPj2AQg0mv6+CS1udi 3LeRxqO6Y3uszl6pipwGKzpgZrRUz5GzRXnMFvvSMv/Eg4YdmaToH5W+kHMBEPARQTaM BQzg== X-Gm-Message-State: ANhLgQ0Oy19TK/Bb/vtmZmcqGCkg6rtkFnwemx3REbQ22mOSgkvqTm4g 8U9JKiqtkrFP6lyWJg4AAVJ/n4hUnrJA0w== X-Google-Smtp-Source: ADFU+vsRA/ss/6fWEIQ7HArFt6meBvqcrCoeozi8RF6gvkUIQWpUBWa6csmiHREGhAjibKwvXt7w+g== X-Received: by 2002:ac8:7b94:: with SMTP id p20mr501998qtu.122.1583448626340; Thu, 05 Mar 2020 14:50:26 -0800 (PST) Original-Received: from [104.39.198.240] ([104.39.198.240]) by smtp.gmail.com with ESMTPSA id 4sm5178283qkm.22.2020.03.05.14.50.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Mar 2020 14:50:24 -0800 (PST) In-Reply-To: <6DE83788-5296-4C4F-A265-88B33A43DC93@gmail.com> X-Mailer: Apple Mail (2.3608.60.0.2.5) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4864:20::830 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 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-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:245279 Archived-At: --Apple-Mail=_AB90B314-7BE2-4F97-A872-ED36A44F9AB1 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > I have no idea if it helps (apologies, if not), > but maybe take a look at library `find-where.el'. > It lets you find (forward or backward) the first > (or the Nth) buffer position where some predicate > holds. Thanks Adam. I actually find the way just now (by sheer luck). Now its = reasonably fast. For anyone that=E2=80=99s interested, here is the code. Set = sfill-variale-pitch to t and M-x sfill-paragraph on a text paragraph, = and see the magic happens ;-) It would be great if some one can have a = look at it and give some suggestions, especially if it can be made = faster. Next I want to try to make it automatic and only fills the = visible portion just-in-time. Could some one point me to some library = that does similar things? Thanks. --Apple-Mail=_AB90B314-7BE2-4F97-A872-ED36A44F9AB1 Content-Disposition: attachment; filename=sfill.el Content-Type: application/octet-stream; x-unix-mode=0644; name="sfill.el" Content-Transfer-Encoding: quoted-printable ;;;=20sfill.el=20---=20Soft=20and=20smart=20fill=20=20=20=20=20=20-*-=20= lexical-binding:=20t;=20-*-=0A=0A;;=20Author:=20Yuan=20Fu=20= =0A=0A;;;=20This=20file=20is=20NOT=20part=20of=20GNU=20= Emacs=0A=0A;;;=20Commentary:=0A;;=0A=0A;;;=20Code:=0A;;=0A=0A= (defvar-local=20sfill-column=2070=0A=20=20"Default=20fill=20Column=20for=20= sfill.")=0A=0A(defvar-local=20sfill-variable-pitch-column=2070=0A=20=20= "Column=20used=20for=20variable=20pitch=20filling.")=0A=0A(defvar-local=20= sfill-variale-pitch=20nil=0A=20=20"Set=20to=20non-nil=20and=20sfill=20= will=20assume=20variable=20pitch=20when=20filling.")=0A=0A(defface=20= sfill-debug-face=20(let=20((spec=20'(:inherit=20default))=0A=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (display=20t))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20`((,display=20.=20,spec)))=0A=20=20"Face=20for=20= highlighting=20sfill=20overlays."=0A=20=20:group=20'sfill)=0A=0A= (define-minor-mode=20sfill-debug-mode=0A=20=20"Toggle=20debug=20mode=20= for=20sfill."=0A=20=20:lighter=20""=0A=20=20(if=20sfill-debug-mode=0A=20=20= =20=20=20=20(set-face-attribute=20'sfill-debug-face=20nil=20:inherit=20= 'highlight)=0A=20=20=20=20(set-face-attribute=20'sfill-debug-face=20nil=20= :inherit=20'default)))=0A=0A(defun=20sfill-insert=20(string)=0A=20=20= "Insert=20STRING=20at=20point=20by=20overlay."=0A=20=20;;=20We=20= shouldn=E2=80=99t=20need=20to=20break=20line=20at=20point-max.=0A=20=20= (if=20(or=20(eq=20(point)=20(point-max)))=0A=20=20=20=20=20=20(error=20= "Cannot=20insert=20at=20the=20end=20of=20visible=20buffer")=0A=20=20=20=20= (let*=20((beg=20(point))=0A=20=20=20=20=20=20=20=20=20=20=20(end=20(1+=20= (point)))=0A=20=20=20=20=20=20=20=20=20=20=20(ov=20(make-overlay=20beg=20= end)))=0A=20=20=20=20=20=20(overlay-put=20ov=20'sfill=20t)=0A=20=20=20=20= =20=20(overlay-put=20ov=20'before-string=20string)=0A=20=20=20=20=20=20= (overlay-put=20ov=20'evaporate=20t)=0A=20=20=20=20=20=20(overlay-put=20= ov=20'face=20'sfill-debug-face))))=0A=0A(defun=20sfill-clear-overlay=20= (beg=20end)=0A=20=20"Clear=20overlays=20that=20`soft-insert'=20made=20= between=20BEG=20and=20END."=0A=20=20(let=20((overlay-list=20(overlays-in=20= beg=20end)))=0A=20=20=20=20(dolist=20(ov=20overlay-list)=0A=20=20=20=20=20= =20(when=20(overlay-get=20ov=20'sfill)=0A=20=20=20=20=20=20=20=20= (delete-overlay=20ov)))))=0A=0A(defun=20sfill-clear-char=20(char=20beg=20= end)=0A=20=20"Remove=20CHAR(string)=20in=20the=20region=20from=20BEG=20= to=20END."=0A=20=20(save-excursion=0A=20=20=20=20(goto-char=20beg)=0A=20=20= =20=20(while=20(re-search-forward=20char=20end=20t)=0A=20=20=20=20=20=20= ;;=20I=20can=20be=20more=20intelligent=20here,=20but=20since=20the=20= break=20point=0A=20=20=20=20=20=20;;=20function=20is=20from=20fill.el,=20= better=20keep=20in=20sync=20with=20it.=0A=20=20=20=20=20=20;;=20(see=20= =E2=80=98fill-move-to-break-point=E2=80=99)=0A=20=20=20=20=20=20(if=20= (and=20(eq=20(char-charset=20(char-before=20(1-=20(point))))=20'ascii)=0A= =09=20=20=20=20=20=20=20(eq=20(char-charset=20(char-after=20(point)))=20= 'ascii))=0A=20=20=20=20=20=20=20=20=20=20(replace-match=20"=20")=0A=20=20= =20=20=20=20=20=20(replace-match=20"")))))=0A=0A(defun=20= sfill-forward-column=20(column)=0A=20=20"Forward=20COLUMN=20columns."=0A=20= =20(while=20(>=3D=20column=200)=0A=20=20=20=20(forward-char)=0A=20=20=20=20= (setq=20column=20(-=20column=20(char-width=20(char-before))))))=0A=0A= (defun=20sfill-forward-column-variable-pitch=20(column=20bound)=0A=20=20= "Forward=20COLUMN=20columns=20in=20variable=20pitch=20environment.=0A= BOUND=20is=20point=20where=20we=20shouldn=E2=80=99t=20go=20beyond."=0A=20= =20;;=20X=20offset=20from=20widow=E2=80=99s=20left=20edge=20in=20pixels.=20= We=20want=20to=20break=0A=20=20;;=20around=20this=20position.=0A=20=20= (let*=20((column-x-pos=20(*=20column=20(window-font-width)))=0A=20=20=20=20= =20=20=20=20=20(initial-y=20(cadr=20(pos-visible-in-window-p=20nil=20nil=20= t))))=0A=20=20=20=20(goto-char=20(min=20(posn-point=20(posn-at-x-y=20= column-x-pos=20initial-y))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20bound))))=0A=0A(defun=20sfill-region=20(beg=20end)=0A=20=20= "Fill=20region=20between=20BEG=20and=20END.=20Assume=20mono=20space."=0A=20= =20(save-excursion=0A=20=20=20=20(sfill-clear-overlay=20beg=20end)=0A=20=20= =20=20(sfill-clear-char=20"\n"=20beg=20end)=0A=20=20=20=20(let=20= (linebeg)=0A=20=20=20=20=20=20(goto-char=20beg)=0A=20=20=20=20=20=20= (while=20(<=20(point)=20end)=0A=20=20=20=20=20=20=20=20(setq=20linebeg=20= (point))=0A=20=20=20=20=20=20=20=20;;=20We=20cannot=20use=20= =E2=80=98move-to-column=E2=80=99=20as=20fill.el=20does.=20Because=20we=0A= =20=20=20=20=20=20=20=20;;=20break=20lines=20with=20overlays,=20so=20if=20= we=20are=20at=20a=20fake=20newline,=0A=20=20=20=20=20=20=20=20;;=20= =E2=80=98move-to-column=E2=80=99=20doesn=E2=80=99t=20really=20go=20= forward.=0A=20=20=20=20=20=20=20=20(if=20sfill-variale-pitch=0A=20=20=20=20= =20=20=20=20=20=20=20=20(progn=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (unless=20(pos-visible-in-window-p)=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(recenter=20nil=20t))=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(sfill-forward-column-variable-pitch=0A=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20sfill-variable-pitch-column=20end))=0A=20=20=20=20=20=20=20=20= =20=20(sfill-forward-column=20sfill-column))=0A=20=20=20=20=20=20=20=20= ;;=20Check=20again=20if=20we=20are=20in=20the=20desired=20range.=0A=20=20= =20=20=20=20=20=20(when=20(<=20(point)=20end)=0A=20=20=20=20=20=20=20=20=20= =20(fill-move-to-break-point=20linebeg)=0A=20=20=20=20=20=20=20=20=20=20= (skip-chars-forward=20"=20\t")=0A=20=20=20=20=20=20=20=20=20=20= (sfill-insert=20"\n"))))))=0A=0A(defun=20sfill-paragraph=20()=0A=20=20= "Fill=20current=20paragraph."=0A=20=20(interactive)=0A=20=20(let=20(beg=20= end)=0A=20=20=20=20(save-excursion=0A=20=20=20=20=20=20= (backward-paragraph)=0A=20=20=20=20=20=20(skip-chars-forward=20"\n")=0A=20= =20=20=20=20=20(setq=20beg=20(point))=0A=20=20=20=20=20=20= (forward-paragraph)=0A=20=20=20=20=20=20(skip-chars-backward=20"\n")=0A=20= =20=20=20=20=20(setq=20end=20(point))=0A=20=20=20=20=20=20(sfill-region=20= beg=20end))))=0A=0A(provide=20'sfill)=0A=0A;;;=20sfill.el=20ends=20here=0A= --Apple-Mail=_AB90B314-7BE2-4F97-A872-ED36A44F9AB1 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii Yuan --Apple-Mail=_AB90B314-7BE2-4F97-A872-ED36A44F9AB1--