Skip to content

Commit

Permalink
Merge pull request #11 from psibi/directory-smart
Browse files Browse the repository at this point in the history
Make directory traversing smart
  • Loading branch information
psibi authored Feb 26, 2022
2 parents df699c9 + d605c3d commit f0431b4
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 32 deletions.
8 changes: 8 additions & 0 deletions Changelog.org
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
* 0.6

- Make the directory parsing smart. Now invoking justl from any
subdirectory should work.
- eshell executes from the directory where justfile is placed.
- Introduce buffer local variable ~~justl--justfile~~ which contains
the justfile location for a particular justl-mode buffer.

* 0.5

- Stop following symbolic link as it leads to a high CPU usage. This
Expand Down
116 changes: 87 additions & 29 deletions justl.el
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,44 @@ NAME is the buffer name."
(goto-char (point-max))
(insert (format "%s\n" str))))

(defvar-local justl--justfile nil
"Buffer local variable which points to the justfile.
If this is NIL, it means that no justfiles was found. In any
other cases, it's a known path.")

(defun justl--find-any-justfiles (dir filename)
"Find just FILENAME inside a sub-directory DIR or a parent directory.
Returns the absolute path if FILENAME exists or nil if no path
was found."
(let ((justfile-dir (f-traverse-upwards
(lambda (path)
(f-exists? (f-expand filename path)))
dir)))
(if justfile-dir
(f-expand filename justfile-dir)
(let ((justfile-paths (directory-files-recursively dir filename)))
(if justfile-paths
(car justfile-paths)
nil)))))

(defun justl--find-justfiles (dir)
"Find all the justfiles inside a directory.
"Find justfiles inside a sub-directory DIR or a parent directory.
DIR represents the directory where search will be carried
out. The search will be performed recursively."
(let ((case-fold-search t))
(directory-files-recursively dir "justfile")))
DIR represents the directory where search will be carried out.
It searches either for the filename justfile or .justfile"
(let ((justfile-path (justl--find-any-justfiles dir "justfile")))
(if justfile-path
(progn
(setq justl--justfile justfile-path)
justfile-path)
(let ((dot-justfile-path (justl--find-any-justfiles dir ".justfile")))
(if dot-justfile-path
(progn
(setq justl--justfile dot-justfile-path)
dot-justfile-path)
nil)))))

(defun justl--get-recipe-name (str)
"Compute the recipe name from the string STR."
Expand All @@ -175,7 +206,7 @@ out. The search will be performed recursively."
(make-justl-jarg :arg (nth 0 arg) :default (nth 1 arg))))

(defun justl--str-to-jarg (str)
"Convert string STR to liat of JARG.
"Convert string STR to list of JARG.
The string after the recipe name and before the build constraints
is expected."
Expand Down Expand Up @@ -247,6 +278,30 @@ STRING is the data returned by the PROC"
(defun justl--exec (process-name args)
"Utility function to run commands in the proper context and namespace.
PROCESS-NAME is an identifier for the process. Default to \"just\".
ARGS is a ist of arguments."
(when (equal process-name "")
(setq process-name "just"))
(let ((buffer-name justl--output-process-buffer)
(error-buffer (justl--process-error-buffer process-name))
(cmd (append (list justl-executable (justl--justfile-argument)) args)))
(when (get-buffer buffer-name)
(kill-buffer buffer-name))
(when (get-buffer error-buffer)
(kill-buffer error-buffer))
(justl--log-command process-name cmd)
(make-process :name process-name
:buffer buffer-name
:filter 'justl--xterm-color-filter
:sentinel #'justl--sentinel
:file-handler t
:stderr nil
:command cmd)
(pop-to-buffer buffer-name)))

(defun justl--exec-without-justfile (process-name args)
"Utility function to run commands in the proper context and namespace.
PROCESS-NAME is an identifier for the process. Default to \"just\".
ARGS is a ist of arguments."
(when (equal process-name "")
Expand Down Expand Up @@ -293,10 +348,15 @@ and output of process."
justl-executable)))))
(mapcar #'string-trim-right recipies)))

(defun justl--get-recipies-with-desc ()
"Return all the recipies with description."
(let* ((recipe-status (justl--exec-to-string-with-exit-code (format "%s --list --unsorted"
justl-executable)))
(defun justl--justfile-argument ()
"Provides justfile argument with the proper location."
(format "--justfile=%s" justl--justfile))

(defun justl--get-recipies-with-desc (justfile)
"Return all the recipies in JUSTFILE with description."
(let* ((recipe-status (justl--exec-to-string-with-exit-code
(format "%s --justfile=%s --list --unsorted"
justl-executable justfile)))
(just-status (nth 0 recipe-status))
(recipe-lines (split-string
(nth 1 recipe-status)
Expand All @@ -322,7 +382,7 @@ and output of process."
(interactive)
(let* ((recipies (completing-read "Recipies: " (justl--get-recipies)
nil nil nil nil "default")))
(justl--exec "just" (list recipies))))
(justl--exec-without-justfile "just" (list recipies))))

(defvar justl-mode-map
(let ((map (make-sparse-keymap)))
Expand All @@ -339,8 +399,9 @@ and output of process."

(defun justl--buffer-name ()
"Return justl buffer name."
(format "*just [%s]"
default-directory))
(let ((justfile (justl--find-justfiles default-directory)))
(format "*just [%s]"
(f-dirname justfile))))

(defvar justl--line-number nil
"Store the current line number to jump back after a refresh.")
Expand All @@ -362,14 +423,16 @@ and output of process."
"Opens eshell buffer but does not execute it.
Populates the eshell buffer with RECIPE name so that it can be
tweaked further by the user."
(let* ((eshell-buffer-name (format "justl - eshell - %s" recipe)))
(let* ((eshell-buffer-name (format "justl - eshell - %s" recipe))
(default-directory (f-dirname justl--justfile)))
(progn
(eshell)
(insert (format "just %s" recipe)))))

(defun justl--exec-with-eshell (recipe)
"Opens eshell buffer and execute the just RECIPE."
(let* ((eshell-buffer-name (format "justl - eshell - %s" recipe)))
(let* ((eshell-buffer-name (format "justl - eshell - %s" recipe))
(default-directory (f-dirname justl--justfile)))
(progn
(eshell)
(insert (format "just %s" recipe))
Expand All @@ -379,8 +442,7 @@ tweaked further by the user."
"Execute just recipe in eshell."
(interactive)
(let* ((recipe (justl--get-word-under-cursor))
(justfile (justl--find-justfiles default-directory))
(justl-recipe (justl--get-recipe-from-file (car justfile) recipe))
(justl-recipe (justl--get-recipe-from-file justl--justfile recipe))
(t-args (transient-args 'justl-help-popup))
(recipe-has-args (justl--jrecipe-has-args-p justl-recipe)))
(if recipe-has-args
Expand All @@ -398,8 +460,7 @@ tweaked further by the user."
"Open eshell with the recipe but do not execute it."
(interactive)
(let* ((recipe (justl--get-word-under-cursor))
(justfile (justl--find-justfiles default-directory))
(justl-recipe (justl--get-recipe-from-file (car justfile) recipe))
(justl-recipe (justl--get-recipe-from-file justl--justfile recipe))
(t-args (transient-args 'justl-help-popup))
(recipe-has-args (justl--jrecipe-has-args-p justl-recipe)))
(if recipe-has-args
Expand Down Expand Up @@ -456,8 +517,7 @@ tweaked further by the user."
"Execute just recipe."
(interactive)
(let* ((recipe (justl--get-word-under-cursor))
(justfile (justl--find-justfiles default-directory))
(justl-recipe (justl--get-recipe-from-file (car justfile) recipe))
(justl-recipe (justl--get-recipe-from-file justl--justfile recipe))
(t-args (transient-args 'justl-help-popup))
(recipe-has-args (justl--jrecipe-has-args-p justl-recipe)))
(if recipe-has-args
Expand All @@ -475,8 +535,7 @@ tweaked further by the user."
"Execute just recipe with arguments."
(interactive)
(let* ((recipe (justl--get-word-under-cursor))
(justfile (justl--find-justfiles default-directory))
(justl-recipe (justl--get-recipe-from-file (car justfile) recipe))
(justl-recipe (justl--get-recipe-from-file justl--justfile recipe))
(t-args (transient-args 'justl-help-popup))
(user-args (read-from-minibuffer
(format "Arguments seperated by spaces:"))))
Expand All @@ -491,10 +550,9 @@ tweaked further by the user."
"Go to the recipe on justfile."
(interactive)
(let* ((recipe (justl--get-word-under-cursor))
(justfile (justl--find-justfiles default-directory))
(justl-recipe (justl--get-recipe-from-file (car justfile) recipe)))
(justl-recipe (justl--get-recipe-from-file justl--justfile recipe)))
(progn
(find-file (car justfile))
(find-file justl--justfile)
(goto-char 0)
(when (re-search-forward (concat (justl-jrecipe-name justl-recipe) ".*:") nil t 1)
(let ((start (point)))
Expand Down Expand Up @@ -523,8 +581,8 @@ tweaked further by the user."
"Special mode for justl buffers."
(buffer-disable-undo)
(setq truncate-lines t)
(let ((justfiles (justl--find-justfiles default-directory))
(entries (justl--get-recipies-with-desc)))
(let* ((justfiles (justl--find-justfiles default-directory))
(entries (justl--get-recipies-with-desc justfiles)))
(if (or (null justfiles) (not (eq justl--list-command-exit-code 0)) )
(progn
(when (null justfiles)
Expand All @@ -540,7 +598,7 @@ tweaked further by the user."
(tabulated-list-init-header)
(tabulated-list-print t)
(hl-line-mode 1)
(message (concat "Just: " default-directory))
(message (concat "Just: " (f-dirname justfiles)))
(justl--jump-back-to-line))))

(provide 'justl)
Expand Down
14 changes: 11 additions & 3 deletions test/justl-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

(require 'justl)
(require 'ert)
(require 'f)

(ert-deftest justl--get-recipies-test ()
(should (equal
Expand Down Expand Up @@ -75,9 +76,6 @@
(justl--is-recipe-line-p " just --list")
nil)))

(ert-deftest justl--find-justfiles-test ()
(should (equal (length (justl--find-justfiles ".")) 1)))

(ert-deftest justl--get-recipe-from-file-test ()
(should (equal
(justl--get-recipe-from-file "./justfile" "default")
Expand Down Expand Up @@ -191,6 +189,16 @@
(kill-buffer (justl--buffer-name))
(kill-buffer justl--output-process-buffer))

(ert-deftest justl--find-justfiles-check ()
(should (equal (f-filename (justl--find-justfiles default-directory)) "justfile")))

(ert-deftest justl--get-recipies-with-desc-check ()
(let* ((justfile (justl--find-justfiles default-directory))
(recipies (justl--get-recipies-with-desc justfile)))
(should (member (list "default" "List all recipies") recipies))
(should (member (list "push" nil) recipies))
(should (member (list "push2" nil) recipies))))

;; (ert "justl--**")

(provide 'justl-test)
Expand Down

0 comments on commit f0431b4

Please sign in to comment.