emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
To: "Gustav Wikström" <gustav.erik@gmail.com>
Cc: Org Mode List <emacs-orgmode@gnu.org>
Subject: Re: [RFC] [PATCH] Changes to Tag groups - allow nesting and regexps
Date: Tue, 24 Feb 2015 17:43:06 +0100	[thread overview]
Message-ID: <87a90345wl.fsf@nicolasgoaziou.fr> (raw)
In-Reply-To: <CA+SyOP-DVW8HFprsjV7iHqvaYg9N+eXE6nrmKhjW0d3HdBJ42w@mail.gmail.com> ("Gustav \=\?utf-8\?Q\?Wikstr\=C3\=B6m\=22's\?\= message of "Thu, 19 Feb 2015 21:00:27 +0100")

Gustav Wikström <gustav.erik@gmail.com> writes:

> Hi again! The FSA-assignment is now complete. New patches are attached
> and comments below.

OK. I updated list of contributors accordingly.

> The reason for the use of [ ] is because { } already has another purpose
> - it is used to make the tags within { } exclusive.
>
> this example
>
> ,----
> | #+TAGS: { group : include1 include2 }
> `----
>
> will only allow one of the tags on any specific headline. [ ] solves
> this. Note that grouptags doesn't care if { } or [ ] is used. The only
> difference is the exclusiveness. I.e both
>
> ,----
> | #+TAGS: [ group : include1 include2 ]
> | #+TAGS: { group : include1 include2 }
> `----
>
> will work. With some limitations on the second example due to the way {
> } works since before.

OK, but is it really needed? What is the point of having two tags of the
same group (or, if we consider nested group tags, the same set of
siblings) at the same time?

> Subject: [PATCH 1/3] org: Grouptags not unique and can contain regexp
>
> * lisp/org.el (org--setup-process-tags):
>   (org-fast-tag-selection):
>
>   Grouptags had to previously be defined with { }. This syntax is
>   already used for exclusive tags and Grouptags need their own,
>   non-exclusive syntax. This behaviour is achieved with [ ]
>   instead. Note: { } can still be used also for Grouptags but then
>   only one of the given tags can be used on the headline at the same
>   time. Example:

You need to separate sentences with two spaces.  Also, commit messages
need to be formatted this way

 * lisp/org.el (function): Small description.
   (other function): Small description.

 Long explanations.

> -	   (org-re "\\`\\([[:alnum:]_@#%]+\\)\\(?:(\\(.\\))\\)?\\'") e)
> +	   (org-re (concat "\\`\\([[:alnum:]_@#%]+"
> +			   "\\|{.+}\\)" ; regular expression
                               ^^^
I think it should be non-greedy above.

> +	     (taggroups (or org-tag-groups-alist-for-agenda org-tag-groups-alist))
> +	     (taggroups (if downcased (mapcar (lambda(tg) (mapcar 'downcase tg)) taggroups) taggroups))

Nitpick:

  "(lambda (tg) ... #'downcase ...)"

Also it should be wrapped at 80 characters.

> +	     (taggroups-keys (mapcar 'car taggroups))

Nitpick: (mapcar #'car taggroups)

> +	     (return-match (if downcased (downcase match) match))
> +	     (count 0)
> +	     regexps-in-match tags-in-group regexp-in-group regexp-in-group-escaped)
>  	;; @ and _ are allowed as word-components in tags
>  	(modify-syntax-entry ?@ "w" stable)
>  	(modify-syntax-entry ?_ "w" stable)
> -	(while (and tml
> +	;; Temporarily replace regexp-expressions in the match-expression

Nitpick: missing full stop.

> +	(while (string-match "{.+?}" return-match)
> +	  (setq count (1+ count))

Nitpick:

  (incf count)

> +	  (setq regexps-in-match (cons (match-string 0 return-match) regexps-in-match))

Nitpick:

  (push (match-string 0 return-match) regexps-in-match)

> +	  (setq return-match (replace-match (concat "<" (number-to-string count) ">") t nil return-match)))

Nitpick:

  (format "<%d>" count)

> +	      ; Filter tag-regexps from tags
> +	      (setq regexp-in-group-escaped (delq nil (mapcar (lambda (x)
> +								(if (stringp x)
> +								    (and (string-prefix-p "{" x)
> +									 (string-suffix-p "}" x)
> +									 x)
> +								  x)) tags-in-group))

We cannot use `string-prefix-p' and `string-suffix-p' due to backward
compatibility. The former will be fine in Org 8.4 (it was introduced in
Emacs 24.1), but the latter comes from Emacs 24.4.

You can use (equal (substring x ... ...) ...) instead.

Be careful about line width, too.

> +		    tags-in-group (delq nil (mapcar (lambda (x)
> +						      (if (stringp x)
> +							  (and (not (string-prefix-p "{" x))
> +							       (not (string-suffix-p "}" x))
> +							       x)
> +							x)) tags-in-group)))

Ditto.

> +	      ; If single-as-list, do no more in the while-loop...
> +	      (if (not single-as-list)
> +		  (progn
> +		    (if regexp-in-group
> +			(setq regexp-in-group (concat "\\|" (mapconcat 'identity regexp-in-group "\\|"))))
> +		    (setq tags-in-group (concat dir "{\\<" (regexp-opt tags-in-group) regexp-in-group  "\\>}"))
> +		    (if (stringp tags-in-group) (org-add-props tags-in-group '(grouptag t)))

Nitpick: (when (stringp tags-in-group) ...)

> +		    (setq return-match (replace-match tags-in-group t t return-match)))
> + 		(setq tags-in-group (append regexp-in-group-escaped tags-in-group))))
> + 	    (setq taggroups-keys (delete tag taggroups-keys))))

I think you can refactor this part into a `cond'.

  (cond (single-as-list (setq taggroups-keys (delete tag taggroups-keys)))
        (regexp-in-group (setq regexp-in-group ...))
        (t (setq tags-in-group ....)
           (when (stringp tags-in-group) ...)
           (setq return match ...))

> +	;; Add the regular expressions back into the match-expression again

See above.

> +	(while regexps-in-match
> +	  (setq return-match (replace-regexp-in-string (concat "<" (number-to-string count) ">")

See above.

> +	 ((equal (car e) :startgrouptags)

`eq' instead of `equal'.

> +	  (setq intaggroup t)
> +	  (when (not (= cnt 0))

(unless (zerop cnt) ...)

or

(unless (= cnt 0) ...)

> +	 ((equal (car e) :endgrouptags)

See above.

>  	  (when (not (= cnt 0))

Ditto.

> +	  (if (and (= cnt 0) (not ingroup) (not intaggroup)) (insert " "))

`when' instead of `if'.

> +	    (if (or ingroup intaggroup) (insert " "))

Ditto.

> Subject: [PATCH 2/3] org-agenda: Filtering in the agenda on grouptags

[...]

> +      (while (not (member char (append '(?\t ?\r ?/ ?. ?\ ?q)
> +				       (string-to-list tag-chars))))

Nitpick: `memq' instead of `member'.

> +	(cond ((equal char ?-) (setq exclude t))
> +	      ((equal char ?+) (setq exclude nil)))))

Nitpick: `eq' instead of `equal'.

> +     ((equal char ?q)) ;If q, abort (even if there is a q-key for a tag...)

Ditto.

> -(defun org-agenda-filter-make-matcher (filter type)
> +(defun org-agenda-filter-make-matcher (filter type &optional expand)
>    "Create the form that tests a line for agenda filter."

You need to explain arguments (data type, purpose) in the docstring.

> +      ;(if expand (setq filter (org-agenda-filter-expand-tags filter)))

This line should be removed.

> +	(let ((op (string-to-char x)))
> +	  (if expand (setq x (org-agenda-filter-expand-tags (list x) t))
> +	    (setq x (list x)))
> +	  (setq f1 (org-agenda-filter-make-matcher-tag-exp x op))
> +	  (push f1 f))))

Is it useful to bind OP since you use it only once anyway?

> +(defun org-agenda-filter-make-matcher-tag-exp (tags op)

Missing docstring.

> +  (let (f f1) ;f = return expression. f1 = working-area
> +    (dolist (x tags)
> +      (let* ((tag (substring x 1))
> +	     (isregexp (and (string-prefix-p "{" tag)
> +			    (string-suffix-p "}" tag)))

See above.

> +	     regexp)
> +	(cond
> +	 (isregexp
> +	  (setq regexp (substring tag 1 -1))
> +	  (setq f1 (list 'string-match regexp '(apply 'concat  tags))))

Spurious space.

> +	 (t
> +	  (setq f1 (list 'member (downcase tag) 'tags))))
> +	(when (equal op ?-)

`eq'

> +    ; any of the expressions can match if op = +
> +    ; all must match if the operator is -. All o

You need two semi-colons here.

> +    (if (equal op ?-)

`eq'

> +(defun org-agenda-filter-apply (filter type &optional expand)
>    "Set FILTER as the new agenda filter and apply it."

See above.

> Subject: [PATCH 3/3] org: Nesting grouptags
>
> * lisp/org.el (org-tags-expand): Nesting grouptags. Allowing subtags
>   to be defined as groups themselves.
>
>   : #+TAGS: [ Group : SubOne(1) SubTwo ]
>   : #+TAGS: [ SubOne : SubOne1 SubOne2 ]
>   : #+TAGS: [ SubTwo : SubTwo1 SubTwo2 ]
>
>   Should be seen as a tree of tags:
>   - Group
>     - SubOne
>       - SubOne1
>       - SubOne2
>     - SubTwo
>       - SubTwo1
>       - SubTwo2
>
>   Searching for "Group" should return all tags defined above.
> ---
>  lisp/org.el | 25 +++++++++++++++++++++++--
>  1 file changed, 23 insertions(+), 2 deletions(-)
>
> diff --git a/lisp/org.el b/lisp/org.el
> index 6bb8edf..5c80238 100755
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -14543,7 +14543,7 @@ See also `org-scan-tags'.
>  			  matcher)))
>      (cons match0 matcher)))
>  
> -(defun org-tags-expand (match &optional single-as-list downcased)
> +(defun org-tags-expand (match &optional single-as-list downcased tags-already-expanded)
>    "Expand group tags in MATCH.

See above.

> +	    (when (and (not (get-text-property 0 'grouptag (match-string 2 return-match)))
> +		       (not (member tag work-already-expanded)))

Nitpick:

  (unless (or (get-text-property ...)
              (member tag ...)))

> +	      (setq work-already-expanded (append (list tag) work-already-expanded))

  (push tag work-already-expanded)

> +	      ; Recursively expand each tag in the group, if the tag hasn't
> +	      ; already been expanded

See above. Missing full stop, too.

> +		    ;; Redo the regexp-match because the recursive calls seems to mess it up...

You can also use `save-match-data' and restore it later.

Thanks for your work.


Regards,

  reply	other threads:[~2015-02-24 16:42 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-25 11:07 [RFC] [PATCH] Changes to Tag groups - allow nesting and regexps Gustav Wikström
2015-01-31  8:41 ` Nicolas Goaziou
2015-02-19 20:00   ` Gustav Wikström
2015-02-24 16:43     ` Nicolas Goaziou [this message]
2015-03-05  1:08       ` Gustav Wikström
2015-03-07 21:51         ` Nicolas Goaziou
2015-03-15 10:17           ` Gustav Wikström
2015-03-16 20:38           ` Gustav Wikström
2015-03-16 21:30             ` Nicolas Goaziou
2015-03-19 21:07               ` Gustav Wikström
2015-03-19 22:43                 ` Nicolas Goaziou
  -- strict thread matches above, loose matches on Subject: below --
2015-11-25  7:50 sgeorgii .
2015-11-25 10:26 ` Gustav Wikström
2015-11-25 11:05   ` sgeorgii .
2015-11-25 12:20     ` Gustav Wikström
2015-11-25 12:58       ` Nicolas Goaziou
2015-11-25 14:44         ` Gustav Wikström
2015-11-25 14:52           ` Nicolas Goaziou
2015-11-25 15:39             ` Gustav Wikström
2015-11-26  7:30               ` sgeorgii .
2015-11-26  8:21               ` Nicolas Goaziou
2015-11-26 10:01                 ` Gustav Wikström
2015-11-26 10:21                   ` Nicolas Goaziou

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87a90345wl.fsf@nicolasgoaziou.fr \
    --to=mail@nicolasgoaziou.fr \
    --cc=emacs-orgmode@gnu.org \
    --cc=gustav.erik@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).