From ef230103262eada4e8f4a2ce0228b43c8e9613a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Delalande?= Date: Thu, 20 Nov 2025 05:18:17 +0100 Subject: [PATCH] Add tag filtering functionality to RSpec mode This commit adds four functions: - rspec-verify-tagged: only verify the tag(s) in the current file - rspec-verify-all-tagged: only verify the tag(s) in the whole suite - rspec-dired-verify-tagged: only verify the tag(s) in the current dired scope - rspec-dired-verify-single-tagged: only verify the tag(s) in the currently marked files It also adds the corresponding key bindings The functions prompt the user for one or more tags following the rspec syntax and appends them to the rspec command. See https://rspec.info/features/3-12/rspec-core/command-line/tag/ --- README.md | 45 +++++++++++++++++++++++------------------- rspec-mode.el | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 954e442..3647d64 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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. diff --git a/rspec-mode.el b/rspec-mode.el index ff233b9..46815cf 100644 --- a/rspec-mode.el +++ b/rspec-mode.el @@ -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) @@ -115,6 +117,10 @@ (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) @@ -122,11 +128,19 @@ (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) @@ -466,6 +480,19 @@ 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-verify-tags () + "Run current spec file, filtered by one or multiple tags." + (interactive) + (rspec--autosave-buffer-maybe) + (let* ((tags (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history nil nil nil 'rspec-tags-history))) + (rspec-run-single-file (rspec-spec-file-for (buffer-file-name)) + (concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags " ") + " " + (rspec-core-options))))) + (defun rspec-verify-matching () "Run the specs related to the current buffer. This is more fuzzy that a simple verify." @@ -517,17 +544,44 @@ in long-running test suites." (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 (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history nil nil nil 'rspec-tags-history)) + (rspec-command-options (concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags " ") + " " + (rspec-core-options)))) + (rspec-dired-verify))) + (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/spec at point, filtered by one or multiple tags." + (interactive) + (let* ((tags (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history nil nil nil 'rspec-tags-history)) + (rspec-command-options (concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags " ") + " " + (rspec-core-options)))) + (rspec-dired-verify-single))) + (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 project specs, filtered by one or multiple tags." + (interactive) + (let* ((tags (completing-read-multiple "Select tags (separated by comma): " rspec-tags-history nil nil nil 'rspec-tags-history)) + (rspec-command-options (concat (mapconcat #'(lambda (tag) (format " --tag %s" tag)) tags " ") + " " + (rspec-core-options)))) + (rspec-verify-all))) + (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