Archived entries from file /home/me/src/helm-org-rifle/notes.org
;; This should return the "Target heading" heading too
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "test.org") "face")
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org") "face helm")
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "testtemp.org") "face helm")
This does not work:
(let ((target "(face-remap-set-base 'helm-selection")
(token "face"))
(string-match (concat "\\_<" token "\\_>") target))
Which is strange, because \\_<
is supposed to be the symbol-boundary character…
This works but isn’t what we want:
(let ((target "(face-remap-set-base 'helm-selection")
(token "face"))
(string-match token target))
(let ((target "(face-remap-set-base 'helm-selection")
(token "face"))
(string-match (concat "\\b" token "\\b") target))
This may do it:
(let ((target "(face-remap-set-base 'helm-selection")
(token "face"))
(string-match (concat "\\W" token "\\W") target))
It matches face
okay, but not helm
because of the quote.
(let ((target "(face-remap-set-base 'helm-selection")
(token "helm"))
(string-match (concat "\\(\\W\\|\\_<\\)" token "\\(\\W\\|\\_>\\)") target))
Wow, that “‘helm-selection” really doesn’t want to be matched…
This might do it…
(string-match "\\(\\B\\|\\W\\)face" "(face-remap-set-base 'helm-selection")
Seems to work… now for the real test…
(let ((target "(face-remap-set-base 'helm-selection")
(token "selection"))
(string-match (concat "\\(\\B\\|\\W\\)" token "\\(\\W\\|\\B\\)") target))
I think it works! Let’s try it for real…
Buuuuut it doesn’t match “selection”. Wow.
(let ((target "(face-remap-set-base 'helm-selection")
(tokens '("face" "helm" "blah" "selection" "base")))
(cl-loop for token in tokens
when (string-match (concat "\\(\\B\\|\\W\\|\\_<\\|[[:punct:]]\\)" token "\\(\\B\\|\\W\\|\\_>\\|[[:punct:]]\\)") target)
collect token))
Ok, this seems to match for “face”, “helm”, and “selection” and “base” but not “blah”.
Okay, this seems to work:
(defcustom helm-org-rifle-re-begin-part
"\\(\\B\\|\\W\\|\\_<\\|[[:punct:]]\\)"
"Argh"
:group 'helm-org-rifle :type 'regexp)
(defcustom helm-org-rifle-re-end-part
"\\(\\B\\|\\W\\|\\_>\\|[[:punct:]]\\)"
"argh"
:group 'helm-org-rifle :type 'regexp)
;; Then do:
(concat helm-org-rifle-re-begin-part token helm-org-rifle-re-end-part)
But it feels like it’s matching slower now, so I guess I need to experiment with different ones…
(let ((target "(face-remap-set-base 'helm-selection")
(tokens '("face" "helm" "blah" "selection" "base")))
(cl-loop for token in tokens
when (string-match (concat helm-org-rifle-re-begin-part token helm-org-rifle-re-end-part) target)
collect token))
Let’s try a simpler one:
(setq helm-org-rifle-re-begin-part
"\\(\\B\\|\\_<\\|[[:punct:]]\\)")
(setq helm-org-rifle-re-end-part
"\\(\\B\\|\\_>\\|[[:punct:]]\\)")
Ok, that works. Now for another:
(setq helm-org-rifle-re-begin-part
"\\(\\_<\\|[[:punct:]]\\)")
(setq helm-org-rifle-re-end-part
"\\(\\_>\\|[[:punct:]]\\)")
Ok, that seems to work too. Kind of makes sense: symbol boundaries or punctuation (which apparently doesn’t count as a symbol-boundary…for some values of syntax table…)
Ok, this seems to work and seems to be decently fast. Let’s commit it and try it out for a while.
Searching for just the first word should find this, but it doesn’t; only searching for face-remap-set-base
does.
:after-init-hook (lambda ()
(with-current-buffer helm-buffer
(face-remap-set-base 'helm-selection
:underline 'unspecified
:weight 'unspecified
:background (face-attribute 'helm-selection :background))))
We want order to be irrelevant. So searching for “bravo alpha” should match the following subheading…
And it does. Except…
;; This works
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "~/org/inbox.org") "emacs org-mode")
;; This works
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "~/org/inbox.org") "org-mode emac")
;; This gives a weird args-out-of-range error. Does it only happen in this large file?
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "~/org/inbox.org") "org-mode emacs")
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "~/org/reference.org") "org-mode emacs")
;; No, it happens in the smaller file too...are hyphens the problem?...yes...
alpha bravo
;; This works fine
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "alpha charlie-delta")
;; So does this
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "charlie-delta")
;; And this
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "charlie-delta alpha")
;; But this does not!
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "org-mode alpha")
;; But this works!
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "org-mode blah")
The problem seems to be when the hyphenated word is on a different line than the non-hyphenated word (and we’re only dealing with two words here…). I sure don’t know why. Will have to step through the matching code…
The ivy-regex-ignore-order
setting in ivy/swiper might help with figuring this out.
alpha bravo charlie-delta argh org-mode blah
Headings with priorities should be correctly displayed in results.
Baby elephant
- State “DONE” from “UNDERWAY” [2016-03-28 Mon 19:34]
- State “UNDERWAY” from “DONE” [2016-03-28 Mon 19:31]
- State “DONE” from “TODO” [2016-03-28 Mon 17:30]
This should show both this heading and the target:
(let ((helm-org-rifle-show-tags t))
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "charade"))
This should show only this heading:
(let ((helm-org-rifle-show-tags nil))
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "charade"))
Yarr.
This should also match for the content: :charade:
Tags are being fontified just like the rest of the heading text, instead of like tags.
(helm-org-rifle-fontify-like-in-org-mode (s-join " " (list "*"
"Heading"
":tag1:tag2:")))
Seems like there needs to be whitespace after the tag string to make it appear in the org-tag
face.
(helm-org-rifle-fontify-like-in-org-mode (s-join " " (list "*"
"Heading"
":tag1:tag2: ")))
Surrounding tags with colons in the input doesn’t seem to work:
(let ((helm-org-rifle-show-tags t))
(helm-org-rifle-get-candidates-in-buffer (current-buffer) ":charade:"))
It’s because the colons in the tag string are being matched by the :punct:
in the regexp’s first part, eating the colon so it doesn’t match the one in the input string. I’m not sure how to fix that. I guess I could make the matching regexp a series of prefix-input-suffix
groups, and adjust the prefix and suffix for inputs that should match tags…seems messy but I guess it would work.
\(\_<\|[[:punct:]]\)\( \)\(\_>\|[[:punct:]]\)
"(_<|[[:punct:]])(:tag1:)(_>|[[:punct:]])"
(string-match "^:[[:word:]@:]+:$" ":charade:tag2:")
(string-match "a" "ba")
(let* ((input (split-string input " " t))
;; Double colons in tag strings in input so they can match
(input (mapcar (lambda (s)
(if (string-match helm-org-rifle-tags-re s)
(replace-regexp-in-string ":" "::" s)
s))
input))
(match-all-tokens-re (mapconcat (lambda (token)
(if (string-match helm-org-rifle-tags-re token)
;; Remove punct class from prefix and suffix so it can match tag strings
(concat "\\_<" (regexp-quote token) "\\_>")
;; Not a tag; use normal prefix/suffix
(concat helm-org-rifle-re-begin-part
(regexp-quote token)
helm-org-rifle-re-end-part)))))
;; TODO: Turn off case folding if input contains mixed case
(case-fold-search t)
results))
Now it matches headings with one tag, but not more than one.
(let ((helm-org-rifle-show-tags t))
(helm-org-rifle-get-candidates-in-buffer (current-buffer) ":gunn:"))
Maybe this will help, from org.el
(org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?")
(let ((helm-org-rifle-show-tags t)
(helm-org-rifle-tags-re (org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?")))
(--map (substring-no-properties (car it)) (helm-org-rifle-get-candidates-in-buffer (current-buffer) ":gunn:")))
Yeah, using that regexp from org-complex-heading-regexp-format
in org.el
seems to work. Whew.
But this is the more correct one I think:
(let ((tag-re (concat org-outline-regexp-bol
"\\(?:.*?[ \t]\\)?"
(org-re ":\\([[:alnum:]_@#%:]+\\):[ \t]*$")))
(targets (list ":yes:" "no")))
(mapcar (it (when (string-match tag-re it)
(match-string 0 it))) targets))
And this more minimal one seems to work too:
(let ((tag-re (org-re ":\\([[:alnum:]_@#%:]+\\):[ \t]*$"))
(targets (list ":yes:" "location" ":tag:" "notatag")))
(mapcar (it (when (string-match tag-re it)
(match-string 0 it))) targets))
(let ((tag-re helm-org-rifle-tags-re)
(targets (list ":yes:" "location" ":tag:" "notatag" ":website:Emacs:")))
(mapcar (it (when (string-match tag-re it)
(match-string 0 it))) targets))
[2016-04-01 Fri 21:18] Here I go again… This code is from up above, the first time I implemented/fixed tag matching:
(let ((helm-org-rifle-show-tags t)
(helm-org-rifle-tags-re (org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?")))
(--map (substring-no-properties (car it))
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org")
":website: Emacs")))
Ok, it seems to work now.
Note: Having this block of code (which I copied from further up) saved me probably hours of debugging. Somehow in the course of fixing the context-matching and re-fixing negation, I broke tag matching, and the key to fixing it again was having this:
(org-re "\\(?:[ \t]+\\(:[[:alnum:]_@#%%:]+:\\)\\)?")
…as opposed to this, which doesn’t seem to work:
(org-re ":\\([[:alnum:]_@#%:]+\\):[ \t]*$")
If I hadn’t kept these notes, I’d probably have spent at least another hour tracing the problem to the regexp and going back into org.el
and finding the right one again. I’ve never kept notes like this about a programming project before, but I am completely sold on doing this now, especially with Org, which is so powerful with its inline evaluation, code block evaluation, intermingling of code with results with comments…
- State “DONE” from “UNDERWAY” [2016-03-28 Mon 20:49]
- State “UNDERWAY” from “DONE” [2016-03-28 Mon 18:57]
- State “DONE” from “UNDERWAY” [2016-03-28 Mon 18:03]
- State “UNDERWAY” from “” [2016-03-28 Mon 17:30]
Emacs regexps don’t support negation or lookahead, so we’ll have to do it in stages.
- Find negation patterns and move them to a separate list.
- Test each match against negations and remove any that match.
(mapcar (it (helm-org-rifle-prep-token it)) '("notatag" ":tag:"))
(mapit '("notatag" ":tag:") (string-match helm-org-rifle-tags-re it))
(let ((helm-org-rifle-tags-re (org-re ":\\([[:alnum:]_@#%:]+\\):[ \t]*$")))
(mapit '("notatag" ":tag:") (string-match helm-org-rifle-tags-re it)))
(let* ((input (split-string "summertime !difficult easy" " " t))
(negations (delq nil (mapcar (lambda (token)
(when (string-match "^!" token)
(setq input (remove token input))
(helm-org-rifle-prep-token (s-chop-prefix "!" token))))
input))))
(list input negations))
(let ((helm-org-rifle-show-tags t))
(helm-org-rifle-get-candidates-in-buffer (current-buffer) "target !winter"))
e.g. searching for location !cat
should not exclude results containing location
.
This should return the Target positive: location
heading:
(let ((helm-org-rifle-show-tags t))
(mapit (helm-org-rifle-get-candidates-in-buffer (current-buffer) "location !ca ")
(s-replace "\n" "" (s-collapse-whitespace (org-no-properties (car it))))))
This should not return that heading:
(let ((helm-org-rifle-show-tags t))
(mapit (helm-org-rifle-get-candidates-in-buffer (current-buffer) "location !cat ")
(s-replace "\n" "" (s-collapse-whitespace (org-no-properties (car it))))))
(let ((pat "\\bcat\\b")
(targets '("a cat sleeps" "a catastrophe" "what")))
(mapit targets (when (string-match pat it)(match-string 0 it))))
…sigh. Use s-matches
not s-contains
. Duh.
(let ((pat "\\(\\_<\\|[[:punct:]]\\)cat\\(\\_>\\|[[:punct:]]\\)")
(target "a cat sleeps"))
(s-matches? pat target))
[2016-03-28 Mon 20:38] Well, I think it’s working correctly now, but I’m not 100% sure. Time will tell. If it’s not, hopefully I’ll discover it or get some reports.
notacatbutadog
cat
(profile-rifle 10 (helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org") "emacs helm"))
(profile-rifle 10 (helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org") "emacs helm !mail"))
It seems awkward that all of the results disappear when a bare !
is entered. Even if you type quickly, they all disappear and then reappear. Should be possible to fix this…
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org") "emacs helm !")
(helm-org-rifle-get-candidates-in-buffer (find-file-noselect "~/org/inbox.org") "emacs helm !org")
Fixed. Thanks to /u/washy9999 for the feedback!
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "pomegr blueberry")
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "green")
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "green blue")
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "pomegr")
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "helm food")
(let ((helm-candidate-separator " ")
(helm-org-rifle-show-path t))
(helm-org-rifle-get-candidates-in-buffer (get-file-buffer "test.org") "green blue"))
(let ((helm-org-rifle-fontify-headings nil))
(helm-org-rifle-get-candidates-in-buffer (get-buffer "reference.org") "emacs"))
(helm-org-rifle-get-candidates-in-buffer (get-buffer "reference.org") "emacs")
(helm-org-rifle-get-candidates-in-buffer (get-buffer "main.org") "emacs")
(helm-org-rifle-get-candidates-in-buffer (get-buffer "main.org") "tires")
(let ((helm-candidate-separator " "))
(helm :sources (helm-org-rifle-get-sources)))
(let ((helm-candidate-separator " ")
(helm-org-rifle-show-path t))
(helm :sources (helm-org-rifle-get-sources)))
(let ((helm-candidate-separator " ")
(helm-org-rifle-fontify-headings nil))
(helm :sources (helm-org-rifle-get-sources)))
(let ((helm-candidate-separator " ")
(helm-org-rifle-show-path t)
(helm-org-rifle-fontify-headings nil))
(helm :sources (helm-org-rifle-get-sources)))
(setq helm-org-rifle-show-path nil)
(setq helm-org-rifle-show-path t)
(setq argh-how-many-buffers 0)
(message "This many buffers: %s" argh-how-many-buffers)
(setq argh-how-many-times-getc-called 0)
(message "This many times: %s" argh-how-many-times-getc-called)
(progn
(dolist (p '("helm-" "org-" "string-" "s-"))
(elp-instrument-package p))
(let ((helm-pattern "emacs helm"))
(helm-org-rifle))
(elp-results)
(elp-restore-all)
(buffer-substring-no-properties (point-min) (point-max)))
This function is working correctly, returning the number of sources that it should.
This function works correctly and pretty quickly.
However, Helm seems to be calling this function, the :candidates
function…sometimes 10 times per buffer, sometimes less, like this time where it did it 6 times for each buffer (input was “emacs”):
Evaluate this elisp code block on your system? (y or n) y executing Elisp code block... This many sources: 18 ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org ARGH called for buffer: test.org ARGH called for buffer: README.org\helm-org-rifle ARGH called for buffer: inbox.org ARGH called for buffer: README.org\org-bookmark-heading ARGH called for buffer: main.org ARGH called for buffer: school.org ARGH called for buffer: sparky.org ARGH called for buffer: prayers.org ARGH called for buffer: calendar.org ARGH called for buffer: log.org ARGH called for buffer: people.org ARGH called for buffer: bible.org ARGH called for buffer: books.org ARGH called for buffer: misc.org ARGH called for buffer: posts.org ARGH called for buffer: quotes.org ARGH called for buffer: reference.org ARGH called for buffer: research.org Code block evaluation complete.
Okay, I think I see what it’s doing: Helm is calling the candidates function once for every character that is typed, plus one more time. When I type emacs
it calls it 6 times per buffer, and when I type e
it calls it twice per buffer. The :delay
works in that it doesn’t start getting candidates until that much time has elapsed after I’ve finished typing, but then it goes ahead and calls it for every character I typed, plus one.
Problem might be in helm-update
or helm-process-delayed-sources
…
(progn
(let ((buffers (remove-if 'helm-org-rifle-buffer-invisible-p (org-buffer-list nil t)))
(string "emacs helm";; (read-from-minibuffer "Words: ")
))
(dolist (p '("helm-" "org-" "string-" "s-"))
(elp-instrument-package p))
(dolist (buffer buffers)
(helm-org-rifle-get-candidates-in-buffer buffer string)))
(elp-results)
(elp-restore-all)
(buffer-substring-no-properties (point-min) (point-max)))