Skip to content

Commit 32739c4

Browse files
authored
Merge pull request #1534 from pajawojciech/quickcmd-output-and-labels
Add output and labels to quickcmd
2 parents e88bc68 + 1c13683 commit 32739c4

2 files changed

Lines changed: 157 additions & 19 deletions

File tree

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Template for new versions:
4747
## New Tools
4848

4949
## New Features
50+
- `gui/quickcmd`: added custom command names and option to display command output
5051
- `gui/notify`: new notification type: missing nemesis records; displays a warning message about game corruption.
5152

5253
## Fixes

gui/quickcmd.lua

Lines changed: 156 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,45 @@ local json = require('json')
3434
local gui = require('gui')
3535
local widgets = require('gui.widgets')
3636

37+
local CONFIG_FILE_BACKUP = 'dfhack-config/quickcmd.json.bak'
3738
local CONFIG_FILE = 'dfhack-config/quickcmd.json'
3839
local HOTKEYWIDTH = 7
40+
local OUTWIDTH = 4
3941
local HOTKEYS = 'asdfghjklqwertyuiopzxcvbnm'
4042

43+
local function save_commands(data)
44+
json.encode_file({version=2, commands=data}, CONFIG_FILE)
45+
end
46+
47+
local function migrate_to_v2(data)
48+
json.encode_file(data, CONFIG_FILE_BACKUP)
49+
50+
local commands = {}
51+
for i, cmd in ipairs(data) do
52+
if type(cmd) == 'string' then
53+
table.insert(commands, {command = cmd, name = nil, show_output = false})
54+
end
55+
end
56+
57+
save_commands(commands)
58+
return commands
59+
end
60+
4161
local function load_commands()
4262
local ok, data = pcall(json.decode_file, CONFIG_FILE)
43-
return ok and data or {}
44-
end
63+
if ok then
64+
if type(data) == 'table' and data.version then
65+
if data.version == 2 then
66+
return data.commands or {}
67+
end
68+
end
69+
-- Old format: array of strings
70+
if type(data) == 'table' and #data > 0 then
71+
return migrate_to_v2(data)
72+
end
73+
end
4574

46-
local function save_commands(data)
47-
json.encode_file(data, CONFIG_FILE)
75+
return {}
4876
end
4977

5078
QCMDDialog = defclass(QCMDDialog, widgets.Window)
@@ -61,12 +89,12 @@ function QCMDDialog:init(info)
6189
self:addviews{
6290
widgets.Label{
6391
frame={t=0},
64-
text={{text='Hotkey', width=HOTKEYWIDTH}, ' Command'},
92+
text={{text='Hotkey', width=HOTKEYWIDTH}, {text='Out', width=OUTWIDTH}, 'Name/Command'},
6593
visible=function() return #self.commands > 0 end,
6694
},
6795
widgets.List{
6896
view_id='list',
69-
frame={t=2, b=3},
97+
frame={t=2, b=4},
7098
on_submit=self:callback('submit'),
7199
},
72100
widgets.Label{
@@ -75,53 +103,128 @@ function QCMDDialog:init(info)
75103
visible=function() return #self.commands == 0 end,
76104
},
77105
widgets.HotkeyLabel{
78-
frame={b=1, l=0},
106+
frame={b=2, l=0},
79107
key='CUSTOM_SHIFT_A',
80108
label='Add command',
81109
auto_width=true,
82110
on_activate=self:callback('onAddCommand'),
83111
},
84112
widgets.HotkeyLabel{
85-
frame={b=1, l=19},
113+
frame={b=2, l=19},
86114
key='CUSTOM_SHIFT_D',
87115
label='Delete command',
88116
auto_width=true,
89117
on_activate=self:callback('onDelCommand'),
90118
},
91119
widgets.HotkeyLabel{
92-
frame={b=0, l=0},
120+
frame={b=1, l=0},
93121
key='CUSTOM_SHIFT_E',
94122
label='Edit command',
95123
auto_width=true,
96124
on_activate=self:callback('onEditCommand'),
97125
},
126+
widgets.HotkeyLabel{
127+
frame={b=1, l=19},
128+
key='CUSTOM_SHIFT_N',
129+
label='Edit name',
130+
auto_width=true,
131+
on_activate=self:callback('onSetName'),
132+
},
133+
widgets.HotkeyLabel{
134+
frame={b=0, l=0},
135+
key='CUSTOM_SHIFT_O',
136+
label='Capture output',
137+
auto_width=true,
138+
on_activate=self:callback('onToggleOutput'),
139+
},
98140
}
99141

100142
self:updateList()
101143
end
102144

103145
function QCMDDialog:submit(idx, choice)
146+
local cmd_obj = self.commands[idx]
147+
148+
if cmd_obj.show_output then
149+
self:showCommandOutput(cmd_obj.command, cmd_obj.name)
150+
else
151+
local screen = self.parent_view
152+
dfhack.screen.hideGuard(screen, function()
153+
dfhack.run_command(cmd_obj.command)
154+
end)
155+
screen:dismiss()
156+
end
157+
end
158+
159+
function QCMDDialog:showCommandOutput(command, name)
160+
local output = dfhack.run_command_silent(command)
161+
162+
-- Dismiss the quickcmd dialog before showing output
104163
local screen = self.parent_view
105-
dfhack.screen.hideGuard(screen, function()
106-
dfhack.run_command(choice.command)
107-
end)
108164
screen:dismiss()
165+
166+
local OutputDialog = defclass(OutputDialog, gui.ZScreen)
167+
OutputDialog.ATTRS{
168+
focus_path='quickcmd_output',
169+
command='',
170+
name='',
171+
output='',
172+
}
173+
174+
function OutputDialog:init()
175+
local title = ('%s%s'):format(self.name ~= '' and self.name .. ': ' or '', self.command)
176+
177+
self:addviews{
178+
widgets.Window{
179+
frame_title=title,
180+
frame={w=80, h=25},
181+
resizable=true,
182+
resize_min={h=10, w=40},
183+
subviews={
184+
widgets.WrappedLabel{
185+
view_id='output',
186+
frame={t=0, l=0, r=0, b=2},
187+
text_to_wrap=self.output or 'No output',
188+
scroll_keys=widgets.STANDARDSCROLL,
189+
},
190+
widgets.HotkeyLabel{
191+
frame={b=0, l=0},
192+
key='LEAVESCREEN',
193+
label='Close',
194+
auto_width=true,
195+
on_activate=self:callback('dismiss'),
196+
},
197+
}
198+
}
199+
}
200+
end
201+
202+
if #output == 0 then
203+
output = 'Command finished successfully'
204+
end
205+
206+
OutputDialog{command=command, name=name, output=output}:show()
109207
end
110208

111209
function QCMDDialog:updateList()
112210
-- Build the list entries.
113211
local choices = {}
114-
for i,command in ipairs(self.commands) do
212+
for i,cmd_obj in ipairs(self.commands) do
115213
-- Get the hotkey for this entry.
116214
local hotkey = nil
117215
if i <= HOTKEYS:len() then
118216
hotkey = HOTKEYS:sub(i, i)
119217
end
120218

219+
-- Display name if set, otherwise display command
220+
local display_text = cmd_obj.name or cmd_obj.command
221+
121222
-- Store the entry.
122223
table.insert(choices, {
123-
text={{text=hotkey or '', width=HOTKEYWIDTH}, ' ', command},
124-
command=command,
224+
text={{text=hotkey or '', width=HOTKEYWIDTH}, {text=cmd_obj.show_output and '[X]' or '[ ]', width=OUTWIDTH}, display_text},
225+
command=cmd_obj.command,
226+
name=cmd_obj.name,
227+
show_output=cmd_obj.show_output,
125228
hotkey=hotkey and ('CUSTOM_' .. hotkey:upper()) or '',
126229
})
127230
end
@@ -148,7 +251,7 @@ function QCMDDialog:onAddCommand()
148251
COLOR_GREEN,
149252
'',
150253
function(command)
151-
table.insert(self.commands, command)
254+
table.insert(self.commands, {command=command, name=nil, show_output=false})
152255
save_commands(self.commands)
153256
self:updateList()
154257
end
@@ -165,7 +268,7 @@ function QCMDDialog:onDelCommand()
165268
-- Prompt for confirmation.
166269
dlg.showYesNoPrompt(
167270
'Delete command',
168-
'Are you sure you want to delete this command: ' .. NEWLINE .. item.command,
271+
'Are you sure you want to delete this command: ' .. NEWLINE .. self.commands[index].command,
169272
COLOR_GREEN,
170273
function()
171274
table.remove(self.commands, index)
@@ -187,15 +290,49 @@ function QCMDDialog:onEditCommand()
187290
'Edit command',
188291
'Enter command:',
189292
COLOR_GREEN,
190-
item.command,
293+
self.commands[index].command,
191294
function(command)
192-
self.commands[index] = command
295+
self.commands[index].command = command
193296
save_commands(self.commands)
194297
self:updateList()
195298
end
196299
)
197300
end
198301

302+
function QCMDDialog:onSetName()
303+
-- Get the selected command.
304+
local index, item = self.subviews.list:getSelected()
305+
if not item then
306+
return
307+
end
308+
309+
-- Prompt for new name.
310+
dlg.showInputPrompt(
311+
'Set name',
312+
'Enter name:',
313+
COLOR_GREEN,
314+
self.commands[index].name or '',
315+
function(name)
316+
self.commands[index].name = name ~= '' and name or nil
317+
save_commands(self.commands)
318+
self:updateList()
319+
end
320+
)
321+
end
322+
323+
function QCMDDialog:onToggleOutput()
324+
-- Get the selected command.
325+
local index, item = self.subviews.list:getSelected()
326+
if not item then
327+
return
328+
end
329+
330+
-- Toggle the show_output flag.
331+
self.commands[index].show_output = not self.commands[index].show_output
332+
save_commands(self.commands)
333+
self:updateList()
334+
end
335+
199336
QCMDScreen = defclass(QCMDScreen, gui.ZScreen)
200337
QCMDScreen.ATTRS {
201338
focus_path='quickcmd',

0 commit comments

Comments
 (0)