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 the ability to run specs filtered by tags #217

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
45 changes: 25 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,22 @@ automatically when `ruby-mode` is started.

These keybindings are available in any Ruby source file:

Keybinding | Description |
------------|-------------------------------------------------------------------------------|
`C-c , v` | Verify the spec file associated with the current buffer |
`C-c , a` | Run spec for entire project |
`C-c , t` | Toggle back and forth between a spec and its target |
`C-c , e` | Toggle back and forth between a method and its examples in the spec file |
`C-c , 4 t` | Find in the other window the spec or the target file |
`C-c , 4 e` | As above, but try to navigate to the example or method corresponding to point |
`C-c , r` | Re-run the last verification process |
`C-c , y` | Yank the last verification command to clipboard |
`C-c , m` | Run all specs related to the current buffer |
`C-c , c` | Run the current spec and all after it |
`C-c , s` | Verify the example or method defined at point |
`C-c , f` | Re-run just the failed examples from the last run |
| Keybinding | Description |
| -------------- | ----------------------------------------------------------------------------------------- |
| `C-c , v` | Verify the spec file associated with the current buffer |
| `C-c , a` | Run spec for entire project |
| `C-c , t` | Toggle back and forth between a spec and its target |
| `C-c , e` | Toggle back and forth between a method and its examples in the spec file |
| `C-c , 4 t` | Find in the other window the spec or the target file |
| `C-c , 4 e` | As above, but try to navigate to the example or method corresponding to point |
| `C-c , r` | Re-run the last verification process |
| `C-c , y` | Yank the last verification command to clipboard |
| `C-c , m` | Run all specs related to the current buffer |
| `C-c , c` | Run the current spec and all after it |
| `C-c , s` | Verify the example or method defined at point |
| `C-c , f` | Re-run just the failed examples from the last run |
| `C-c , g v` | Verify the spec file associated with the current buffer, filtered by one or multiple tags |
| `C-c , g a` | Run spec for entire project, filtered by one or multiple tags |

### RSpec mode

Expand All @@ -61,12 +63,15 @@ Keybinding | Description |

These keybindings are available in Dired buffers:

Keybinding | Description |
-----------|----------------------------------------------------------------|
`C-c , v` | Run all specs in the current directory |
`C-c , s` | Run marked specs or spec at point (works with directories too) |
`C-c , a` | Run the 'spec' rake task for the project of the current file |
`C-c , r` | Re-run the last RSpec invocation |
Keybinding | Description |
-------------|--------------------------------------------------------------------------------------------------|
`C-c , v` | Run all specs in the current directory |
`C-c , s` | Run marked specs or spec at point (works with directories too) |
`C-c , a` | Run the 'spec' rake task for the project of the current file |
`C-c , r` | Re-run the last RSpec invocation |
`C-c , g v` | Run all specs in the current directory, filtered by one or multiple tags |
`C-c , g s` | Run marked specs or spec at point, filtered by one or multiple tags (works with directories too) |
`C-c , g a` | Run the 'spec' rake task for the project of the current file, filtered by one or multiple tags |

See `rspec-mode.el` for further usage.

Expand Down
66 changes: 65 additions & 1 deletion rspec-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
(define-prefix-command 'rspec-verifiable-mode-keymap)
(defvar rspec-mode-keymap)
(define-prefix-command 'rspec-mode-keymap)
(defvar rspec-verifiable-tags-mode-keymap)
(define-prefix-command 'rspec-verifiable-tags-mode-keymap)

(define-key rspec-verifiable-mode-keymap (kbd "v") 'rspec-verify)
(define-key rspec-verifiable-mode-keymap (kbd "a") 'rspec-verify-all)
Expand All @@ -115,18 +117,30 @@
(define-key rspec-verifiable-mode-keymap (kbd "s") 'rspec-verify-method)
(define-key rspec-verifiable-mode-keymap (kbd "f") 'rspec-run-last-failed)

(define-key rspec-verifiable-mode-keymap (kbd "g") rspec-verifiable-tags-mode-keymap)
(define-key rspec-verifiable-tags-mode-keymap (kbd "v") 'rspec-verify-tags)
(define-key rspec-verifiable-tags-mode-keymap (kbd "a") 'rspec-verify-tags-all)

(set-keymap-parent rspec-mode-keymap rspec-verifiable-mode-keymap)

(define-key rspec-mode-keymap (kbd "s") 'rspec-verify-single)
(define-key rspec-mode-keymap (kbd "d") 'rspec-toggle-example-pendingness)

(defvar rspec-dired-mode-keymap)
(define-prefix-command 'rspec-dired-mode-keymap)
(defvar rspec-dired-tags-mode-keymap)
(define-prefix-command 'rspec-dired-tags-mode-keymap)

(define-key rspec-dired-mode-keymap (kbd "v") 'rspec-dired-verify)
(define-key rspec-dired-mode-keymap (kbd "s") 'rspec-dired-verify-single)
(define-key rspec-dired-mode-keymap (kbd "a") 'rspec-verify-all)
(define-key rspec-dired-mode-keymap (kbd "r") 'rspec-rerun)

(define-key rspec-dired-mode-keymap (kbd "g") rspec-dired-tags-mode-keymap)
(define-key rspec-dired-tags-mode-keymap (kbd "v") 'rspec-dired-verify-tags)
(define-key rspec-dired-tags-mode-keymap (kbd "a") 'rspec-verify-tags-all)
(define-key rspec-dired-tags-mode-keymap (kbd "s") 'rspec-dired-verify-tags-single)

(defgroup rspec-mode nil
"RSpec minor mode."
:group 'languages)
Expand Down Expand Up @@ -466,6 +480,28 @@ buffers concurrently"
(rspec-run-single-file (rspec-spec-file-for (buffer-file-name))
(rspec-core-options)))

(defvar rspec-tags-history nil
"History of tags used in rspec-verify-tags-* functions.")

(defun rspec-add-tags-to-history (tags)
"Add TAGS to rspec-tags-history and optionally save to savehist."
(dolist (tag tags)
(add-to-history 'rspec-tags-history tag))
(when (and (featurep 'savehist) savehist-mode)
(unless (member 'rspec-tags-history savehist-additional-variables)
(add-to-list 'savehist-additional-variables 'rspec-tags-history))))

(defun rspec-verify-tags ()
"Run the specified spec, or the spec file for the current buffer, filtered by one or multiple tags."
(interactive)
(rspec--autosave-buffer-maybe)
(let* ((tags-string (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's better to use the history variable as the HIST argument in completing-read-multiple. It's the argument number 6. Doing that would automatically add the selected input to history as well (so rspec-add-tags-to-history won't be needed, I think).

I guess you could pass rspec-tags-history as TABLE and 'rspec-tags-history (quoted) as the history variable, so both saving to history works, and completion works as well.

(tags-list (if (stringp tags-string) (split-string tags-string ",\\s-*") tags-string)))
(rspec-add-tags-to-history tags-list)
(rspec-run-single-file (rspec-spec-file-for (buffer-file-name))
(concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags-list " "))
(rspec-core-options))))

(defun rspec-verify-matching ()
"Run the specs related to the current buffer.
This is more fuzzy that a simple verify."
Expand Down Expand Up @@ -513,21 +549,49 @@ in long-running test suites."
(declare-function dired-get-marked-files "dired")

(defun rspec-dired-verify ()
"Run all specs in the current directory."
"Run all specs in the current directory, filtered by one or multiple tags."
(interactive)
(rspec-run-single-file (dired-current-directory) (rspec-core-options)))

(defun rspec-dired-verify-tags ()
"Run all specs in the current directory, filtered by one or multiple tags."
(interactive)
(let* ((tags-string (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history))
(tags-list (if (stringp tags-string) (split-string tags-string ",\\s-*") tags-string)))
(rspec-add-tags-to-history tags-list)
(rspec-run-single-file (dired-current-directory)
(concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags-list " ") " "
(rspec-core-options)))))

(defun rspec-dired-verify-single ()
"Run marked specs or spec at point (works with directories too)."
(interactive)
(rspec-compile (dired-get-marked-files)
(rspec-core-options)))

(defun rspec-dired-verify-tags-single ()
"Run marked specs or spec at point, filtered by one or multiple tags (works with directories too)."
(interactive)
(let* ((tags-string (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history))
(tags-list (if (stringp tags-string) (split-string tags-string ",\\s-*") tags-string)))
(rspec-add-tags-to-history tags-list)
(rspec-compile (dired-get-marked-files)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here's a way to make this shorter: change the value of rspec-command-options locally (in the let form) and then call the "base" function. Like this:

(defun rspec-dired-verify-tags-single ()
  "Run marked specs or spec at point, filtered by one or multiple tags (works with directories too)."
  (interactive)
  (let* ((tags (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history))
         (rspec-command-options (concat rspec-command-options
                                        " "
                                        (mapconcat (lambda (tag) (format " --tag %s" tag)) tags " "))))
    (rspec-dired-verify-single)))

Same with the other commands.

(concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags-list " ") " "
(rspec-core-options)))))

(defun rspec-verify-all ()
"Run the `spec' rake task for the project of the current file."
(interactive)
(rspec-run (rspec-core-options)))

(defun rspec-verify-tags-all ()
"Run the `spec' rake task for the project of the current file, filtered by one or multiple tags."
(interactive)
(let* ((tags-string (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history))
(tags-list (if (stringp tags-string) (split-string tags-string ",\\s-*") tags-string)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

According to the docstring, completing-read-multiple always returns a list. So (stringp tags-string) should always be nil, and tags-string can be renamed to tags.

(rspec-add-tags-to-history tags-list)
(rspec-run (concat (rspec-core-options) (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags-list " ")))))

(defun rspec-toggle-spec-and-target ()
"Switch to the spec or the target file for the current buffer.
If the current buffer is visiting a spec file, switches to the
Expand Down