-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
398 lines (354 loc) · 11 KB
/
init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
local actions = require "telescope.actions"
local action_state = require "telescope.actions.state"
local pickers = require "telescope.pickers"
local finders = require "telescope.finders"
local conf = require("telescope.config").values
local utils = require("grep_app.utils")
local language_map = require("grep_app.language_map")
local grepapp = {}
grepapp.config = {}
grepapp.setup = function(ext_config, _)
-- ext_config overrides opts
ext_config = ext_config or {}
for k, v in pairs(ext_config) do
grepapp.config[k] = v
end
end
local make_previewer = function(opts)
local previewers = require "telescope.previewers"
return previewers.new_buffer_previewer {
dyn_title = function(_, entry)
return entry.value.raw_url
end,
define_preview = function (self, entry, status)
local preview = {}
for _,line in pairs(entry.value.lines) do
table.insert(preview, line.code)
end
vim.api.nvim_buf_set_option(self.state.bufnr, "filetype", opts.ftype)
vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, false, preview)
end,
}
end
local result_entry_maker = function(result)
return {
value = result,
display = result.repo..": "..result.main_line.code,
ordinal = result.main_line.code,
}
end
local function create_raw_buffer(opts, result)
local grepclient = require("grep_app.client")
local raw_url = result.raw_url
local code = grepclient.Code_from_url(raw_url)
-- Create a new buffer with that code
local bufnr = vim.api.nvim_create_buf(true, true)
vim.api.nvim_set_current_buf(bufnr)
local lines = {}
for line in code:gmatch("([^\n]*)\n?") do
table.insert(lines, line)
end
vim.api.nvim_buf_set_text(bufnr, 0, 0, 0, 0, lines)
-- switch to new buffer
vim.api.nvim_buf_set_option(bufnr, "filetype", opts.ftype)
vim.api.nvim_buf_set_option(bufnr, "buftype", "nofile")
local lnum = result.main_line.lnum
vim.api.nvim_win_set_cursor(0, {lnum, 0})
end
local paste = function(opts, result)
-- Paste result.main_line.code into current buffer
local code = result.main_line.code
vim.api.nvim_put({code}, "l", true, true)
end
local clone = function(opts, result)
--- Clone the repo and open the file
local repo = result.repo
-- prompt for directory
local dir = vim.fn.input("Clone to: ", vim.fn.getcwd().."/"..result.repo, "dir")
-- clone repo
local clone_cmd = "git clone "..result.clone_url.." "..dir
local checkout_cmd = "git checkout "..result.branch
local on_stderr = function(_, data, _)
for _, line in pairs(data) do
print(line)
end
end
vim.fn.jobstart(clone_cmd, {
on_stderr = on_stderr,
on_exit = function(_, code)
if code == 0 then
-- Start job for checkign out branch
vim.fn.jobstart(checkout_cmd, {
on_stderr = on_stderr,
on_exit = function(_, ccode)
if ccode ~= 0 then
print("Failed to checkout branch! Trying to open anyway.")
end
-- open file
local file = result.main_line.path
local path = dir.."/"..file
vim.cmd("edit "..path)
-- jump to line
local lnum = result.main_line.lnum
vim.api.nvim_win_set_cursor(0, {lnum, 0})
end,
cwd = dir
})
else
print("Error cloning repo: "..result.clone_url.." to "..dir)
end
end
})
end
local open_browser = function(opts, result)
local url
if type(result) == "string" then
url = result
else
url = result.main_line.url
end
if opts.open_browser_cmd then
vim.fn.system(opts.open_browser_cmd.." "..url)
return
end
-- open using xdg-open if on linux and open if on mac and start if on windows
if vim.fn.has("mac") == 1 then
vim.fn.system("open " .. url)
elseif vim.fn.has("unix") == 1 then
vim.fn.system("xdg-open " .. url)
elseif vim.fn.has("win32") == 1 then
vim.fn.system("start " .. url)
else
print("Unsupported OS. Set 'open_browser_cmd' in your config.")
print(url)
end
end
local action_picker = function(opts, result)
pickers.new(opts, {
title = "Choose an action",
prompt_title = "What to do?",
finder = finders.new_table {
results = {
{value = "Open raw in scratch buffer", action = create_raw_buffer},
{value = "Paste line in current buffer", action = paste},
{value = "Clone repo and open file", action = clone},
{value = "Open repo in browser", action = open_browser}
},
entry_maker = function(this_result)
return {
result = result,
value = this_result.value,
action = this_result.action,
display = this_result.value,
ordinal = this_result.value
}
end
},
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
local action = action_state.get_selected_entry().action
local this_result = action_state.get_selected_entry().result.value
action(opts, this_result)
end)
return true
end
}):find()
end
local lang_repeat_picker = function(opts, languages)
pickers.new(opts, {
title = "The language you want to search",
prompt_title = "Languages",
finder = finders.new_table {
results = languages,
},
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
opts.lang = action_state.get_selected_entry().value
grepapp.picker(opts)
end)
return true
end
}):find()
end
local parse_opts = function(opts)
-- Command args override config
for k, v in pairs(grepapp.config) do
if opts[k] == nil then
opts[k] = v
end
end
local ftype = opts.ftype or vim.bo.filetype
opts.ftype = ftype
local max_results = opts.max_results or 20
opts.max_results = max_results
local lang = opts.lang or language_map[ftype]
local api_params = {
words = opts.words or false,
case = opts.case or false,
regexp = opts.regex or false,
lang = lang
}
for k, v in pairs(opts) do
opts[k] = v
end
for k, v in pairs(api_params) do
opts[k] = v
end
local query
if opts.search_query then
query = opts.search_query
elseif opts.search then
query = opts.search
else
query = utils.get_current_line()
end
return opts, api_params, query
end
grepapp.picker = function(opts)
local grepclient = require("grep_app.client")
local _opts, api_params, query = parse_opts(opts)
opts = _opts
local results, lang_suggestions = grepclient.Grep(query, api_params, opts.max_results)
if #results == 0 then
if #lang_suggestions > 0 then
print("No results found for that language! Try another one")
lang_repeat_picker(opts, lang_suggestions)
end
print("No results found!")
return
end
opts = opts or {}
pickers.new(opts, {
prompt_title = "grep.app",
previewer = make_previewer(opts),
finder = finders.new_table {
results = results,
entry_maker = result_entry_maker
},
sorter = conf.generic_sorter(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
action_picker(opts, action_state.get_selected_entry())
end)
return true
end
}):find()
end
grepapp.live_picker = function(opts)
local grepclient = require("grep_app.client")
local _opts, api_params, query = parse_opts(opts)
opts = _opts
local dyn_finder = function(prompt)
if not prompt or prompt == "" then
return nil
end
query = prompt or query
local results, lang_suggestions = grepclient.Grep(query, api_params, opts.max_results)
return results
end
opts.entry_maker = result_entry_maker
opts.fn = dyn_finder
opts.sorting_strategy = "ascending"
local sorters = require "telescope.sorters"
local live_grepper = finders.new_dynamic(opts)
pickers.new(opts, {
title = "Live grep.app",
prompt_title = "Search",
finder = live_grepper,
previewer = make_previewer(opts),
sorter = sorters.highlighter_only(opts),
attach_mappings = function(prompt_bufnr)
actions.select_default:replace(function()
actions.close(prompt_bufnr)
action_picker(opts, action_state.get_selected_entry())
end)
return true
end
}):find()
end
local get_repo_url = function()
local remote_name = utils.system("git remote")
remote_name = remote_name:match("(.*)\n") or remote_name
return utils.system("git remote get-url "..remote_name)
end
local get_branch = function(opts)
local branch = opts.branch
if not branch or branch == "" then
local current_branch = utils.system("git branch --show-current")
local branch_cmd = string.format("git rev-parse --abbrev-ref --symbolic-full-name %s@{upstream}", current_branch)
branch = utils.system(branch_cmd)
branch = branch:match("[^/]/(.+)")
if not branch then
branch = utils.system("git -P branch --remotes --list '*/HEAD'")
branch = branch:match(".+-> [^/]+/(.+)")
end
end
return branch
end
local get_commit_hash = function()
return utils.system("git rev-parse HEAD")
end
local get_git_path = function()
local filename = vim.fn.expand("%:p")
return utils.system(string.format("git ls-files --full-name %s", filename))
end
local generate_github_url = function(opts, branch)
local url = get_repo_url()
url = string.gsub(url, ".git$", "")
url = url .. "/blob/" .. branch .. "/%s#L%s"
local filepath = get_git_path()
if opts.visual then
-- Back to visual mode
vim.cmd("normal! gv")
local start_line = vim.api.nvim_buf_get_mark(0, '<')[1]
local end_line = vim.api.nvim_buf_get_mark(0, '>')[1]
local line_range = string.format("%s-L%s", start_line, end_line)
url = string.format(url, filepath, line_range)
else
url = string.format(url, filepath, vim.fn.line("."))
end
return url
end
local get_line_url = function(opts)
if opts.branch then
return generate_github_url(opts, get_branch(opts))
end
return generate_github_url(opts, get_commit_hash())
end
grepapp.copy_repo_url = function(opts)
opts, _, _ = parse_opts(opts)
vim.fn.setreg("+", get_repo_url())
end
grepapp.open_repo = function(opts)
opts, _, _ = parse_opts(opts)
open_browser(opts, get_repo_url())
end
grepapp.copy_line_url = function(opts)
opts, _, _ = parse_opts(opts)
vim.fn.setreg("+", get_line_url(opts))
end
grepapp.open_line = function(opts)
opts, _, _ = parse_opts(opts)
open_browser(opts, get_line_url(opts))
end
grepapp.copy_file_url = function(opts)
opts, _, _ = parse_opts(opts)
local url = get_line_url(opts)
vim.fn.setreg("+", url:gsub("#L.+$", ""))
end
grepapp.open_file = function(opts)
opts, _, _ = parse_opts(opts)
local url = get_line_url(opts)
open_browser(opts, url:gsub("#L.+$", ""))
end
grepapp.copy_file_git_path = function(opts)
opts, _, _ = parse_opts(opts)
vim.fn.setreg("+", get_git_path())
end
-- to execute the function
return grepapp