Skip to content
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ use { -- pytrize {{{
config = 'require("pytrize").setup()',
} -- }}}
```
Requires [`plenary.nvim`](https://github.com/nvim-lua/plenary.nvim).
Requires [`plenary.nvim`](https://github.com/nvim-lua/plenary.nvim) and [`telescope.nvim`](https://github.com/nvim-telescope/telescope.nvim).

## Configuration
`require("pytrize").setup` takes an optional table of settings which currently have the default values:
Expand Down
8 changes: 4 additions & 4 deletions lua/pytrize/call_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ local ts = vim.treesitter
local ts_query = ts.query
local parse_query = ts_query.parse or ts_query.parse_query

local warn = require('pytrize.warn').warn
local notify = require('pytrize.notify')
local tbls = require('pytrize.tables')

local get_root = function(bufnr)
Expand Down Expand Up @@ -103,7 +103,7 @@ local get_entry = function(entry_idx, entry_node, params, bufnr)
local item_nodes = get_named_children(entry_node)
if #params ~= #item_nodes then
-- TODO warn here?
-- warn(string.format(
-- notify.warn(string.format(
-- 'number of items in entry tuple differ from number of params, %d items and %d params (line %d in %s)',
-- #item_nodes,
-- #params,
Expand Down Expand Up @@ -146,7 +146,7 @@ M.get_calls = function(bufnr)
local decorated_definition = call:parent():parent()
if decorated_definition:type() ~= 'decorated_definition' then
local row = call:start()
warn(string.format(
notify.warn(string.format(
"couldn't parse params (line %d)\n expected `decorated_definition`\n got `%s`",
row,
decorated_definition:type()
Expand All @@ -160,7 +160,7 @@ M.get_calls = function(bufnr)
local params_node = arguments:child(1)
if params_node:type() ~= 'string' then
local row = call:start()
warn(string.format(
notify.warn(string.format(
"couldn't parse params (line %d)\n expected `string`\n got `%s`",
row,
params_node:type()
Expand Down
16 changes: 16 additions & 0 deletions lua/pytrize/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ local function setup_commands()
vim.cmd('command PytrizeJumpFixture lua require("pytrize.api").jump_fixture()')
end


local warm_up_cache = require'pytrize.jump'.warm_up_cache

local function create_autocmd()
vim.api.nvim_create_autocmd({"BufRead", "BufWrite", "BufEnter"}, {
pattern = "*/tests*/*.py",
callback = function(args)
warm_up_cache():start()
end,
})
end


M.setup = function(opts)
if opts == nil then
opts = {}
Expand All @@ -17,6 +30,9 @@ M.setup = function(opts)
if not settings.settings.no_commands then
setup_commands()
end
if not settings.settings.no_autocmds then
create_autocmd()
end
end

return M
4 changes: 2 additions & 2 deletions lua/pytrize/input/init.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- local M = {}
--
-- local settings = require('pytrize.settings').settings
-- local warn = require('pytrize.warn').warn
-- local notify = require('pytrize.notify')
--
-- local function get_nui_handler()
-- return require('pytrize.input.nui').load()
Expand Down Expand Up @@ -29,7 +29,7 @@
--
-- local function get_input_handler()
-- if handler_getters[settings.preferred_input] == nil then
-- warn(string.format('unknown input choice "%s"', settings.preferred_input))
-- notify.warn(string.format('unknown input choice "%s"', settings.preferred_input))
-- return
-- end
-- local handler = handler_getters[settings.preferred_input]()
Expand Down
132 changes: 110 additions & 22 deletions lua/pytrize/jump/fixture.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ local M = {}
local Job = require('plenary.job')
local Path = require('plenary.path')

local warn = require('pytrize.warn').warn
local notify = require('pytrize.notify')
local open_file = require('pytrize.jump.util').open_file
local settings = require('pytrize.settings')

local conf = require('telescope.config').values
local pickers = require('telescope.pickers')
local finders = require('telescope.finders')
local sorters = require('telescope.sorters')
local actions = require('telescope.actions')
local action_state = require('telescope.actions.state')

local function normal(cmd)
vim.cmd(string.format('normal! %s', cmd))
Expand All @@ -19,55 +27,135 @@ local function get_word_under_cursor()
end

local function parse_raw_fixture_output(cwd, lines)
local fixtures = {}
local fixtures = setmetatable({}, M.meta_nested_sized())
local pattern = '^([%w_]*) .*%-%- (%S*):(%d*)$'
for _, line in ipairs(lines) do
local i, _, fixture, file, linenr = string.find(line, pattern)
if i ~= nil then
fixtures[fixture] = {
file = cwd / file,
linenr = tonumber(linenr),
}
file = cwd / file
linenr = tonumber(linenr)
fixtures[fixture][file:normalize()] = linenr
end
end
return fixtures
end

local function get_cwd()
return Path:new(vim.api.nvim_buf_get_name(0)):parent()
return Path:new(vim.fn.getcwd())
end

local function lookup_fixtures(callback)
local cwd = get_cwd()
Job:new({
local current_file_path = Path.new(vim.fn.expand("%:p"))
return Job:new({
command = 'pytest',
args = {'--fixtures', '-v'},
cwd = tostring(cwd),
args = {'--fixtures', '-v', current_file_path},
cwd = vim.fn.getcwd(),
on_exit = vim.schedule_wrap(function(j, return_val)
if return_val == 0 then
local fixtures = parse_raw_fixture_output(cwd, j:result())
callback(fixtures)
else
warn(string.format('failed to query fixtures: %s', table.concat(j:result(), '\n')))
notify.err(
string.format(
'failed to query fixtures, pytest response code: %d, result: %s, stderr: %s',
return_val,
table.concat(j:result(), '\n'),
table.concat(j:stderr_result(), '\n')
)
)
end
end),
}):sync()
})
end

M.meta_nested_sized = function ()
return {
__index = function (self1, key1)
local new_entry = {}
rawset(self1, key1, new_entry)
return new_entry
end,
}
end

local len = function(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
end

M.fixtures_cache = setmetatable({}, M.meta_nested_sized())

M.fixtures_cache.update = function(opts)
for fixture, locations in pairs(opts) do
for file, linenr in pairs(locations) do
M.fixtures_cache[fixture][file] = linenr
end
end
end

M.warm_up_cache = function()
return lookup_fixtures(function(fixtures)
M.fixtures_cache.update(fixtures)
end)
end

M._to_declaration = function(fixture, file, linenr)
open_file(tostring(file))
vim.api.nvim_win_set_cursor(0, {linenr, 0})
vim.fn.search(fixture)
end

M.to_declaration = function()
local fixture = get_word_under_cursor()
lookup_fixtures(function(fixtures)
local fixture_location = fixtures[fixture]
if fixture_location == nil then
warn(string.format('fixture "%s" not found', fixture))
if settings.settings.no_autocmds then
M.warm_up_cache():sync()
end
local locations = M.fixtures_cache[fixture]
if len(locations) > 0 then
if len(locations) == 1 then
for file, linenr in pairs(locations) do
M._to_declaration(fixture, file, linenr)
return
end
else
local file = fixture_location.file
local linenr = fixture_location.linenr
open_file(tostring(file))
vim.api.nvim_win_set_cursor(0, {linenr, 0})
vim.fn.search(fixture)
local entries = {}
for path, linenr in pairs(locations) do
table.insert(entries, {path = path, linenr = linenr})
end
pickers.new({}, {
prompt_title = 'Ambiguous fixture name, please choose a file',
finder = finders.new_table {
results = entries,
entry_maker = function(entry)
return {
path = entry.path,
linenr = entry.linenr,
value = tostring(entry.path),
display = entry.path .. ':' .. entry.linenr,
ordinal = entry.path .. ':' .. entry.linenr,
}
end,
},
sorter = sorters.get_generic_fuzzy_sorter(),
attach_mappings = function(prompt_bufnr, map)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local selection = action_state.get_selected_entry()
M._to_declaration(fixture, selection.path, selection.linenr)
end)
return true
end,
previewer = conf.file_previewer({}),
}):find()
return
end
end)
else
notify.warn(string.format('fixture "%s" not found', fixture))
end
end

return M
1 change: 1 addition & 0 deletions lua/pytrize/jump/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ local fixture = require('pytrize.jump.fixture')

M.to_param_declaration = param.to_declaration
M.to_fixture_declaration = fixture.to_declaration
M.warm_up_cache = fixture.warm_up_cache

return M
16 changes: 8 additions & 8 deletions lua/pytrize/jump/param.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ local nids = require('pytrize.nodeids')
local tbls = require('pytrize.tables')
local paths = require('pytrize.paths')
-- local prompt_files = require('pytrize.input').prompt_files
local warn = require('pytrize.warn').warn
local notify = require('pytrize.notify')
local open_file = require('pytrize.jump.util').open_file
local get_nodeids_path = require('pytrize.paths').get_nodeids_path
local min = require('pytrize.utils').min
Expand All @@ -29,7 +29,7 @@ local function query_file(func_name, callback)
end
end
if #files == 0 then
warn(string.format(
notify.warn(string.format(
'could not find the file for function `%s` when looking in %s, did you run the test?',
func_name,
get_nodeids_path(rootdir)
Expand All @@ -50,15 +50,15 @@ local function jump_to_nodeid_at_cursor(callback)
local line = vim.api.nvim_buf_get_lines(0, line_num - 1, line_num, 0)[1]
local i, _ = string.find(line, '%S*:?:?test_%w+%[.*') -- TODO how to check for zero or two :?
if i == nil then
warn("no nodeid under cursor")
notify.warn("no nodeid under cursor")
return
end
local nodeid = nids.parse_raw(line:sub(i))
local pattern_position = col_num + 1 - (i - 1) -- cursor relative to match
local param_position = pattern_position - nodeid.param_start_idx + 1 -- cursor relative to params
param_position = min(max(1, param_position), nodeid.params:len()) -- restrict it to be inside
if nodeid == nil then
warn("couldn't parse nodeid under cursor")
notify.warn("couldn't parse nodeid under cursor")
return
end
if nodeid.file == nil then
Expand All @@ -83,7 +83,7 @@ end
-- end
-- end
-- if found_call_spec == nil then
-- warn("couldn't find the declaration with param " .. param)
-- notify.warn("couldn't find the declaration with param " .. param)
-- return
-- end
-- return found_call_spec
Expand All @@ -104,7 +104,7 @@ end
-- local max = tbls.max_length(param_values[call_spec.func_name])
-- while true do
-- if list_idx > max then
-- warn("couldn't find the declaration matching id " .. param_id)
-- notify.warn("couldn't find the declaration matching id " .. param_id)
-- return
-- end
-- local pid = params.get_id(param_values[call_spec.func_name], call_spec.params, list_idx)
Expand Down Expand Up @@ -137,7 +137,7 @@ M.to_declaration = function()
local bufnr = 0
local original_buffer = vim.api.nvim_buf_get_name(bufnr)
if vim.fn.filereadable(nodeid.file) == 0 then
warn(string.format('file `%s` is not readable', nodeid.file))
notify.warn(string.format('file `%s` is not readable', nodeid.file))
return
end
open_file(nodeid.file)
Expand Down Expand Up @@ -166,7 +166,7 @@ M.to_declaration = function()
end
end
end
warn(string.format(
notify.warn(string.format(
'could not find the id `%s` of `%s` in file `%s`',
nodeid.params,
nodeid.func_name,
Expand Down
4 changes: 2 additions & 2 deletions lua/pytrize/nodeids.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
local M = {}

local split_once = require('pytrize.strings').split_once
local warn = require('pytrize.warn').warn
local notify = require('pytrize.notify')
local get_nodeids_path = require('pytrize.paths').get_nodeids_path

local function get_raw_nodeids(rootdir)
Expand Down Expand Up @@ -44,7 +44,7 @@ M.get = function(rootdir)
local nodeid = M.parse_raw(raw_nodeid)
if nodeid ~= nil then
if nodeid.file == nil then
warn('node id has no file')
notify.warn('node id has no file')
return {}
end
if nodeids[nodeid.file] == nil then
Expand Down
14 changes: 14 additions & 0 deletions lua/pytrize/notify.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
local M = {}

M.warn = function(msg)
msg = vim.fn.escape(msg, '"'):gsub('\\n', '\n')
-- vim.cmd(string.format('echohl WarningMsg | echo "Pytrize Warning: %s" | echohl None', msg))
vim.notify(string.format("Pytrize Warning: %s", msg), vim.log.levels.WARN)
end

M.err = function(msg)
msg = vim.fn.escape(msg, '"'):gsub('\\n', '\n')
vim.notify(string.format("Pytrize Error: %s", msg), vim.log.levels.ERROR)
end

return M
4 changes: 2 additions & 2 deletions lua/pytrize/params.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
--
-- local paths = require('pytrize.paths')
-- local nids = require('pytrize.nodeids')
-- local warn = require('pytrize.warn').warn
-- local notify = require('pytrize.warn')
--
-- M.get_values = function(param_order, bufnr)
-- local rootdir, file = paths.split_at_root(vim.api.nvim_buf_get_name(bufnr))
Expand All @@ -11,7 +11,7 @@
-- end
-- local nodeids = nids.get(rootdir)
-- if nodeids[file] == nil then
-- warn("no pytest cache for file " .. file .. " at root dir " .. rootdir)
-- notify.warn("no pytest cache for file " .. file .. " at root dir " .. rootdir)
-- return
-- end
-- local values_per_func = {}
Expand Down
Loading