emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: "Tim O'Callaghan" <timo@dspsrv.com>
To: Marcelo de Moraes Serpa <celoserpa@gmail.com>
Cc: Org Mode <emacs-orgmode@gnu.org>
Subject: Re: Re: [hack/extension] org-mode/emacs regexp
Date: Tue, 17 Nov 2009 12:49:53 +0100	[thread overview]
Message-ID: <3d6808890911170349t125ce906kcece8cf67e4cf66@mail.gmail.com> (raw)
In-Reply-To: <1e5bcefd0911161145ubdb4cc6w3ea40bcfcdeeb225@mail.gmail.com>

Hi Marcelo.

Thanks for the thumbs up, its nice when that happens.

So, to your questions - The answers are a bit long, and I'm cc'ing to
the list so that others wanting org-action-verb like stuff can
understand what it does, and hack it for their needs.

* Debugging.

 I've been coding elisp on and off for years, but I'm no elisp
 expert. I put org-action-verb together after allot of RTFM, and
 looking at other code.

 I debugged it using these methods:

 + (message).  To get an idea about what is going on without having
   to use the debugger, the message function is handy. It will print
   whatever to the *messages* buffer. Primitive, but worked for me at
   the time.

 + (regexp-builder). For regular expression work there is the built
   in regular expression builder (M-x regexp-builder) or John
   Wiegley's excellent (M-x regex-tool), which i only just remembered
   I have.

 + (eval-region). I have it mapped to a key, but (M-x eval-region) is
   great for changing small parts of the compiled elisp, variables or
   whatever.

 + (info-lookup-symbol).  When poking about in the innards of
   (X)Emacs, it is always a good idea to have info-lookup-symbol
   mapped to a key somewhere. I have it mapped to f1.

   (define-key global-map [f1] 'info-lookup-symbol)

   It will bring up a buffer showing what the symbol under the cursor
   does and what file it is defined in (if the symbol is documented).

* RTFM - Read the Fine Manual.
 Other things to read up on to understand org-action-verb:

 + What brackets do in a regular expression
   http://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Backslash.html#Regexp-Backslash

   It is also kind of confusing to see "\\" in the code and "\" in
   the documentation. Some more RTFM may be required :)

 + What this line of elisp does:
   (make-overlay (match-beginning 1) (match-end 1) nil t nil)

    http://www.gnu.org/software/emacs/manual/html_node/elisp/Managing-Overlays.html#Managing-Overlays
    http://www.gnu.org/software/emacs/manual/html_node/elisp/Simple-Match-Data.html#index-match_002dbeginning-3021

* org-action-verb - what it does.

 Essentially, all org-action-verb does, is build a bunch of regular
 expressions to find headlines between 'point' and 'limit' with the
 correct TODO type. Once it has found a headline that matches, it
 uses other regular expressions to add or remove the overlay *to the
 first sub-element* of those regular expressions.

 The meat of the code from the original org-action-verb with some
 better comments, will probably provide a better explanation

----------------------- starting at line 189

;;
;; match the whole headline and remove any previous overlay without
;; moving point. Where point should be at the start of a headline.
;;
(if (looking-at "\\(.*\\)$")
   (remove-overlays (match-beginning 1) (match-end 1) 'org-action-overlay t))
;;
;; check for the presence of a valid action-verb
;;
(if (looking-at todo-action-verbs-regexp)
 ;;
 ;; do nothing if the action verb matches
 ;;
   nil
 ;;
 ;; It is not an action verb, apply the overlay to the first word
 ;; in the line.
 ;;
 ;; The regular expression matches the first word after a space or
 ;; tab on a matching headline, and applies the org-action-incorrect
 ;; overlay to it.
 ;; So:
 ;; "[ ]+\\(\\<\\w+\\>\\)"
 ;;
 ;; in english becomes:
 ;;
 ;; - "[ ]+" - Match one or more space or tab (should use :space:).
 ;; - "\\("   - Open sub expression 1
 ;; - "\\<"   - Match the empty string, but only at the beginning of a word
 ;; - "\\w"   - Match one or more word-constituent characters
 ;; - "\\>"   - Match the empty string, but only at the end of a word
 ;; - "\\)"   - Close sub expression 1
 ;;
 (if (looking-at "[ ]+\\(\\<\\w+\\>\\)")
     ;; apply new overlay to 1st matching sub-expression
     (let ((overlay (make-overlay (match-beginning 1) (match-end 1) nil t nil)))
       (overlay-put overlay 'org-action-overlay t)
       (overlay-put overlay 'face 'org-action-incorrect)
       (overlay-put overlay 'evaporate t)
       overlay))))

----------------------- ending at line 202

* What you need to do to fix your problem?
 I suspect all you need to do is change the matching expression to
 something like:

 (let ((tag-keywords-regexp (concat
"^\\*+[:space:]+[\\w:space:]+[:space:]+:\\(" tag "\\):$") ))

 Also you probably want to first match the whole line to remove the
 overlay, before applying a new one.

Hope that helps,

Tim.

2009/11/16 Marcelo de Moraes Serpa <celoserpa@gmail.com>:
> Ok, I'm sorry, I actually had to research a little bit more before posting
> :)
>
> Well, what I need to know now is how to make the overlay work. The code to
> match is working, but I'm receiving the following error:
>
> Error during redisplay: (wrong-number-of-arguments match-beginning 0)
>
> Here's the full code: http://pastie.org/701448
>
> (Thanks to Tim O'Calaghan for the original contribution)
>
> Marcelo.
>
> Also, how can I debug it? I tried debug-on-entry but it is not working :S
>
>
> On Mon, Nov 16, 2009 at 12:10 PM, Marcelo de Moraes Serpa
> <celoserpa@gmail.com> wrote:
>>
>> Hello,
>>
>> I started writing an extension to org that actually applies a custom face
>> to an item tagges as CATEGORY or PROJECT. The thing is I'm really having a
>> hard time understanding the regexp. The code is adapted from the
>> org-action-verb.el by Tim O'Calaghan, basically using the same structure
>> since my elisp knowledge is very basic. I have managed to get it to work to
>> a basic level, but it is applying the face to the whole tree instead of
>> applying to only one item.
>>
>> (defface org-gtd-default-category-face
>>   '((((class color) (background light)) (:foreground "purple" :bold t
>> :underline t))
>>     (((class color) (background dark)) (:foreground "purple" :bold t
>> :underline t))
>>     (t (:bold t :underline t)))
>>   "Used by org-color-by-tag for items tagged with :CATEGORY:")
>>
>> (defface org-gtd-default-project-face
>>   '((((class color) (background light)) (:foreground "purple" :bold t
>> :underline t))
>>     (((class color) (background dark)) (:foreground "purple" :bold t
>> :underline t))
>>     (t (:bold t :underline t)))
>>   "Used by org-color-by-tag for items tagged with :PROJECT:")
>>
>> (defvar org-gtd-tags '("PROJECT" "CATEGORY"))
>>
>> (defun org-font-lock-add-tag-faces (limit)
>>   "Add the faces to corresponding items depending on the TAG."
>>   (let (rtn a)
>>     ;; check variable is set, and buffer left to search
>>     (when (and (not rtn) org-gtd-tags)
>>       ;; for each todo/action verb set
>>       (dolist (tag org-gtd-tags)
>>         ;; build regexps
>>         (let ((tag-keywords-regexp
>>
>>                        (regexp-opt (cdr tag) 'word)))
>>
>>           ;; while we can find a todo keyword
>>           (while (re-search-forward ":PROJECT:" limit t)
>>             ;; check for action verb
>>
>>
>>                    ;; apply new overlay
>>                   (let ((overlay (make-overlay (match-beginning 1)
>> (match-end 1) nil t nil)))
>>                     (overlay-put overlay 'face
>> 'org-gtd-default-project-face)
>>                     ;;(overlay-put overlay 'mouse-face mouse-face)
>>                     (overlay-put overlay 'org-action-overlay t)
>>                     (overlay-put overlay 'evaporate t)
>>                     (overlay-put overlay 'help-echo "mouse-2: correct word
>> at point")
>>                     overlay)
>>
>>
>>             ;; reset search point?
>>             (backward-char 1)))))
>>     rtn))
>>
>> (org-font-lock-add-tag-faces 10)
>>
>> (defun org-mode-color-by-tag-hook ()
>>   "Initalise org-color-by-tag."
>>   (interactive)
>>   (font-lock-add-keywords nil '((org-font-lock-add-tag-faces)))
>>   )
>>
>> ;; Turn on action verb font locking.
>> (add-hook 'org-mode-hook 'org-mode-color-by-tag-hook)
>>
>> As you can see, I'm in the debug phase, and I'm not even using the list of
>> strings (PROJECT CATEGORY) I've created. I'm just trying to search for
>> occurrences of the PROJECT tag and trying to apply the face. I've removed
>> the regexp string that Tim used, which were:
>>
>> "^\\*+[     ]+"
>>
>> Was used here:
>>         (let ((todo-keywords-regexp
>>                (concat "^\\*+[     ]+"
>>                        (regexp-opt (car todo) 'words)))
>>               (todo-action-verbs-regexp
>>                (concat "[     ]+" (regexp-opt (cdr todo) 'words))))
>>
>>
>> And:  "[     ]+\\(\\<\\w\\w+\\>\\)"
>>
>> Used in: (looking-at "[     ]+\\(\\<\\w\\w+\\>\\)")
>>
>> What I want to do is: Search for items tagged as PROJECT or CATEGORY and
>> apply the corresponding face to them.
>>
>> If someone could explain me the role of  "[    ]", and w, I would be
>> grateful :)
>>
>> Thanks,
>>
>> Marcelo.
>>
>
>
> _______________________________________________
> Emacs-orgmode mailing list
> Remember: use `Reply All' to send replies to the list.
> Emacs-orgmode@gnu.org
> http://lists.gnu.org/mailman/listinfo/emacs-orgmode
>
>

      reply	other threads:[~2009-11-17 11:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-16 18:10 [hack/extension] org-mode/emacs regexp Marcelo de Moraes Serpa
2009-11-16 19:45 ` Marcelo de Moraes Serpa
2009-11-17 11:49   ` Tim O'Callaghan [this message]

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=3d6808890911170349t125ce906kcece8cf67e4cf66@mail.gmail.com \
    --to=timo@dspsrv.com \
    --cc=celoserpa@gmail.com \
    --cc=emacs-orgmode@gnu.org \
    /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).