From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jon Snader Subject: Re: Patch to implement sorting Org tables by IP address Date: Sat, 20 Dec 2014 13:40:29 -0500 Message-ID: <130E330E-9A74-40DB-AAF1-B5368996CD2B@mac.com> References: <87r3w4a326.fsf@nicolasgoaziou.fr> <87tx0z8vxw.fsf@nicolasgoaziou.fr> <42DDD6AD-8F6F-4F85-840B-4C3946AD3C55@mac.com> <87oar78ro1.fsf@nicolasgoaziou.fr> <8C2CF3B2-399D-4944-8CE9-D486EA1A0985@mac.com> <87bnn78apu.fsf@nicolasgoaziou.fr> <2217AFF8-7135-4EAC-A189-8152FDDE52F9@mac.com> <87tx0y79st.fsf@nicolasgoaziou.fr> <63EA1170-B4E2-4CB8-95CD-77AF7AA117C3@mac.com> <87ppbm6tgl.fsf@nicolasgoaziou.fr> <87vbl6zg7f.fsf@nicolasgoaziou.fr> Mime-Version: 1.0 (Mac OS X Mail 8.1 \(1993\)) Content-Type: multipart/signed; boundary="Apple-Mail=_90735BF1-4D8D-4824-A577-56F9E6AD9ED0"; protocol="application/pgp-signature"; micalg=pgp-sha1 Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:39466) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y2OxN-000166-LL for emacs-orgmode@gnu.org; Sat, 20 Dec 2014 13:40:55 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y2OxH-0003ok-Hx for emacs-orgmode@gnu.org; Sat, 20 Dec 2014 13:40:49 -0500 Received: from st11p01mm-asmtpout002.mac.com ([17.172.204.237]:62128 helo=st11p01mm-asmtp002.mac.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y2OxH-0003oK-B2 for emacs-orgmode@gnu.org; Sat, 20 Dec 2014 13:40:43 -0500 Received: from [172.30.0.157] (75-115-6-171.res.bhn.net [75.115.6.171]) by st11p01mm-asmtp002.mac.com (Oracle Communications Messaging Server 7.0.5.33.0 64bit (built Aug 27 2014)) with ESMTPSA id <0NGW0076297PCH00@st11p01mm-asmtp002.mac.com> for emacs-orgmode@gnu.org; Sat, 20 Dec 2014 18:40:39 +0000 (GMT) In-reply-to: <87vbl6zg7f.fsf@nicolasgoaziou.fr> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Nicolas Goaziou Cc: emacs-orgmode@gnu.org --Apple-Mail=_90735BF1-4D8D-4824-A577-56F9E6AD9ED0 Content-Type: multipart/alternative; boundary="Apple-Mail=_4A7B518A-1A2F-429A-9506-D3168436EF9D" --Apple-Mail=_4A7B518A-1A2F-429A-9506-D3168436EF9D Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On Dec 20, 2014, at 6:57 AM, Nicolas Goaziou = wrote: >> + extractfun comparefun tempfun extract-string-p) >=20 > EXTRACT-STRING-P, and possibly TEMPFUN, are bound too early. See = below. I moved EXTRACT-STRING-P to a lower let but TEMPFUN has to be available = to the call to sort so I left it in the outer let. > I suggest something like >=20 > (let* ((tempfun (or getkey-func > (intern ...))) > (extract-string-p (stringp (funcall tempfun (caar table))))) > (setq extractfun (if (and extract-string-p (not with-case)) > `(lambda (x) (downcase (funcall ',tempfun x))) > tempfun)) > (setq comparefun > (cond (compare-func) > (extract-string-p (if (=3D sorting-type ?f) #'string< = #'org-string>)) > ((=3D sorting-type ?f) #'<) > (t #'>)))) I followed this suggestion modulo leaving TEMPFUN in the outer let. Thanks for your suggestions. The attached patch was against the latest master branch at the time I = generated it. --Apple-Mail=_4A7B518A-1A2F-429A-9506-D3168436EF9D Content-Type: multipart/mixed; boundary="Apple-Mail=_8D3B98F2-E472-4CF0-90FB-3F943AE7FAB1" --Apple-Mail=_8D3B98F2-E472-4CF0-90FB-3F943AE7FAB1 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii
On Dec 20, 2014, at 6:57 AM, Nicolas Goaziou <mail@nicolasgoaziou.fr> wrote:

+ extractfun comparefun tempfun extract-string-p)

EXTRACT-STRING-P, and = possibly TEMPFUN, are bound too early. See below.

I moved = EXTRACT-STRING-P to a lower let but TEMPFUN has to be available to the = call to sort so I left it in the outer let.

I suggest something = like

 (let* ((tempfun (or = getkey-func
          &nb= sp;          (intern = ...)))
        (extract-string= -p (stringp (funcall tempfun (caar table)))))
   (setq extractfun (if (and = extract-string-p (not with-case))
          &nb= sp;            = ; `(lambda (x) (downcase (funcall ',tempfun x)))
          &nb= sp;           tempf= un))
   (setq = comparefun
        (cond = (compare-func)
          &nb= sp;   (extract-string-p (if (=3D sorting-type ?f) = #'string< #'org-string>))
          &nb= sp;   ((=3D sorting-type ?f) #'<)
          &nb= sp;   (t #'>))))

I followed this suggestion modulo leaving TEMPFUN = in the outer let.

Thanks for your = suggestions.

The attached patch was = against the latest master branch at the time I generated = it.

= --Apple-Mail=_8D3B98F2-E472-4CF0-90FB-3F943AE7FAB1 Content-Disposition: attachment; filename=0001-org.el-Implement-user-defined-table-sorting.patch Content-Type: application/octet-stream; name="0001-org.el-Implement-user-defined-table-sorting.patch" Content-Transfer-Encoding: quoted-printable =46rom=209d526679cd958b46605c60d092062cf6db441cb3=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Jon=20Snader=20=0ADate:=20= Sat,=2020=20Dec=202014=2013:13:17=20-0500=0ASubject:=20[PATCH]=20org.el:=20= Implement=20user-defined=20table=20sorting=0A=0A*=20lisp/org.el=20= (org-do-sort):=20Implement=20the=20?f=20and=20?F=20sorting=20options=0A=20= =20to=20allow=20user-defined=20table=20sorting.=20=20Update=20the=20DOC=20= string.=0A=0A*=20lisp/org-table=20(org-table-sort-lines):=20Add=20the=20= GETKEY-FUNC=20and=0A=20=20COMPARE-FUNC=20optional=20parameters=20and=20= pass=20them=20to=20the=20call=20to=0A=20=20`org-do-sort'.=20=20Update=20= the=20DOC=20string.=0A=0A*=20doc/org.texi=20(org-table-sort-lines):=20= Update=20documentation=20to=20reflect=0A=20=20the=20addition=20of=20the=20= ?f=20and=20?F=20options.=0A=0AThis=20patch=20implements=20user-defined=20= extraction=20and=20comparison=20functions=0Afor=20table=20sorting.=20=20= Thanks=20to=20Nicolas=20Goaziou=20for=20helpful=20suggestions.=0A=0AThis=20= patch=20was=20discussed=20on=20the=20Org=20Mode=20mailing=20list:=0A= http://article.gmane.org/gmane.emacs.orgmode/93334=0A---=0A=20= doc/org.texi=20=20=20=20=20=20|=20=206=20++++--=0A=20lisp/org-table.el=20= |=2015=20+++++++++++----=0A=20lisp/org.el=20=20=20=20=20=20=20|=2035=20= +++++++++++++++++++++++++++++------=0A=203=20files=20changed,=2044=20= insertions(+),=2012=20deletions(-)=0A=0Adiff=20--git=20a/doc/org.texi=20= b/doc/org.texi=0Aindex=207c464ca..33a6a0d=20100644=0A---=20= a/doc/org.texi=0A+++=20b/doc/org.texi=0A@@=20-2205,8=20+2205,10=20@@=20= point=20is=20before=20the=20first=20column,=20you=20will=20be=20prompted=20= for=20the=20sorting=0A=20column.=20=20If=20there=20is=20an=20active=20= region,=20the=20mark=20specifies=20the=20first=20line=0A=20and=20the=20= sorting=20column,=20while=20point=20should=20be=20in=20the=20last=20line=20= to=20be=0A=20included=20into=20the=20sorting.=20=20The=20command=20= prompts=20for=20the=20sorting=20type=0A-(alphabetically,=20numerically,=20= or=20by=20time).=20=20When=20called=20with=20a=20prefix=0A-argument,=20= alphabetic=20sorting=20will=20be=20case-sensitive.=0A+(alphabetically,=20= numerically,=20or=20by=20time).=20=20You=20can=20sort=20in=20normal=20or=0A= +reverse=20order.=20=20You=20can=20also=20supply=20your=20own=20key=20= extraction=20and=20comparison=0A+functions.=20=20When=20called=20with=20= a=20prefix=20argument,=20alphabetic=20sorting=20will=20be=0A= +case-sensitive.=0A=20=0A=20@tsubheading{Regions}=0A=20@orgcmd{C-c=20C-x=20= M-w,org-table-copy-region}=0Adiff=20--git=20a/lisp/org-table.el=20= b/lisp/org-table.el=0Aindex=20fa59113..9941160=20100644=0A---=20= a/lisp/org-table.el=0A+++=20b/lisp/org-table.el=0A@@=20-1657,7=20+1657,7=20= @@=20In=20particular,=20this=20does=20handle=20wide=20and=20invisible=20= characters."=0A=20=09=09=09=20=20=20=20=20=20dline=20-1=20dline))))=0A=20= =0A=20;;;###autoload=0A-(defun=20org-table-sort-lines=20(with-case=20= &optional=20sorting-type)=0A+(defun=20org-table-sort-lines=20(with-case=20= &optional=20sorting-type=20getkey-func=20compare-func)=0A=20=20=20"Sort=20= table=20lines=20according=20to=20the=20column=20at=20point.=0A=20=0A=20= The=20position=20of=20point=20indicates=20the=20column=20to=20be=20used=20= for=0A@@=20-1677,8=20+1677,15=20@@=20With=20prefix=20argument=20= WITH-CASE,=20alphabetic=20sorting=20will=20be=20case-sensitive.=0A=20=0A=20= If=20SORTING-TYPE=20is=20specified=20when=20this=20function=20is=20= called=20from=20a=20Lisp=0A=20program,=20no=20prompting=20will=20take=20= place.=20=20SORTING-TYPE=20must=20be=20a=20character,=0A-any=20of=20(?a=20= ?A=20?n=20?N=20?t=20?T)=20where=20the=20capital=20letter=20indicate=20= that=20sorting=0A-should=20be=20done=20in=20reverse=20order."=0A+any=20= of=20(?a=20?A=20?n=20?N=20?t=20?T=20?f=20?F)=20where=20the=20capital=20= letters=20indicate=20that=0A+sorting=20should=20be=20done=20in=20reverse=20= order.=0A+=0A+If=20the=20SORTING-TYPE=20is=20?f=20or=20?F,=20then=20= GETKEY-FUNC=20specifies=0A+a=20function=20to=20be=20called=20to=20= extract=20the=20key.=20=20It=20must=20return=20either=0A+a=20string=20or=20= a=20number=20that=20should=20serve=20as=20the=20sorting=20key=20for=20= that=0A+row.=20=20It=20will=20then=20use=20COMPARE-FUNC=20to=20compare=20= entries.=20=20If=20GETKEY-FUNC=0A+is=20specified=20interactively,=20the=20= comparison=20will=20be=20either=20a=20string=20or=0A+numeric=20compare=20= based=20on=20the=20type=20of=20the=20first=20key=20in=20the=20table."=0A=20= =20=20(interactive=20"P")=0A=20=20=20(let*=20((thisline=20= (org-current-line))=0A=20=09=20(thiscol=20(org-table-current-column))=0A= @@=20-1730,7=20+1737,7=20@@=20should=20be=20done=20in=20reverse=20= order."=0A=20=09=09=09=09=09(org-split-string=20x=20"[=20\t]*|[=20= \t]*")))=0A=20=09=09=09=09=20=20x))=0A=20=09=09=20=20=20=20=20=20= (org-split-string=20(buffer-substring=20beg=20end)=20"\n")))=0A-=20=20=20= =20(setq=20lns=20(org-do-sort=20lns=20"Table"=20with-case=20= sorting-type))=0A+=20=20=20=20(setq=20lns=20(org-do-sort=20lns=20"Table"=20= with-case=20sorting-type=20getkey-func=20compare-func))=0A=20=20=20=20=20= (when=20org-table-overlay-coordinates=0A=20=20=20=20=20=20=20= (org-table-toggle-coordinate-overlays))=0A=20=20=20=20=20(delete-region=20= beg=20end)=0Adiff=20--git=20a/lisp/org.el=20b/lisp/org.el=0Aindex=20= 1383d76..29439d2=20100755=0A---=20a/lisp/org.el=0A+++=20b/lisp/org.el=0A= @@=20-9057,21=20+9057,27=20@@=20When=20sorting=20is=20done,=20call=20= `org-after-sorting-entries-or-items-hook'."=0A=20=09(move-marker=20= org-clock-marker=20(point))))=0A=20=20=20=20=20(message=20"Sorting=20= entries...done")))=0A=20=0A-(defun=20org-do-sort=20(table=20what=20= &optional=20with-case=20sorting-type)=0A+(defun=20org-do-sort=20(table=20= what=20&optional=20with-case=20sorting-type=20getkey-func=20= compare-func)=0A=20=20=20"Sort=20TABLE=20of=20WHAT=20according=20to=20= SORTING-TYPE.=0A=20The=20user=20will=20be=20prompted=20for=20the=20= SORTING-TYPE=20if=20the=20call=20to=20this=0A=20function=20does=20not=20= specify=20it.=0A=20WHAT=20is=20only=20for=20the=20prompt,=20to=20= indicate=20what=20is=20being=20sorted.=0A=20The=20sorting=20key=20will=20= be=20extracted=20from=20the=20car=20of=20the=20elements=20of=0A-the=20= table.=0A-If=20WITH-CASE=20is=20non-nil,=20the=20sorting=20will=20be=20= case-sensitive."=0A+the=20table.=20If=20WITH-CASE=20is=20non-nil,=20the=20= sorting=20will=20be=20case-sensitive.=0A+=0A+If=20the=20SORTING-TYPE=20= is=20?f=20or=20?F,=20then=20GETKEY-FUNC=20specifies=0A+a=20function=20to=20= be=20called=20to=20extract=20the=20key.=20=20It=20must=20return=20either=0A= +a=20string=20or=20a=20number=20that=20should=20serve=20as=20the=20= sorting=20key=20for=20that=0A+row.=20=20It=20will=20then=20use=20= COMPARE-FUNC=20to=20compare=20entries.=20=20If=20GETKEY-FUNC=0A+is=20= specified=20interactively,=20the=20comparison=20will=20be=20either=20a=20= string=20or=0A+numeric=20compare=20based=20on=20the=20type=20of=20the=20= first=20key=20in=20the=20table."=0A=20=20=20(unless=20sorting-type=0A=20=20= =20=20=20(message=0A-=20=20=20=20=20"Sort=20%s:=20[a]lphabetic,=20= [n]umeric,=20[t]ime.=20=20A/N/T=20means=20reversed:"=0A+=20=20=20=20=20= "Sort=20%s:=20[a]lphabetic,=20[n]umeric,=20[t]ime,=20[f]unc.=20=20= A/N/T/F=20means=20reversed:"=0A=20=20=20=20=20=20what)=0A=20=20=20=20=20= (setq=20sorting-type=20(read-char-exclusive)))=0A=20=20=20(let=20((dcst=20= (downcase=20sorting-type))=0A-=09extractfun=20comparefun)=0A+=09= extractfun=20comparefun=20tempfun)=0A=20=20=20=20=20;;=20Define=20the=20= appropriate=20functions=0A=20=20=20=20=20(cond=0A=20=20=20=20=20=20((=3D=20= dcst=20?n)=0A@@=20-9095,13=20+9101,30=20@@=20If=20WITH-CASE=20is=20= non-nil,=20the=20sorting=20will=20be=20case-sensitive."=0A=20=09=09=20=20= =20=20=20(org-hh:mm-string-to-minutes=20x))=0A=20=09=09=20=20=20=20(t=20= 0)))=0A=20=09=20=20=20=20comparefun=20(if=20(=3D=20dcst=20sorting-type)=20= '<=20'>)))=0A+=20=20=20=20=20((=3D=20dcst=20?f)=0A+=20=20=20=20=20=20= (setq=20tempfun=20(or=20getkey-func=0A+=09=09=09(intern=20= (org-icompleting-read=0A+=09=09=09=09=20"Sort=20using=20function:=20"=0A= +=09=09=09=09=20obarray=20#'fboundp=20t=20nil=20nil))))=0A+=20=20=20=20=20= =20(let*=20((extract-string-p=20(stringp=20(funcall=20tempfun=20(caar=20= table)))))=0A+=09(setq=20extractfun=20(if=20(and=20extract-string-p=20= (not=20with-case))=0A+=09=09=09=20=20=20=20=20(lambda=20(x)=20(downcase=20= (funcall=20tempfun=20x)))=0A+=09=09=09=20=20=20tempfun))=0A+=09(setq=20= comparefun=20(cond=20(compare-func)=0A+=09=09=09=20=20=20=20=20=20=20= (extract-string-p=0A+=09=09=09=09(if=20(=3D=20sorting-type=20?f)=0A+=09=09= =09=09=20=20=20=20#'string<=0A+=09=09=09=09=20=20#'org-string>))=0A+=09=09= =09=20=20=20=20=20=20=20(t=09;numeric=0A+=09=09=09=09(if=20(=3D=20= sorting-type=20?f)=0A+=09=09=09=09=20=20=20=20#'<=0A+=09=09=09=09=20=20= #'>))))))=0A=20=20=20=20=20=20(t=20(error=20"Invalid=20sorting=20type=20= `%c'"=20sorting-type)))=0A=20=0A=20=20=20=20=20(sort=20(mapcar=20(lambda=20= (x)=20(cons=20(funcall=20extractfun=20(car=20x))=20(cdr=20x)))=0A=20=09=09= =20=20table)=0A=20=09=20=20(lambda=20(a=20b)=20(funcall=20comparefun=20= (car=20a)=20(car=20b))))))=0A=20=0A-=0A=20;;;=20The=20orgstruct=20minor=20= mode=0A=20=0A=20;;=20Define=20a=20minor=20mode=20which=20can=20be=20used=20= in=20other=20modes=20in=20order=20to=0A--=20=0A1.9.3=20(Apple=20Git-50)=0A= =0A= --Apple-Mail=_8D3B98F2-E472-4CF0-90FB-3F943AE7FAB1 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii

--Apple-Mail=_8D3B98F2-E472-4CF0-90FB-3F943AE7FAB1-- --Apple-Mail=_4A7B518A-1A2F-429A-9506-D3168436EF9D-- --Apple-Mail=_90735BF1-4D8D-4824-A577-56F9E6AD9ED0 Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=signature.asc Content-Type: application/pgp-signature; name=signature.asc Content-Description: Message signed with OpenPGP using GPGMail -----BEGIN PGP SIGNATURE----- Comment: GPGTools - http://gpgtools.org iQIcBAEBAgAGBQJUlcKlAAoJEO+a/ARTO0yyjXUP/0okx1TnDNDMSPgxkBuZWKT6 kxb82qHojwLCdbWJhAwww3oKYPgyb8akXapjf798yse3AqEypneProK3Oyapl9hV oGL9Sr9c2kUDETwBlVHKoc7cm/FPHrPhe5KY6UPLEIQUUqlWw3nYCoBTbk50hCia ZscXZhvs2J6AKYaNYIs6cr/ER+sE6IuJfM5k7rJoE5ZveEDlxwWUDkbPQ5odKih0 HY57QV/fFU2e403oLxKwVGj8c+tP2o+LQfZY8tTp7hlIVnqjfzj1VAr0pCO9OOmG 8k89kRpp4Ac63LpamVk5pYZTi4XSA5P6ZS9w5DErbufA4uMG2acRGS86dJ3Wrs12 qlEqi+B8Z5qkChh5lqDmQUe3f2uQB3MoqYJfG0VSewKypvdKns5vhm5u8DU1mZ+v 06cLl/qVHfMzQpa97aEcauYUaLl0+VkQ0UoB8QG/lVZeoS25/mt0vFsO0Yd7n/eR hz1yHReeESn7W6TKeAdP9p+wj/1xMID23lpPvLy3Slu7vQa1f7DNT7eMUugvHiCT BoHVqL/BygARkWJDvvP5yRScfOZ2q0vYYSNMOwmQ5MsHQ4D8eyVcbkQ+7eHaYYUR 99RN+OATeq6pSpMTwzvJQoqWMqbpMOlb92y3pHkF6Erd8YAWHMcrFlQTURK+stkp qHPL7V+CBjV5MKXIc9IF =3Hvs -----END PGP SIGNATURE----- --Apple-Mail=_90735BF1-4D8D-4824-A577-56F9E6AD9ED0--