aboutsummaryrefslogtreecommitdiff
path: root/core/args.lua
blob: 0dbf0efbbd28576fdec9ad0836df55a5d3fbca43 (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
102
103
104
105
106
107
108
109
110
111
112
113
114
-- Copyright 2007-2020 Mitchell mitchell.att.foicica.com. See LICENSE.

local M = {}

--[[ This comment is for LuaDoc.
---
-- Processes command line arguments for Textadept.
-- @field _G.events.ARG_NONE (string)
--   Emitted when no command line arguments are passed to Textadept on startup.
module('args')]]

events.ARG_NONE = 'arg_none'

-- Contains registered command line switches.
-- @class table
-- @name switches
local switches = {}

---
-- Registers a command line switch with short and long versions *short* and
-- *long*, respectively. *narg* is the number of arguments the switch accepts,
-- *f* is the function called when the switch is tripped, and *description* is
-- the switch's description when displaying help.
-- @param short The string short version of the switch.
-- @param long The string long version of the switch.
-- @param narg The number of expected parameters for the switch.
-- @param f The Lua function to run when the switch is tripped. It is passed
--   *narg* string arguments.
-- @param description The string description of the switch for command line
--   help.
-- @name register
function M.register(short, long, narg, f, description)
  local t = {f, narg, description}
  switches[short], switches[long] = t, t
end

-- Processes command line argument table *arg*, handling switches previously
-- defined using `args.register()` and treating unrecognized arguments as
-- filenames to open.
-- Emits an `ARG_NONE` event when no arguments are present unless
-- *no_emit_arg_none* is `true`.
-- @param arg Argument table.
-- @see register
-- @see _G.events
local function process(arg, no_emit_arg_none)
  local no_args = true
  local i = 1
  while i <= #arg do
    local switch = switches[arg[i]]
    if switch then
      local f, n = table.unpack(switch)
      f(table.unpack(arg, i + 1, i + n))
      i = i + n
    else
      io.open_file(lfs.abspath(arg[i], arg[-1]))
      no_args = false
    end
    i = i + 1
  end
  if no_args and not no_emit_arg_none then events.emit(events.ARG_NONE) end
end
events.connect(events.INITIALIZED, function() if arg then process(arg) end end)
-- Undocumented, single-instance event handler for forwarding arguments.
events.connect('cmd_line', function(arg) process(arg, true) end)

if not CURSES then
  -- Shows all registered command line switches on the command line.
  M.register('-h', '--help', 0, function()
    print('Usage: textadept [args] [filenames]')
    local line = "  %s [%d args]: %s"
    local list = {}
    for switch in pairs(switches) do list[#list + 1] = switch end
    table.sort(list,
               function(a, b) return a:match('[^-]+') < b:match('[^-]+') end)
    for i = 1, #list do
      local switch = list[i]
      print(line:format(switch, table.unpack(switches[switch], 2)))
    end
    os.exit()
  end, 'Shows this')
  -- Shows Textadept version and copyright on the command line.
  M.register('-v', '--version', 0, function()
    print(_RELEASE..'\n'.._COPYRIGHT)
    quit()
  end, 'Prints Textadept version and copyright')
  -- After Textadept finishes initializing and processes arguments, remove the
  -- help and version switches in order to prevent another instance from sending
  -- '-h', '--help', '-v', and '--version' to the first instance, killing the
  -- latter.
  events.connect(events.INITIALIZED, function()
    switches['-h'], switches['--help'] = nil, nil
    switches['-v'], switches['--version'] = nil, nil
  end)
end

-- Set `_G._USERHOME`.
-- This needs to be set as soon as possible since the processing of arguments is
-- positional.
_USERHOME = os.getenv(not WIN32 and 'HOME' or 'USERPROFILE')..'/.textadept'
for i = 1, #arg do
  if (arg[i] == '-u' or arg[i] == '--userhome') and arg[i + 1] then
    _USERHOME = arg[i + 1]
    break
  end
end
if not lfs.attributes(_USERHOME) then lfs.mkdir(_USERHOME) end
local f = io.open(_USERHOME..'/init.lua', 'a+') -- ensure existence
if f then f:close() end

-- Placeholders.
M.register('-u', '--userhome', 1, function() end, 'Sets alternate _USERHOME')
M.register('-f', '--force', 0, function() end, 'Forces unique instance')

return M