aboutsummaryrefslogtreecommitdiffhomepage
path: root/core/ext/pm/find_browser.lua
blob: bf2796b4010868c487d9f8aa77509cc8a85c170b (plain)
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
-- Copyright 2007-2008 Mitchell mitchell<att>caladbolg.net. See LICENSE.

---
-- Find in files browser for the Textadept project manager.
-- It is enabled with the prefix 'find' in the project manager entry field.
module('textadept.pm.browsers.find', package.seeall)

---
-- The directory recursively searched. If pm.search_directory is not specified,
-- defaults to the current working directory.
local search_directory

---
-- The table of file matches.
-- Each key is a filename and the value is a table containing the usual as well
-- as a children key that contains entries for line number matches.
-- @class table
-- @name find_matches
local find_matches

--- Matches 'file:search text' (search text can contain spaces)
function matches(entry_text)
  return entry_text:sub(1, 4) == 'find'
end

---
-- If not expanding, creates the entire tree; otherwise returns the child table
-- of the parent being expanded.
function get_contents_for(full_path, expanding)
  local search_string, recursive
  if full_path[1]:sub(1, 5) == 'findr' then
    search_string = full_path[1]:sub(7) -- ignore 'findr:'
    recursive = true
  else
    search_string = full_path[1]:sub(6) -- ignore 'find:'
    recursive = false
  end
  if #search_string == 0 then return {} end
  if expanding then
    local parent = find_matches
    for i = 2, #full_path do
      local filename = full_path[i]
      if not parent[filename] then return {} end
      parent = parent[filename].children
    end
    return parent
  else
    find_matches = {}
    local p
    search_directory = _G.textadept.pm.search_directory
    if not search_directory then
      p = io.popen('pwd')
      search_directory = p:read('*all'):match('^[^\n]+')
      p:close()
    end
    search_string = search_string:gsub('"', '\\"')
    search_directory = search_directory:gsub('"', '\\"')
    local opts = 'nH'..(recursive and 'r' or '')
    p = io.popen('grep -'..opts..' "'..search_string..'" "'..
                 search_directory..'"')
    for line in p:lines() do
      local filename, line_num, line_text = line:match('^([^:]+):(%d+):%s-(.+)$')
      if filename and line_num and line_text then
        if not find_matches[filename] then
          find_matches[filename] = {
            parent = true,
            children = {},
            display_text = filename
          }
        end
        local entry = {}
        entry.display_text = line_num..':'..line_text
        entry.line_num = line_num
        entry.filepath = filename
        find_matches[filename].children[line_num] = entry
      end
    end
    p:close()
    return find_matches
  end
end

function perform_action(selected_item)
  local item = find_matches
  for i = 2, #selected_item do
    local match = selected_item[i]
    item = item[match]
    if item.children then item = item.children end
  end
  textadept.io.open(item.filepath)
  buffer:goto_line(item.line_num - 1)
  view:focus()
end

function get_context_menu(selected_item)

end

function perform_menu_action(menu_item, selected_item)

end