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: Wed, 17 Dec 2014 12:31:55 -0500 Message-ID: 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> Mime-Version: 1.0 (Mac OS X Mail 8.1 \(1993\)) Content-Type: multipart/signed; boundary="Apple-Mail=_47C53A4C-F1BB-4931-8119-4520D2F8610C"; protocol="application/pgp-signature"; micalg=pgp-sha1 Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:54359) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y1IST-0000x5-62 for emacs-orgmode@gnu.org; Wed, 17 Dec 2014 12:32:27 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Y1ISN-0003Wb-0e for emacs-orgmode@gnu.org; Wed, 17 Dec 2014 12:32:20 -0500 Received: from st11p01mm-asmtp001.mac.com ([17.172.204.239]:39452) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Y1ISM-0003VX-S7 for emacs-orgmode@gnu.org; Wed, 17 Dec 2014 12:32:14 -0500 Received: from [172.30.0.157] (unknown [75.115.6.171]) by st11p01mm-asmtp001.mac.com (Oracle Communications Messaging Server 7.0.5.33.0 64bit (built Aug 27 2014)) with ESMTPSA id <0NGQ009ZTM1LOW10@st11p01mm-asmtp001.mac.com> for emacs-orgmode@gnu.org; Wed, 17 Dec 2014 17:32:11 +0000 (GMT) In-reply-to: <87ppbm6tgl.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=_47C53A4C-F1BB-4931-8119-4520D2F8610C Content-Type: multipart/mixed; boundary="Apple-Mail=_DBAA5406-3E48-43A2-8EFB-F749180A8550" --Apple-Mail=_DBAA5406-3E48-43A2-8EFB-F749180A8550 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Dec 14, 2014, at 12:18 PM, Nicolas Goaziou = wrote: >> As I said above, you=E2=80=99ve convinced me that ?f ?F is the right = solution. >=20 > Fair enough. Let's settle on that, then. Here is the new patch. It extends org-table-sort-lines to allow a user = to specify custom extraction and comparison functions using the ?f ?F = sorting type as in org-sort-list. The user can call org-table-sort-lines programmatically specifying a = SORTING-TYPE of ?f or ?F and provide custom extraction and comparison = functions. If the user calls org-table-sort lines interactively and = specifies ?f or ?F, org-do-sort will prompt for a custom extraction = function. The comparison will be either string or numeric depending on = the type of the first extracted key. --Apple-Mail=_DBAA5406-3E48-43A2-8EFB-F749180A8550 Content-Disposition: attachment; filename=0001-org.el-Implement-user-specified-sorting-functions.patch Content-Type: application/octet-stream; name="0001-org.el-Implement-user-specified-sorting-functions.patch" Content-Transfer-Encoding: quoted-printable =46rom=2053f1929b7a8c1b98230d60e5313e7550ab3d1b13=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Jon=20Snader=20=0ADate:=20= Wed,=2017=20Dec=202014=2011:52:23=20-0500=0ASubject:=20[PATCH]=20org.el:=20= Implement=20user=20specified=20sorting=20functions=0A=0A*=20lisp/org.el=20= (org-do-sort):=20Implemented=20the=20ability=20for=20the=20user=0Ato=20= specify=20custom=20extraction=20and=20comparison=20functions.=09Updated=0A= the=20DOC=20string.=0A=0A*=20lisp/org-table.el=20(org-table-sort-lines):=20= Added=20GETKEY-FUNC=20and=0ACOMPARE-FUNC=20as=20optional=20arguments=20= and=20passed=20them=20to=0A`org-do-sort'.=09Updated=20DOC=20string=20to=20= reflect=20the=20new=0Afunctionality.=0A=0A*=20doc/org.texi=20(Structure=20= editing):=20Document=20the=20ability=20for=20users=0Ato=20specify=20= their=20own=20extraction=20and=20comparison=20functions.=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|=2036=20= ++++++++++++++++++++++++++++++------=0A=203=20files=20changed,=2045=20= insertions(+),=2012=20deletions(-)=0A=0Adiff=20--git=20a/doc/org.texi=20= b/doc/org.texi=0Aindex=20d617259..f56e824=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=20= reverse=0A+order.=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=0A+be=20= 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=2006a8ab7..9048ac9=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= letter=20indicate=20that=20sorting=0A+should=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= bed5cb9..23f5b07=20100755=0A---=20a/lisp/org.el=0A+++=20b/lisp/org.el=0A= @@=20-9051,21=20+9051,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=20extract-string-p)=0A=20=20=20=20=20= ;;=20Define=20the=20appropriate=20functions=0A=20=20=20=20=20(cond=0A=20=20= =20=20=20=20((=3D=20dcst=20?n)=0A@@=20-9075,7=20+9081,7=20@@=20If=20= WITH-CASE=20is=20non-nil,=20the=20sorting=20will=20be=20case-sensitive."=0A= =20=20=20=20=20=20=20(setq=20extractfun=20(if=20with-case=20(lambda(x)=20= (org-sort-remove-invisible=20x))=0A=20=09=09=09=20(lambda(x)=20(downcase=20= (org-sort-remove-invisible=20x))))=0A=20=09=20=20=20=20comparefun=20(if=20= (=3D=20dcst=20sorting-type)=0A-=09=09=09=20=20=20'string<=0A+=09=09=09=20= =20=20#'string<=0A=20=09=09=09=20(lambda=20(a=20b)=20(and=20(not=20= (string<=20a=20b))=0A=20=09=09=09=09=09=20=20=20=20(not=20(string=3D=20a=20= b)))))))=0A=20=20=20=20=20=20((=3D=20dcst=20?t)=0A@@=20-9089,6=20= +9095,24=20@@=20If=20WITH-CASE=20is=20non-nil,=20the=20sorting=20will=20= be=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=200)))=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=20= tempfun=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(setq=20= extract-string-p=20(stringp=20(funcall=20tempfun=20(caar=20table))))=0A+=20= =20=20=20=20=20(setq=20extractfun=20(if=20(and=20extract-string-p=20(not=20= with-case))=0A+=09=09=09=20=20=20(lambda=20(x)=20(downcase=20(funcall=20= tempfun=20x)))=0A+=09=09=09=20tempfun))=0A+=20=20=20=20=20=20(setq=20= comparefun=20(or=20compare-func=0A+=09=09=09=20=20=20(if=20= extract-string-p=20=0A+=09=09=09=20=20=20=20=20=20=20(if=20(=3D=20= sorting-type=20?f)=0A+=09=09=09=09=20=20=20#'string<=0A+=09=09=09=09=20= (lambda=20(a=20b)=20(and=20(not=20(string<=20a=20b))=0A+=09=09=09=09=09=09= =20=20=20=20(not=20(string=3D=20a=20b)))))=0A+=09=09=09=20=20=20=20=20= (if=20(=3D=20sorting-type=20?f)=0A+=09=09=09=09=20#'<=0A+=09=09=09=20=20=20= =20=20=20=20#'>)))))=0A=20=20=20=20=20=20(t=20(error=20"Invalid=20= sorting=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=0A1.9.3=20(Apple=20Git-50)=0A=0A= --Apple-Mail=_DBAA5406-3E48-43A2-8EFB-F749180A8550-- --Apple-Mail=_47C53A4C-F1BB-4931-8119-4520D2F8610C 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 iQIcBAEBAgAGBQJUkb4UAAoJEO+a/ARTO0yyk90P/AksF6BSbqsoziRR9wHJK28K t7sss61y+M28D4CwgOCm1Vkexw3XL/CxIcxu20NEpzjVbBZIodGH0j3UgpBPzDv/ WSviVn6vehrSvIhMSqj1/mXw1L6uiOe9QfM4rEK3/VYCwZIX6JUc4m4FwXr8KKkz G6TOoOUuA98I369/hYG1dJ8ojwONOWNL0dpZE49SQ7u49aJS9OpC+F6eAPZsb4Dl KXe9vJrdZS7+ISzjCNd6hbf9YhDdaAud+9MiVHQjOhOAl/z/K5GypksLJR2fjiNR ZT6VkLIjv7vWEP+1oyU/yNZ92QLrtD+qZMBTx1j6kNWG55zuVFstHos+ZPMLguvI AsVvyZvhtwzkFp4ydw3A4SuzoZdFfABGx/hDNbkBbeSx6capE/jrDQ++YMi2CXVx yBUWi86pjET8IvtocIGIHAI/XywBVCO8E5nIOfrDIQPXPxtXFlCa3APSLmYssJGb 8J5C0oztO5s/vIc18NBfI/pMAPtVp4OPEVoVD8bNRXy9F7UMWupjLsKvwZ2MdAKc munxdkzmWMwhbXEAQbkC+BDV/YBd94FxeL30WQdwsqPUiWepxX1gzOMv1cLaiuG0 mAWkR1X5InQrKl+e1mhIdNjiX3hB+KEEviaygsL2EMQBmJeAEgcPU17IDDr2G+BF UJW7wTJtYgejnfK2rmLh =iRec -----END PGP SIGNATURE----- --Apple-Mail=_47C53A4C-F1BB-4931-8119-4520D2F8610C--