Skip to content

Commit

Permalink
Add new config option: ignored_dirs_on_jump (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
mogulla3 authored Oct 15, 2023
1 parent 7887b4b commit 3046821
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 76 deletions.
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ require('rspec').setup(
-- If none of the above, use "progress".
formatter = "progress",

-- Whether or not to focus on a window when `RSpecShowLastResult` command executed.
-- Whether or not to focus on a window when `ShowLastSpecResult` command executed.
focus_on_last_spec_result_window = true,

-- Whether or not to open the quickfix window when the spec fails.
Expand All @@ -78,6 +78,19 @@ require('rspec').setup(
-- Command to open the file to jump to.
-- Examples of other alternatives: vsplit, split, tabedit
jump_command = "edit",

-- Directories to ignore when jumping with the RSpecJump command
--
-- For example, suppose you want to jump from "src/foo/bar.rb" to "spec/foo/bar_spec.rb".
--
-- However, rspec.nvim would by default try to find "spec/src/foo/bar_spec.rb" and return an error saying it cannot be found.
-- In this case, you would want to treat the "src/" directory as equivalent to the "app/" in Rails or the "lib/" directory in a gem.
--
-- So you can specify the following for the ignored_dirs_on_jump option, which will give you the expected jumps.
-- ```
-- ignored_dirs_on_jump = { "src" }
-- ```
ignored_dirs_on_jump = {},
)
```

Expand Down
13 changes: 13 additions & 0 deletions lua/rspec/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ local default_config = {
-- Command to open the file to jump to.
-- Examples of other alternatives: vsplit, split, tabedit
jump_command = "edit",

-- Directories to ignore when jumping with the RSpecJump command
--
-- For example, suppose you want to jump from "src/foo/bar.rb" to "spec/foo/bar_spec.rb".
--
-- However, rspec.nvim would by default try to find "spec/src/foo/bar_spec.rb" and return an error saying it cannot be found.
-- In this case, you would want to treat the "src/" directory as equivalent to the "app/" in Rails or the "lib/" directory in a gem.
--
-- So you can specify the following for the ignored_dirs_on_jump option, which will give you the expected jumps.
-- ```
-- ignored_dirs_on_jump = { "src" }
-- ```
ignored_dirs_on_jump = {},
}

local Config = {}
Expand Down
137 changes: 62 additions & 75 deletions lua/rspec/jumper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,40 @@ local config = require("rspec.config")

local Jumper = {}

local to_spec_patterns = {
simple = {
pattern = [[^\(.*/\)\?\(.*\).rb$]],
local rails_spec_patterns = {
default = {
pattern = [[^app/\(.*/\)\?\(.*\).rb$]],
replace = "spec/\\1\\2_spec.rb",
},
gem = {
pattern = [[^lib/\(.*/\)\?\(.*\).rb$]],
replace = "spec/\\1\\2_spec.rb",
controller = {
pattern = [[^app/controllers/\(.*/\)\?\(.*\)_controller.rb$]],
replace = "spec/requests/\\1\\2_spec.rb",
},
rails = {
default = {
pattern = [[^app/\(.*/\)\?\(.*\).rb$]],
replace = "spec/\\1\\2_spec.rb",
},
controller = {
pattern = [[^app/controllers/\(.*/\)\?\(.*\)_controller.rb$]],
replace = "spec/requests/\\1\\2_spec.rb",
},
view = {
pattern = [[^app/views/\(.*/\)\?\(.*\)$]],
replace = "spec/views/\\1\\2_spec.rb",
},
view = {
pattern = [[^app/views/\(.*/\)\?\(.*\)$]],
replace = "spec/views/\\1\\2_spec.rb",
},
}

local to_product_code_patterns = {
simple = {
local rails_product_code_patterns = {
default = {
pattern = [[^spec/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "\\1\\2.rb",
replace = "app/\\1\\2.rb",
},
gem = {
pattern = [[^spec/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "lib/\\1\\2.rb",
controller = {
pattern = [[^spec/requests/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "app/controllers/\\1\\2_controller.rb",
},
rails = {
default = {
pattern = [[^spec/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "app/\\1\\2.rb",
},
controller = {
pattern = [[^spec/requests/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "app/controllers/\\1\\2_controller.rb",
},
view = {
pattern = [[^spec/views/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "app/views/\\1\\2",
},
view = {
pattern = [[^spec/views/\(.*/\)\?\(.*\)_spec.rb$]],
replace = "app/views/\\1\\2",
},
}

local function get_ignored_dirs()
return vim.list_extend({ "lib" }, config.ignored_dirs_on_jump)
end

--- Trace back the parent directory from bufname and infer the root path of the project.
---
--- example:
Expand Down Expand Up @@ -81,11 +65,11 @@ end
---@param project_root string
---@return string
local function get_relative_pathname_from_project_root(bufname, project_root)
local bufpath = vim.split(bufname, "/")
local buf_path = vim.split(bufname, "/")
local project_root_path = vim.split(project_root, "/")
local relative_path = vim.list_slice(bufpath, #project_root_path + 1)
local buf_relative_path = vim.list_slice(buf_path, #project_root_path + 1)

return table.concat(relative_path, "/")
return table.concat(buf_relative_path, "/")
end

---@param subject string
Expand All @@ -95,40 +79,40 @@ local function sub(subject, params)
return vim.fn.substitute(subject, params.pattern, params.replace, "")
end

---@param relative_product_code_path string
---@param product_code_relative_path string
---@return string[]
local function infer_rails_spec_paths(relative_product_code_path)
local dir_entries = vim.split(relative_product_code_path, "/")
local function infer_rails_spec_paths(product_code_relative_path)
local dir_entries = vim.split(product_code_relative_path, "/")

-- TODO: Routing specs, Generator specs
local results
if dir_entries[2] == "controllers" then
results = {
sub(relative_product_code_path, to_spec_patterns.rails.controller), -- Request specs
sub(relative_product_code_path, to_spec_patterns.rails.default), -- Controller specs
sub(product_code_relative_path, rails_spec_patterns.controller), -- Request specs
sub(product_code_relative_path, rails_spec_patterns.default), -- Controller specs
}
elseif dir_entries[2] == "views" then
results = { sub(relative_product_code_path, to_spec_patterns.rails.view) }
results = { sub(product_code_relative_path, rails_spec_patterns.view) }
else
results = { sub(relative_product_code_path, to_spec_patterns.rails.default) }
results = { sub(product_code_relative_path, rails_spec_patterns.default) }
end

return results
end

---@param relative_spec_path string
---@param spec_relative_path string
---@return string[]
local function infer_rails_product_code_paths(relative_spec_path)
local dir_entries = vim.split(relative_spec_path, "/")
local function infer_rails_product_code_paths(spec_relative_path)
local dir_entries = vim.split(spec_relative_path, "/")

-- TODO: Routing specs, Generator specs
local results
if dir_entries[2] == "requests" then
results = { sub(relative_spec_path, to_product_code_patterns.rails.controller) }
results = { sub(spec_relative_path, rails_product_code_patterns.controller) }
elseif dir_entries[2] == "views" then
results = { sub(relative_spec_path, to_product_code_patterns.rails.view) }
results = { sub(spec_relative_path, rails_product_code_patterns.view) }
else
results = { sub(relative_spec_path, to_product_code_patterns.rails.default) }
results = { sub(spec_relative_path, rails_product_code_patterns.default) }
end

return results
Expand All @@ -141,23 +125,26 @@ end
---@param project_root string
---@return string[]
local function infer_spec_paths(bufname, project_root)
local relative_path = get_relative_pathname_from_project_root(bufname, project_root)
local current_product_code_relative_path = get_relative_pathname_from_project_root(bufname, project_root)
local inferred_spec_relative_paths

local relative_spec_paths
if vim.startswith(relative_path, "app/") then
relative_spec_paths = infer_rails_spec_paths(relative_path)
elseif vim.startswith(relative_path, "lib/") then
relative_spec_paths = { sub(relative_path, to_spec_patterns.gem) }
if vim.startswith(current_product_code_relative_path, "app/") then
inferred_spec_relative_paths = infer_rails_spec_paths(current_product_code_relative_path)
else
relative_spec_paths = { sub(relative_path, to_spec_patterns.simple) }
inferred_spec_relative_paths = {
sub(current_product_code_relative_path, {
pattern = [[^\(]] .. table.concat(get_ignored_dirs(), [[/\|]]) .. [[/\)\?\(.*/\)\?\(.*\).rb$]],
replace = "spec/\\2\\3_spec.rb",
})
}
end

local results = {}
for _, relative_spec_path in pairs(relative_spec_paths) do
table.insert(results, project_root .. "/" .. relative_spec_path)
local inferred_spec_paths = {}
for _, relative_spec_path in pairs(inferred_spec_relative_paths) do
table.insert(inferred_spec_paths, project_root .. "/" .. relative_spec_path)
end

return results
return inferred_spec_paths
end

--- Infer product code paths from the current spec path.
Expand All @@ -167,25 +154,25 @@ end
---@param project_root string
---@return string[]
local function infer_product_code_paths(bufname, project_root)
local relative_path = get_relative_pathname_from_project_root(bufname, project_root)
local relative_product_code_paths = {}
local current_spec_relative_path = get_relative_pathname_from_project_root(bufname, project_root)
local inferred_product_code_relative_paths = {}

if vim.fn.isdirectory(project_root .. "/app") == 1 then
vim.list_extend(relative_product_code_paths, infer_rails_product_code_paths(relative_path))
vim.list_extend(inferred_product_code_relative_paths, infer_rails_product_code_paths(current_spec_relative_path))
end

if vim.fn.isdirectory(project_root .. "/lib") == 1 then
table.insert(relative_product_code_paths, sub(relative_path, to_product_code_patterns.gem))
for _, ignored_dir in ipairs(get_ignored_dirs()) do
table.insert(inferred_product_code_relative_paths, sub(current_spec_relative_path, { pattern = [[^spec/\(.*/\)\?\(.*\)_spec.rb$]], replace = ignored_dir .. "/" .. "\\1\\2.rb" }))
end

table.insert(relative_product_code_paths, sub(relative_path, to_product_code_patterns.simple))
table.insert(inferred_product_code_relative_paths, sub(current_spec_relative_path, { pattern = [[^spec/\(.*/\)\?\(.*\)_spec.rb$]], replace = "\\1\\2.rb" }))

local results = {}
for _, relative_product_code_path in pairs(relative_product_code_paths) do
table.insert(results, project_root .. "/" .. relative_product_code_path)
local inferred_product_code_paths = {}
for _, relative_product_code_path in pairs(inferred_product_code_relative_paths) do
table.insert(inferred_product_code_paths, project_root .. "/" .. relative_product_code_path)
end

return results
return inferred_product_code_paths
end

--- Jump to the path passed in the argument
Expand Down

0 comments on commit 3046821

Please sign in to comment.