From bfd79e78ce6ad1cea2d612b025b402b3e6cf3517 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 10 May 2017 06:13:14 +0200 Subject: [PATCH] completion/ivy: fix +ivy/tasks, add :todo & +ivy:todo --- modules/completion/ivy/autoload/evil.el | 6 +++ modules/completion/ivy/autoload/ivy.el | 60 ++++++++++++++++++++++--- modules/completion/ivy/config.el | 5 +++ modules/private/hlissner/+commands.el | 2 +- 4 files changed, 67 insertions(+), 6 deletions(-) diff --git a/modules/completion/ivy/autoload/evil.el b/modules/completion/ivy/autoload/evil.el index 7fc0d3a0c..e3a9a47b1 100644 --- a/modules/completion/ivy/autoload/evil.el +++ b/modules/completion/ivy/autoload/evil.el @@ -40,3 +40,9 @@ session." "Invoke `swiper' with SEARCH, otherwise with the symbol at point." (interactive "") (swiper search)) + +;;;###autoload (autoload '+ivy:todo "completion/ivy/autoload/evil" nil t) +(evil-define-command +ivy:todo (&optional bang) + "An ex wrapper around `+ivy/tasks'." + (interactive "") + (+ivy/tasks bang)) diff --git a/modules/completion/ivy/autoload/ivy.el b/modules/completion/ivy/autoload/ivy.el index aae60ab0c..88475240b 100644 --- a/modules/completion/ivy/autoload/ivy.el +++ b/modules/completion/ivy/autoload/ivy.el @@ -76,12 +76,62 @@ limit to buffers in the current workspace." (string-match-p "\\`[\n[:blank:]]+\\'" it))) (cl-remove-duplicates kill-ring :test 'equal)))) +(defun +ivy--tasks-candidates () + "Generate a list of task tags (specified by `+ivy-task-tags') for +`+ivy/tasks'." + (let ((default-directory (if arg default-directory (doom-project-root))) + case-fold-search) + (mapcar (lambda (x) + (save-match-data + (string-match (concat "^\\([^:]+\\):\\([0-9]+\\):.+\\(" + (string-join (mapcar #'car +ivy-task-tags) "\\|") + "\\):?\\s-*\\(.+\\)") + x) + (let* (case-fold-search + (file (match-string 1 x)) + (line (match-string 2 x)) + (type (match-string 3 x)) + (desc (match-string 4 x))) + (format "%-5s %-90s %s:%s" + (propertize type 'face (cdr (assoc type +ivy-task-tags))) + (substring desc 0 (min 90 (length desc))) + (propertize file 'face 'font-lock-keyword-face) + (propertize line 'face 'font-lock-constant-face))))) + (split-string (shell-command-to-string + (format "rg -H -S --no-heading --line-number %s %s" + (concat " -- " + (shell-quote-argument (concat "\\s(" + (string-join (mapcar #'car +ivy-task-tags) "|") + ")([\\s:]|\([^)]+\):?)"))) + (if arg buffer-file-name "."))) + "\n" t)))) + +(defun +ivy--tasks-open-action (x) + "Jump to the file and line of the current task." + (let* ((spec (split-string (substring x 97) ":")) + (type (car (split-string x " "))) + (file (car spec)) + (line (string-to-number (cadr spec)))) + (with-ivy-window + (find-file (expand-file-name file (doom-project-root))) + (goto-char (point-min)) + (forward-line (1- line)) + (search-forward type (line-end-position) t) + (backward-char (length type)) + (recenter)))) + ;;;###autoload -(defun +ivy/tasks () - "Search through all TODO/FIXME tags in the current project using -`counsel-rg'." - (interactive) - (counsel-rg "\\(TODO|FIXME\\)\\s" (doom-project-root) "--case-sensitive -w")) +(defun +ivy/tasks (&optional arg) + "Search through all TODO/FIXME tags in the current project. If ARG, only +search current file. See `+ivy-task-tags' to customize what this searches for." + (interactive "P") + (ivy-read (format "Tasks (%s): " + (if arg + (concat "in: " (file-relative-name buffer-file-name)) + "project")) + (+ivy--tasks-candidates) + :action #'+ivy--tasks-open-action + :caller '+ivy/tasks)) ;;;###autoload (defun +ivy*counsel-ag-function (string base-cmd extra-ag-args) diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index 5765bfe55..0cf37edec 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -1,5 +1,10 @@ ;;; completion/ivy/packages.el +(defvar +ivy-task-tags '(("TODO" . warning) + ("FIXME" . error)) + "An alist of tags for `+ivy/tasks' to include in its search, whose CDR is the +face to render it with.") + (defmacro ivy-do-action! (action) "A factory function that returns an interactive lamba that sets the current ivy action and immediately runs it on the current candidate (ending the ivy diff --git a/modules/private/hlissner/+commands.el b/modules/private/hlissner/+commands.el index e179f6127..e315a974d 100644 --- a/modules/private/hlissner/+commands.el +++ b/modules/private/hlissner/+commands.el @@ -61,7 +61,7 @@ (ex! "build" '+eval/build) (ex! "debug" '+debug/run) (ex! "er[rors]" 'flycheck-list-errors) -(ex! "todo" '+ivy/tasks) +(ex! "todo" '+ivy:todo) ;; File operations (ex! "mv" '+evil:file-move)