Skip to content

Commit 2c0e621

Browse files
committed
refactored initlua
1 parent 0cb562a commit 2c0e621

File tree

3 files changed

+141
-95
lines changed

3 files changed

+141
-95
lines changed

lua/canter/init.lua

Lines changed: 133 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,152 @@
11
-- Helper functions
2+
-- recursive print table for debugging
3+
local function printTable(tbl, indent)
4+
local dbg_msg = ""
5+
indent = indent or 0
6+
for key, value in pairs(tbl) do
7+
local spacing = string.rep(" ", indent)
8+
if type(value) == "table" then
9+
dbg_msg = spacing .. key .. ":"
10+
print(dbg_msg)
11+
printTable(value, indent + 1)
12+
else
13+
dbg_msg = spacing .. key .. ": " .. tostring(value)
14+
print(dbg_msg)
15+
end
16+
end
17+
end
18+
219
local function get_current_file_path()
3-
local filepath = vim.fn.expand("%:p:.") -- Get the current filepath, relative to current dir if possible
4-
return vim.fn.shellescape(filepath)
20+
local filepath = vim.fn.expand("%:p:.") -- Get the current filepath, relative to current dir if possible
21+
return filepath
22+
end
23+
24+
local function get_shebang()
25+
local first_line = vim.fn.getline(1)
26+
if string.match(first_line, "^#!/") then -- If first line starts with shebang (e.g. #!/usr/bin/env node)
27+
return first_line
28+
end
29+
return nil
30+
end
31+
32+
local function build_command(filepath, shebang, opts)
33+
local safe_filepath = vim.fn.shellescape(filepath)
34+
local file_extension = vim.fn.fnamemodify(filepath, ":e")
35+
-- local file_extension = vim.fn.expand("%:e")
36+
local runner = opts.runners[file_extension] -- Get runner
37+
local cmd = nil
38+
39+
if shebang then
40+
if string.match(filepath, "^/") then
41+
cmd = safe_filepath
42+
else -- if filepath is relative add "./"
43+
cmd = "./" .. safe_filepath
44+
end
45+
elseif runner then -- if we have a valid runner for the filetype
46+
cmd = runner .. " " .. safe_filepath -- Runner and filepath (e.g. "node script.js")
47+
end
48+
49+
return cmd
50+
end
51+
52+
local function execute_command(cmd, wait, opts)
53+
if wait then
54+
Snacks.terminal.open()
55+
vim.cmd("startinsert")
56+
vim.api.nvim_input(cmd)
57+
else
58+
Snacks.terminal(cmd, opts.Snacks_terminal_opts)
59+
vim.cmd("startinsert")
60+
end
561
end
662

763
---@param runImmediately (boolean)
864
---@param opts (table)
965
local function run_current_file(runImmediately, opts)
10-
local filepath = get_current_file_path()
11-
local file_extension = vim.fn.expand("%:e")
12-
local first_line = vim.fn.getline(1)
13-
14-
local runners = opts.runners
15-
local snacks_opts = opts.Snacks_terminal_opts
16-
17-
if string.match(first_line, "^#!/") then -- If first line starts with shebang (e.g. #!/usr/bin/env node)
18-
vim.cmd("!chmod +x " .. filepath) -- Make the file executable
19-
20-
if not string.match(filepath, "/") then -- if filepath is relative add "./"
21-
filepath = "./" .. filepath
22-
end
23-
24-
if runImmediately then
25-
Snacks.terminal(filepath, snacks_opts)
26-
vim.cmd("startinsert")
27-
else
28-
Snacks.terminal.open()
29-
vim.cmd("startinsert")
30-
vim.api.nvim_input(filepath)
31-
end
32-
elseif runners[file_extension] then -- if we have a valid runner for the filetype
33-
local runner = runners[file_extension] -- Get runner
34-
local cmd = runner .. " " .. filepath -- Runner and filepath (e.g. node script.js)
35-
if runImmediately then
36-
Snacks.terminal(cmd, snacks_opts)
37-
vim.cmd("startinsert")
38-
else
39-
Snacks.terminal.open()
40-
vim.cmd("startinsert")
41-
vim.api.nvim_input(cmd)
42-
end
43-
else
44-
vim.cmd("echo 'Error: Could not resolve interpreter or find shebang line.'")
45-
end
66+
local wait = not runImmediately -- refactor this
67+
68+
local filepath = get_current_file_path()
69+
local shebang = get_shebang()
70+
local cmd = build_command(filepath, shebang, opts)
71+
72+
if not cmd then
73+
local error_msg =
74+
"Error (Canter): Could not resolve runner or shebang line.\nTry adding a runner for this filetype to your config opts."
75+
vim.api.nvim_echo({ { error_msg, "ErrorMsg" } }, true, {})
76+
return
77+
end
78+
79+
if shebang then
80+
vim.cmd("!chmod +x " .. filepath) -- Make the file executable
81+
end
82+
83+
execute_command(cmd, wait, opts)
4684
end
4785

4886
local default_opts = { -- default options
49-
runners = {},
50-
Snacks_terminal_opts = {
51-
win = {
52-
position = "bottom",
53-
relative = "editor"
54-
},
55-
interactive = false
56-
},
57-
keymaps = {
58-
["<leader><cr><cr>"] = {
59-
cmd = ":CanterRun<CR>",
60-
desc = "Run current file (Auto)"
61-
},
62-
["<leader><cr>w"] = {
63-
cmd = ":CanterWait<CR>",
64-
desc = "Run current file (Wait)"
65-
}
66-
}
87+
runners = {},
88+
Snacks_terminal_opts = {
89+
win = {
90+
position = "bottom",
91+
relative = "editor",
92+
},
93+
interactive = false,
94+
},
95+
keymaps = {
96+
["<leader><cr><cr>"] = {
97+
cmd = ":CanterRun<CR>",
98+
desc = "Run current file (Auto)",
99+
},
100+
["<leader><cr>w"] = {
101+
cmd = ":CanterWait<CR>",
102+
desc = "Run current file (Wait)",
103+
},
104+
},
67105
}
68106

69107
local M = {}
70108

71109
---@param user_opts (table | nil)
72110
function M.setup(user_opts)
73-
user_opts = user_opts or {}
74-
local opts = vim.tbl_deep_extend("force", default_opts, user_opts)
75-
76-
local function run_current_file_auto()
77-
run_current_file(true, opts) -- Pass the entire opts table, not just runners
78-
end
79-
local function run_current_file_wait()
80-
run_current_file(false, opts) -- Pass the entire opts table, not just runners
81-
end
82-
83-
-- Add keymaps if configured
84-
if opts.keymaps then
85-
for key, mapping in pairs(opts.keymaps) do
86-
vim.keymap.set('n', key, mapping.cmd, {
87-
desc = mapping.desc,
88-
silent = true
89-
})
90-
end
91-
end
92-
93-
-- Register which-key group
94-
local ok, wk = pcall(require, "which-key")
95-
if ok then
96-
wk.add({{
97-
"<leader><cr>",
98-
group = "Canter (run code)"
99-
}})
100-
end
101-
102-
local commands = {
103-
CanterRun = run_current_file_auto,
104-
CanterWait = run_current_file_wait
105-
}
106-
107-
for cmd, fn in pairs(commands) do
108-
vim.api.nvim_create_user_command(cmd, fn, {
109-
nargs = 0
110-
})
111-
end
111+
user_opts = user_opts or {}
112+
-- merge user opts with defaults
113+
local opts = vim.tbl_deep_extend("force", default_opts, user_opts)
114+
115+
local function run_current_file_auto()
116+
run_current_file(true, opts)
117+
end
118+
local function run_current_file_wait()
119+
run_current_file(false, opts)
120+
end
121+
122+
-- Add keymaps if configured
123+
if opts.keymaps then
124+
for key, mapping in pairs(opts.keymaps) do
125+
vim.keymap.set("n", key, mapping.cmd, {
126+
desc = mapping.desc,
127+
silent = true,
128+
})
129+
end
130+
end
131+
132+
-- Register which-key group
133+
local ok, wk = pcall(require, "which-key")
134+
if ok then
135+
wk.add({
136+
{ "<leader><cr>", group = "Canter (run code)" },
137+
})
138+
end
139+
140+
local commands = {
141+
CanterRun = run_current_file_auto,
142+
CanterWait = run_current_file_wait,
143+
}
144+
145+
for cmd, fn in pairs(commands) do
146+
vim.api.nvim_create_user_command(cmd, fn, {
147+
nargs = 0,
148+
})
149+
end
112150
end
113151

114152
return M

test.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/usr/bin/env node
2+
3+
console.log("Hello, world!");
4+
// "Hello, world!"

test.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// #!/usr/bin/env node
2+
3+
console.log("Hello, world!");
4+
// "Hello, world!"

0 commit comments

Comments
 (0)