aboutsummaryrefslogtreecommitdiff
path: root/modules/textadept/filter_through.lua
blob: a3094c0ceb798ddba0540743da5f9a5051230eba (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
-- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.

local L = _G.locale.localize

---
-- Filter-Through for the textadept module.
module('_m.textadept.filter_through', package.seeall)

local cat = not WIN32 and 'cat' or 'type'
local tmpfile = _USERHOME..'/.ft'
local filter_through_active = false

---
-- Prompts for a Linux, Mac OSX, or Windows shell command to filter text
-- through.
-- The standard input (stdin) for shell commands is determined as follows: (1)
-- If text is selected and spans multiple lines, all text on the lines
-- containing the selection is used. However, if the end of the selection is at
-- the beginning of a line, only the EOL (end of line) characters from the
-- previous line are included as input. The rest of the line is excluded. (2) If
-- text is selected and spans a single line, only the selected text is used. (3)
-- If no text is selected, the entire buffer is used.
-- The input text is replaced with the standard output (stdout) of the command.
function filter_through()
  filter_through_active = true
  gui.command_entry.focus()
end

events.connect('command_entry_keypress',
  function(code)
    if filter_through_active and code == 0xff1b then -- escape
      filter_through_active = false
    end
  end, 1) -- place before command_entry.lua's handler (if necessary)

events.connect('command_entry_command',
  function(text) -- filter through
    if filter_through_active then
      local buffer = buffer
      local s, e = buffer.selection_start, buffer.selection_end
      local input
      if s ~= e then -- use selected lines as input
        local i, j = buffer:line_from_position(s), buffer:line_from_position(e)
        if i < j then
          s = buffer:position_from_line(i)
          if buffer.column[e] > 0 then e = buffer:position_from_line(j + 1) end
        end
        input = buffer:text_range(s, e)
      else -- use whole buffer as input
        input = buffer:get_text()
      end
      local f = io.open(tmpfile, 'wb')
      f:write(input)
      f:close()
      local cmd = table.concat({ cat, '"'..tmpfile..'"', '|', text }, ' ')
      if WIN32 then cmd = cmd:gsub('/', '\\') end
      local p = io.popen(cmd)
      if s ~= e then
        buffer.target_start, buffer.target_end = s, e
        buffer:replace_target(p:read('*all'))
        buffer:set_sel(buffer.target_start, buffer.target_end)
      else
        buffer:set_text(p:read('*all'))
        buffer:goto_pos(s)
      end
      p:close()
      os.remove(tmpfile)
      filter_through_active = false
      return true
    end
  end, 1) -- place before command_entry.lua's handler (if necessary)