From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Tim O'Callaghan" Subject: Re: Re: [hack/extension] org-mode/emacs regexp Date: Tue, 17 Nov 2009 12:49:53 +0100 Message-ID: <3d6808890911170349t125ce906kcece8cf67e4cf66@mail.gmail.com> References: <1e5bcefd0911161010w448c73d6yb2082b49348c4ea6@mail.gmail.com> <1e5bcefd0911161145ubdb4cc6w3ea40bcfcdeeb225@mail.gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Return-path: Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NAMZg-0003Ws-Lg for emacs-orgmode@gnu.org; Tue, 17 Nov 2009 06:50:20 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NAMZb-0003V5-EU for emacs-orgmode@gnu.org; Tue, 17 Nov 2009 06:50:20 -0500 Received: from [199.232.76.173] (port=52982 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NAMZb-0003Uw-8C for emacs-orgmode@gnu.org; Tue, 17 Nov 2009 06:50:15 -0500 Received: from mail-fx0-f225.google.com ([209.85.220.225]:52782) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NAMZa-0004or-L7 for emacs-orgmode@gnu.org; Tue, 17 Nov 2009 06:50:15 -0500 Received: by fxm25 with SMTP id 25so1698858fxm.26 for ; Tue, 17 Nov 2009 03:50:13 -0800 (PST) In-Reply-To: <1e5bcefd0911161145ubdb4cc6w3ea40bcfcdeeb225@mail.gmail.com> List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org To: Marcelo de Moraes Serpa Cc: Org Mode 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. =A0I've been coding elisp on and off for years, but I'm no elisp =A0expert. I put org-action-verb together after allot of RTFM, and =A0looking at other code. =A0I debugged it using these methods: =A0+ (message). =A0To get an idea about what is going on without having =A0 =A0to use the debugger, the message function is handy. It will print =A0 =A0whatever to the *messages* buffer. Primitive, but worked for me at =A0 =A0the time. =A0+ (regexp-builder). For regular expression work there is the built =A0 =A0in regular expression builder (M-x regexp-builder) or John =A0 =A0Wiegley's excellent (M-x regex-tool), which i only just remembered =A0 =A0I have. =A0+ (eval-region). I have it mapped to a key, but (M-x eval-region) is =A0 =A0great for changing small parts of the compiled elisp, variables or =A0 =A0whatever. =A0+ (info-lookup-symbol). =A0When poking about in the innards of =A0 =A0(X)Emacs, it is always a good idea to have info-lookup-symbol =A0 =A0mapped to a key somewhere. I have it mapped to f1. =A0 =A0(define-key global-map [f1] 'info-lookup-symbol) =A0 =A0It will bring up a buffer showing what the symbol under the cursor =A0 =A0does and what file it is defined in (if the symbol is documented). * RTFM - Read the Fine Manual. =A0Other things to read up on to understand org-action-verb: =A0+ What brackets do in a regular expression =A0 =A0http://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Back= slash.html#Regexp-Backslash =A0 =A0It is also kind of confusing to see "\\" in the code and "\" in =A0 =A0the documentation. Some more RTFM may be required :) =A0+ What this line of elisp does: =A0 =A0(make-overlay (match-beginning 1) (match-end 1) nil t nil) =A0 =A0 http://www.gnu.org/software/emacs/manual/html_node/elisp/Managing-O= verlays.html#Managing-Overlays =A0 =A0 http://www.gnu.org/software/emacs/manual/html_node/elisp/Simple-Mat= ch-Data.html#index-match_002dbeginning-3021 * org-action-verb - what it does. =A0Essentially, all org-action-verb does, is build a bunch of regular =A0expressions to find headlines between 'point' and 'limit' with the =A0correct TODO type. Once it has found a headline that matches, it =A0uses other regular expressions to add or remove the overlay *to the =A0first sub-element* of those regular expressions. =A0The meat of the code from the original org-action-verb with some =A0better 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 "\\(.*\\)$") =A0 =A0(remove-overlays (match-beginning 1) (match-end 1) 'org-action-overl= ay t)) ;; ;; check for the presence of a valid action-verb ;; (if (looking-at todo-action-verbs-regexp) =A0;; =A0;; do nothing if the action verb matches =A0;; =A0 =A0nil =A0;; =A0;; It is not an action verb, apply the overlay to the first word =A0;; in the line. =A0;; =A0;; The regular expression matches the first word after a space or =A0;; tab on a matching headline, and applies the org-action-incorrect =A0;; overlay to it. =A0;; So: =A0;; "[ ]+\\(\\<\\w+\\>\\)" =A0;; =A0;; in english becomes: =A0;; =A0;; - "[ ]+" - Match one or more space or tab (should use :space:). =A0;; - "\\(" =A0 - Open sub expression 1 =A0;; - "\\<" =A0 - Match the empty string, but only at the beginning of a = word =A0;; - "\\w" =A0 - Match one or more word-constituent characters =A0;; - "\\>" =A0 - Match the empty string, but only at the end of a word =A0;; - "\\)" =A0 - Close sub expression 1 =A0;; =A0(if (looking-at "[ ]+\\(\\<\\w+\\>\\)") =A0 =A0 =A0;; apply new overlay to 1st matching sub-expression =A0 =A0 =A0(let ((overlay (make-overlay (match-beginning 1) (match-end 1) n= il t nil))) =A0 =A0 =A0 =A0(overlay-put overlay 'org-action-overlay t) =A0 =A0 =A0 =A0(overlay-put overlay 'face 'org-action-incorrect) =A0 =A0 =A0 =A0(overlay-put overlay 'evaporate t) =A0 =A0 =A0 =A0overlay)))) ----------------------- ending at line 202 * What you need to do to fix your problem? =A0I suspect all you need to do is change the matching expression to =A0something like: =A0(let ((tag-keywords-regexp (concat "^\\*+[:space:]+[\\w:space:]+[:space:]+:\\(" tag "\\):$") )) =A0Also you probably want to first match the whole line to remove the =A0overlay, before applying a new one. Hope that helps, Tim. 2009/11/16 Marcelo de Moraes Serpa : > Ok, I'm sorry, I actually had to research a little bit more before postin= g > :) > > Well, what I need to know now is how to make the overlay work. The code t= o > 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 > wrote: >> >> Hello, >> >> I started writing an extension to org that actually applies a custom fac= e >> 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 >> =A0 '((((class color) (background light)) (:foreground "purple" :bold t >> :underline t)) >> =A0=A0=A0 (((class color) (background dark)) (:foreground "purple" :bold= t >> :underline t)) >> =A0=A0=A0 (t (:bold t :underline t))) >> =A0 "Used by org-color-by-tag for items tagged with :CATEGORY:") >> >> (defface org-gtd-default-project-face >> =A0 '((((class color) (background light)) (:foreground "purple" :bold t >> :underline t)) >> =A0=A0=A0 (((class color) (background dark)) (:foreground "purple" :bold= t >> :underline t)) >> =A0=A0=A0 (t (:bold t :underline t))) >> =A0 "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) >> =A0 "Add the faces to corresponding items depending on the TAG." >> =A0 (let (rtn a) >> =A0=A0=A0 ;; check variable is set, and buffer left to search >> =A0=A0=A0 (when (and (not rtn) org-gtd-tags) >> =A0=A0=A0=A0=A0 ;; for each todo/action verb set >> =A0=A0=A0=A0=A0 (dolist (tag org-gtd-tags) >> =A0=A0=A0=A0=A0=A0=A0 ;; build regexps >> =A0=A0=A0=A0=A0=A0=A0 (let ((tag-keywords-regexp >> >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (rege= xp-opt (cdr tag) 'word))) >> >> =A0=A0=A0=A0=A0=A0=A0=A0=A0 ;; while we can find a todo keyword >> =A0=A0=A0=A0=A0=A0=A0=A0=A0 (while (re-search-forward ":PROJECT:" limit = t) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ;; check for action verb >> >> >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ;; apply new over= lay >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (let ((overlay (make= -overlay (match-beginning 1) >> (match-end 1) nil t nil))) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (overlay-put o= verlay 'face >> 'org-gtd-default-project-face) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ;;(overlay-put= overlay 'mouse-face mouse-face) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (overlay-put o= verlay 'org-action-overlay t) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (overlay-put o= verlay 'evaporate t) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (overlay-put o= verlay 'help-echo "mouse-2: correct word >> at point") >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 overlay) >> >> >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ;; reset search point? >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (backward-char 1))))) >> =A0=A0=A0 rtn)) >> >> (org-font-lock-add-tag-faces 10) >> >> (defun org-mode-color-by-tag-hook () >> =A0 "Initalise org-color-by-tag." >> =A0 (interactive) >> =A0 (font-lock-add-keywords nil '((org-font-lock-add-tag-faces))) >> =A0 ) >> >> ;; 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 remove= d >> the regexp string that Tim used, which were: >> >> "^\\*+[ =A0=A0=A0 ]+" >> >> Was used here: >> =A0=A0=A0=A0=A0=A0=A0 (let ((todo-keywords-regexp >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (concat "^\\*+[ =A0=A0=A0 ]+" >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (rege= xp-opt (car todo) 'words))) >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (todo-action-verbs-regexp >> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (concat "[ =A0=A0=A0 ]+" (reg= exp-opt (cdr todo) 'words)))) >> >> >> And:=A0 "[ =A0=A0=A0 ]+\\(\\<\\w\\w+\\>\\)" >> >> Used in: (looking-at "[ =A0=A0=A0 ]+\\(\\<\\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=A0 "[=A0=A0=A0 ]", and w, I woul= d 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 > >