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

Make directory traversing smart #11

Merged
merged 5 commits into from
Feb 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
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