Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add org src block feature #411

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 108 additions & 23 deletions dumb-jump.el
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,12 @@ or most optimal searcher."
:group 'dumb-jump
:type 'string)

(defcustom dumb-jump-search-type-org-only-org
t
"If non nil restrict type ag/rg to org file.
If nil add also the language type of current src block"
:group 'dumb-jump
:type 'boolean)

(defcustom dumb-jump-find-rules
'((:type "function" :supports ("ag" "grep" "rg" "git-grep") :language "elisp"
Expand Down Expand Up @@ -2038,9 +2044,9 @@ for user to select. Filters PROJ path from files for display."
((and (eq dumb-jump-selector 'helm) (fboundp 'helm))
(helm :sources
(helm-make-source "Jump to: " 'helm-source-sync
:action '(("Jump to match" . dumb-jump-result-follow))
:candidates (-zip choices results)
:persistent-action 'dumb-jump-helm-persist-action)
:action '(("Jump to match" . dumb-jump-result-follow))
:candidates (-zip choices results)
:persistent-action 'dumb-jump-helm-persist-action)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These seem to only be whitespace changes?

:buffer "*helm dumb jump choices*"))
(t
(dumb-jump-to-selected results choices (popup-menu* choices))))))
Expand All @@ -2067,27 +2073,101 @@ to keep looking for another root."

(defun dumb-jump-get-language (file)
"Get language from FILE extension and then fallback to using 'major-mode' name."
(let* ((languages (-distinct
(--map (plist-get it :language)
dumb-jump-find-rules)))
(language (or (dumb-jump-get-language-from-mode)
(let* ((language (or (dumb-jump-get-language-from-mode)
(dumb-jump-get-language-by-filename file)
(dumb-jump-get-mode-base-name))))
(if (member language languages)
; src edit buffer ? org-edit-src-exit
(if (and (fboundp 'org-src-edit-buffer-p)
(org-src-edit-buffer-p))
;; set the composite language
(let* ((beg org-src--beg-marker)
(source-buffer (marker-buffer beg)))
(with-current-buffer source-buffer
(setq language (dumb-jump-get-language-in-org)))
;; save+exit the sub-editing buffer and search in project
(org-edit-src-exit))
(if (string= language "org")
(setq language (dumb-jump-get-language-in-org))))
(if (member language (-distinct
(--map (plist-get it :language)
dumb-jump-find-rules)))
language
(format ".%s file" (or (file-name-extension file) "")))))

(defun dumb-jump-get-language-in-org ()
"In org mode, if inside a src block return
associated language or org when outside a src block."
(let ((lang (nth 0 (org-babel-get-src-block-info))))
; if lang exists then create a composite language
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a ;; comment here, the indentation if unnecessary.

(if lang
(dumb-jump-make-composite-language
"org"
(if (dumb-jump-get-language-from-aliases lang)
(dumb-jump-get-language-from-aliases lang) lang)
"org" "org" "org")
"org")))

(defun dumb-jump-add-language-to-proplist (newlang proplist lang)
"Return nil if NEWLANG is already in PROPLIST or (if not)
return a new proplist. The new proplis is PROPLIS
where a NEWLANG plist(s) is (are) added to PROPLIST.
The plist(s) value of NEWLANG is (are) copied from
those of LANG and LANG is replaced by NEWLANG."
(let ((alreadyuptodate
(--filter (string= newlang (plist-get it :language))
proplist)))
(if alreadyuptodate
nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop the let here and use an unless instead of if.

(--splice
(string= lang (plist-get it :language))
(list it (plist-put (copy-tree it) :language newlang))
proplist))))

(defun dumb-jump-make-composite-language (mode lang extension agtype rgtype)
"Concat one MODE (usually the string org) with a LANG (c or python or etc)
to make a composite language of the form cPLUSorg or pythonPLUSorg or etc.
Modify `dumb-jump-find-rules' and `dumb-jump-language-file-exts' accordingly
(using EXTENSION AGTYPE RGTYPE)"
(let* ((complang (concat lang "PLUS" mode))
(alreadyextension (--filter (and
(string= complang (plist-get it :language))
(string= extension (plist-get it :ext))
(string= agtype (plist-get it :agtype))
(string= rgtype (plist-get it :rgtype)))
dumb-jump-language-file-exts))
(newfindrule (dumb-jump-add-language-to-proplist complang dumb-jump-find-rules lang))
(newfileexts (dumb-jump-add-language-to-proplist complang dumb-jump-language-file-exts lang)))
;; add (if needed) composite language to dumb-jump-find-rules
(if newfindrule
(set-default 'dumb-jump-find-rules newfindrule))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A when is preferable to a single if used for side effects.

;; add (if needed) composite language to dumb-jump-language-file-exts
(if (not dumb-jump-search-type-org-only-org)
(if newfileexts
(set-default 'dumb-jump-language-file-exts newfileexts)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, just with unless.

;; add (if needed) a new extension to dumb-jump-language-file-exts
(if (not alreadyextension)
(set-default 'dumb-jump-language-file-exts
(cons `(:language ,complang :ext ,extension :agtype ,agtype :rgtype ,rgtype)
dumb-jump-language-file-exts)))
complang))

(defun dumb-jump-get-language-from-aliases (lang)
"Extract the lang from aliases."
(let* ((lookup '(sh "shell" shell "shell" cperl "perl"
matlab "matlab" octave "matlab"
emacs-lisp "elisp" elisp "elisp"
R "r" r "r"))
(result (plist-get lookup (intern lang))))
(if result result nil)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if is redundant, but I'd also change the entire function to use assoc/alist-get or cond, instead of plist-get.

(alist-get lang '(("sh" . "shell") ("shell" . "shell") ...))


(defun dumb-jump-get-mode-base-name ()
"Get the base name of the mode."
(s-replace "-mode" "" (symbol-name major-mode)))

(defun dumb-jump-get-language-from-mode ()
"Extract the language from the 'major-mode' name. Currently just everything before '-mode'."
(let* ((lookup '(sh "shell" cperl "perl" matlab "matlab" octave "matlab"))
(m (dumb-jump-get-mode-base-name))
(result (plist-get lookup (intern m))))
result))

(let ((m (dumb-jump-get-mode-base-name)))
(dumb-jump-get-language-from-aliases m)))

(defun dumb-jump-get-language-by-filename (file)
"Get the programming language from the FILE."
Expand All @@ -2097,15 +2177,16 @@ to keep looking for another root."
(result (--filter
(s-ends-with? (concat "." (plist-get it :ext)) filename)
dumb-jump-language-file-exts)))
(when result
(when (and result (eq (length result) 1))
(plist-get (car result) :language))))

(defun dumb-jump-issue-result (issue)
"Return a result property list with the ISSUE set as :issue property symbol."
`(:results nil :lang nil :symbol nil :ctx-type nil :file nil :root nil :issue ,(intern issue)))

(defun dumb-jump-get-results (&optional prompt)
"Run dumb-jump-fetch-results if searcher installed, buffer is saved, and there's a symbol under point."
"Run dumb-jump-fetch-results if searcher installed, buffer is saved,
and there's a symbol under point."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first line of a docstring should be a complete sentence (checkdoc).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually missed this in a few of the last docstring, that should be fixed too.

(cond
((not (or (dumb-jump-ag-installed?)
(dumb-jump-rg-installed?)
Expand Down Expand Up @@ -2312,7 +2393,7 @@ current file."
;; multiple results so let the user pick from a list
;; unless the match is in the current file
(dumb-jump-handle-results results (plist-get info :file) proj-root (plist-get info :ctx-type)
look-for use-tooltip prefer-external))
look-for use-tooltip prefer-external lang))
((= result-count 0)
(dumb-jump-message "'%s' %s %s declaration not found." look-for (if (s-blank? lang) "with unknown language so" lang) (plist-get info :ctx-type))))))

Expand Down Expand Up @@ -2390,15 +2471,16 @@ given the LANG of the current file."
results)))

(defun dumb-jump-handle-results
(results cur-file proj-root ctx-type look-for use-tooltip prefer-external)
(results cur-file proj-root ctx-type look-for use-tooltip prefer-external &optional language)
"Handle the searchers results.
RESULTS is a list of property lists with the searcher's results.
CUR-FILE is the current file within PROJ-ROOT.
CTX-TYPE is a string of the current context.
LOOK-FOR is the symbol we're jumping for.
USE-TOOLTIP shows a preview instead of jumping.
PREFER-EXTERNAL will sort current file last."
(let* ((processed (dumb-jump-process-results results cur-file proj-root ctx-type look-for use-tooltip prefer-external))
PREFER-EXTERNAL will sort current file last
LANGUAGE is an optional language to pass to `dumb-jump-process-results'."
(let* ((processed (dumb-jump-process-results results cur-file proj-root ctx-type look-for use-tooltip prefer-external language))
(results (plist-get processed :results))
(do-var-jump (plist-get processed :do-var-jump))
(var-to-jump (plist-get processed :var-to-jump))
Expand All @@ -2421,16 +2503,18 @@ PREFER-EXTERNAL will sort current file last."
(dumb-jump-prompt-user-for-choice proj-root match-cur-file-front)))))

(defun dumb-jump-process-results
(results cur-file proj-root ctx-type _look-for _use-tooltip prefer-external)
(results cur-file proj-root ctx-type _look-for _use-tooltip prefer-external &optional language)
"Process (filter, sort, ...) the searchers results.
RESULTS is a list of property lists with the searcher's results.
CUR-FILE is the current file within PROJ-ROOT.
CTX-TYPE is a string of the current context.
LOOK-FOR is the symbol we're jumping for.
USE-TOOLTIP shows a preview instead of jumping.
PREFER-EXTERNAL will sort current file last."
PREFER-EXTERNAL will sort current file last.
LANGUAGE is the optional given language, if nil it will be found by
dumb-jump-get-language-by-filename."
"Figure which of the RESULTS to jump to. Favoring the CUR-FILE"
(let* ((lang (dumb-jump-get-language-by-filename cur-file))
(let* ((lang (if language language (dumb-jump-get-language-by-filename cur-file)))
(match-sorted (-sort (lambda (x y) (< (plist-get x :diff) (plist-get y :diff))) results))
(match-no-comments (dumb-jump-filter-no-start-comments match-sorted lang))

Expand Down Expand Up @@ -3091,7 +3175,8 @@ Using ag to search only the files found via git-grep literal symbol search."
(plist-get info :ctx-type)
look-for
nil
nil))
nil
lang))
(results (plist-get processed :results))
(do-var-jump (plist-get processed :do-var-jump))
(var-to-jump (plist-get processed :var-to-jump))
Expand Down
24 changes: 24 additions & 0 deletions test/data/proj1/src/org/test.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
* python
#+begin_src python :results none :session "ses1" :exports code :comments org
a=1
blabla(x)
b=1
c=2
d=3
e=3
def blabla(x):
return x
#+end_src

* R
#+begin_src R :file toto.png :results graphics file :session :exports both :comments org
plot(1, blabla(1))
blabla(2)
#+end_src

#+begin_src R :results none :session :exports code :comments org
blabla(x)
blabla <- function(x) {
x*x
}
#+end_src
36 changes: 36 additions & 0 deletions test/dumb-jump-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,42 @@
(mock (dumb-jump-goto-file-line * 6 18))
(should (string= cpp-file (dumb-jump-go)))))))

(ert-deftest dumb-jump-org-test1 ()
(let ((org-file (f-join test-data-dir-proj1 "src" "org" "test.org")))
(with-current-buffer (find-file-noselect org-file t)
(goto-char (point-min))
(forward-line 3)
(forward-char 2)
(with-mock
(mock (dumb-jump-goto-file-line * 9 6))
(should (string= org-file (dumb-jump-go)))))))

(ert-deftest dumb-jump-org-test2 ()
(let ((org-file (f-join test-data-dir-proj1 "src" "org" "test.org")))
(with-current-buffer (find-file-noselect org-file t)
(goto-char (point-min))
(forward-line 14)
(forward-char 10)
(with-mock
(mock (dumb-jump-goto-file-line * 21 2))
(should (string= org-file (dumb-jump-go)))))))

(ert-deftest dumb-jump-org-issue135 ()
(require 'org)
(require 'ob-python)
(org-babel-do-load-languages 'org-babel-load-languages '((python . t)))
(let ((org-file (f-join test-data-dir-proj1 "src" "org" "test.org")))
(with-current-buffer (find-file-noselect org-file t)
(goto-char (point-min))
(forward-line 3)
(forward-char 2)
(org-edit-src-code)
(with-mock
(mock (dumb-jump-goto-file-line * 9 6))
(should (string= org-file (dumb-jump-go)))))))



;; This test verifies that having ".dumbjumpignore" files in the two sub-projects will make it find
;; the "multiproj" folder as project root since it has a ".dumbjump" file. The two sub-projects have
;; a dummy ".git" folder to signify it as a repository that would normally become the root without
Expand Down