1

I'm trying to create a regexp that will work for two (2) kinds of situations -- an org headline and maybe a second line containing a deadline and/or scheduled (if they exists). I've tried variations using question-marks throughout the second line of the regexp, but to no avail. As soon as I include the regexp for the second line, the heading with Someday ... is excluded. The second line looks like this: \n\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\): <\\([^>]+\\)>\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\): <\\([^>]+\\)> The goal, please, would be to select both of the following examples:

** Active [#A] 0 @ Contains a deadline and is scheduled. :event:lawlist:
   DEADLINE: <2013-12-21 Sat 17:00>  SCHEDULED: <2013-12-21 Sat>

** Active [#B] 0 @ Contains a deadline, but is not scheduled. :event:lawlist:
   DEADLINE: <2013-12-22 Sun 08:00>

** Someday [#D] 0 @ No deadline, and not scheduled. :lawlist:

(defvar lawlist-super-duper-regexp "^\\(\\*+\\)\\(?: +\\(Active\\|Someday\\)\\)?\\(?: +\\(\\[#.\\]\\)\\)?\\(?: +\\(.*?\\)\\)??\\(?:[    ]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[    ]*\n\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\): <\\([^>]+\\)>\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\): <\\([^>]+\\)>"
  "Custom match every element of the headline, plus every element of second line with a deadline or scheduled.")

EDIT (December 17, 2013):  First working draft . . .

EDIT (December 18, 2013):  I broke something during the last 24 hours, so I'm posting the working code again just in case the broken solution was inadvertently posted yesterday.

(defvar lawlist-org-heading-regexp "^\\(\\*+\\)\\(?: +\\(.*?\\)\\)?[ \t]*\\(\n.*DEADLINE.*$\\)"
  "Custom match org headline, plus the second line with a deadline.")

(defvar lawlist-super-duper-regexp "^\\(\\*+\\)\\(?: +\\(Active\\|Next Action\\|Reference\\|Someday\\|Delegated\\|None\\)\\)?\\(?: +\\(\\[#.\\]\\)\\)?\\(?: +\\(.*?\\)\\)??\\(?:[ ]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ ]*\\(?:\n\\)\\(?: +\\(DEADLINE:\\|SCHEDULED:\\)\\)?\\(?: +\\(<\\)\\([^>]+\\)\\(>\\)\\)?\\(?: +\\(DEADLINE:\\|SCHEDULED:\\)\\)?\\(?: +\\(<\\)\\([^>]+\\)\\(>\\)\\)?"
  "Custom match every element of the headline, plus every element of second line with a deadline or scheduled (if they exist).")

(defun org-get-super-duper-heading ()
  (when (looking-at lawlist-super-duper-regexp)
    (concat
  (when (not (equal (match-string 1) nil))
    (match-string 1))
  (when (not (equal (match-string 2) nil))
    (concat " " (match-string 2)))
  (when (not (equal (match-string 3) nil))
    (concat " " (match-string 3)))
  (when (not (equal (match-string 4) nil))
    (concat " " (match-string 4)))
  (when (not (equal (match-string 5) nil))
    (concat " " (match-string 5)))
  (when (not (equal (match-string 6) nil))
    (concat "\n   " (match-string 6)))
  (when (not (equal (match-string 7) nil))
    (concat " " (match-string 7)))
  (when (not (equal (match-string 8) nil))
    (match-string 8))
  (when (not (equal (match-string 9) nil))
    (match-string 9))
  (when (not (equal (match-string 10) nil))
    (concat " " (match-string 10)))
  (when (not (equal (match-string 11) nil))
    (concat " " (match-string 11)))
  (when (not (equal (match-string 12) nil))
    (match-string 12))
  (when (not (equal (match-string 13) nil))
    (match-string 13)))))

(defun lawlist-org-get-heading (&optional no-tags no-todo)
  "Return the heading of the current entry, without the stars.
When NO-TAGS is non-nil, don't include tags.
When NO-TODO is non-nil, don't include TODO keywords."
  (save-excursion
    (org-back-to-heading t)
    (cond
     ((and no-tags no-todo)
      (looking-at org-complex-heading-regexp)
      (match-string 4))
     (no-tags
      (looking-at (concat org-outline-regexp
        "\\(.*?\\)"
        "\\(?:[ \t]+:[[:alnum:]:_@#%]+:\\)?[ \t]*$"))
      (match-string 1))
     (no-todo
      (looking-at org-todo-line-regexp)
      (match-string 3))
     (t (looking-at org-heading-regexp)
        (concat
          (match-string 1)
          " "
          (match-string 2)
          (if (and (looking-at lawlist-org-heading-regexp) (match-string 3))
            (match-string 3)) )))))
lawlist
  • 13,099
  • 3
  • 49
  • 158

2 Answers2

1

If I understand what you want to do, try the following

^\*\+.*\(\s\+\(DEADLINE.*\|.*?SCHEDULED.*\)\)\?

Now I am not entirely sure of the syntax for emacs or elisp. But I believe they do support the lazy quantifier .*?

Also, you need to set the option for Dot does NOT match newline; and ^$ MATCH at line breaks

Edit: I may have some of the quantifiers messed up with regard to emacs lisp. I may have some unwanted \'s. I believe emacs does NOT use \+ and \? which I have in the above. If that is the case, try:

^\*+.*\(\s+\(DEADLINE.*?\|.*?SCHEDULED.*\)\)?

Also, if emacs does not support the ? at the end then replace that with \{0,1\}

Ron Rosenfeld
  • 53,870
  • 7
  • 28
  • 60
  • I haven't been able to get your example to work with Emacs using the `re-builder` function. The sample code I posted works with the second line, but the single headline containing `Someday . . .` gets excluded. I'll keep trying variations . . . . – lawlist Dec 18 '13 at 01:49
  • `"^\\(\\*+\\)\\(?: +\\(Active\\|Someday\\)\\)?\\(?: +\\(\\[#.\\]\\)\\)?\\(?: +\\(.*?\\)\\)??\\(?:[ ]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ ]*\n\\(?: +\\(DEADLINE\\.*\\|\\.*SCHEDULED\\.*\\)\\)?"`. The code preceding this sentence seems to work until I add a colon to the very end -- something about the colon means all bets are off -- if I could just figure out a way to add the remainder: `: <\\([^>]+\\)>\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\): <\\([^>]+\\)>` – lawlist Dec 18 '13 at 01:59
  • There was an error in my regex, now corrected \s~ should be \s+ – Ron Rosenfeld Dec 18 '13 at 02:14
  • But you also should state more clearly what you require. There appears items in your regex that are not in your stated requirements; you also do not define how a org headline is defined (I assumed it started with 2 *'s) – Ron Rosenfeld Dec 18 '13 at 02:15
  • Items in your regex that do not appear in your description include not only the colon, but also Someday and some other stuff. – Ron Rosenfeld Dec 18 '13 at 02:16
  • It may be that the entire second line needs to be encapsulated within one set of parentheses -- the following regex is just about all the way there -- just a little tidying up needed:  `^\\(\\*+\\)\\(?: +\\(Active\\|Someday\\)\\)?\\(?: +\\(\\[#.\\]\\)\\)?\\(?: +\\(.*?\\)\\)??\\(?:[ ]+\\(:[[:alnum:]_@#%:]+:\\)\\)?[ ]*\n\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\(: <\\)\\([^>]+\\)\\(>\\)\\(?: +\\(DEADLINE\\|SCHEDULED\\)\\)\\(: <\\)\\([^>]+\\)\\(>\\)\\)?`  There are different sections so that I can match a variety of sections depending upon whatever function that will be used. – lawlist Dec 18 '13 at 02:42
  • The second line definitely needs to be in a capturing group, and then you make that entire group optional with either the ? quantifier if emacs supports that, or the \{0,1\} quantifier if it does not. – Ron Rosenfeld Dec 18 '13 at 03:52
  • Thank you very much for working on my issue -- your help has been greatly appreciated !!! – lawlist Dec 18 '13 at 06:40
0

I may be modifying / tweaking the answer in this related thread, so I'll just post the link -- it solves the question posed in this current thread:

https://stackoverflow.com/a/20960301/2112489

Community
  • 1
  • 1
lawlist
  • 13,099
  • 3
  • 49
  • 158