Skip to content

Commit deef75b

Browse files
authored
Merge branch 'master' into master
2 parents 8690ba4 + d1e329d commit deef75b

3 files changed

Lines changed: 76 additions & 16 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repos:
2020
args: ['--fix=lf']
2121
- id: trailing-whitespace
2222
- repo: https://github.com/python-jsonschema/check-jsonschema
23-
rev: 0.37.2
23+
rev: 0.37.4
2424
hooks:
2525
- id: check-github-workflows
2626
- repo: https://github.com/Lucas-C/pre-commit-hooks

changelog.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ Template for new versions:
4545

4646
## Fixes
4747
- `add-recipe`: fix to include incorrectly excluded recipes
48+
- `combine`: stopgap fix for incorrectly combining dyes, no longer affects dyes
4849
- `gui/control-panel`: fixed incorrect description of deteriorate commands
4950
- `gui/petitions`: fix deity display
50-
- `combine`: stopgap fix for incorrectly combining dyes, no longer affects dyes
51+
- `gui/rename`: fix script error that sometimes caused the script to malfunction when started from the Launcher.
5152

5253
## Misc Improvements
5354
- `trackstop`: ``pressureplate`` overlay moved to `machine-toggle` as an ``armok`` tool

gui/rename.lua

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ local translations = df.language_translation.get_vector()
2020
-- target selection
2121
--
2222

23-
local entity_names = {
23+
---@alias target_type { name:df.language_name, sync_names:(df.language_name|fun():nil)[]?, civ_id:df.historical_entity.id? }
24+
25+
local entity_names = { ---@type table<df.language_name_type, df.entity_name_type>
2426
[df.language_name_type.Figure]=df.entity_name_type.OTHER,
2527
[df.language_name_type.FigureFirstOnly]=df.entity_name_type.OTHER,
2628
[df.language_name_type.FigureNoFirst]=df.entity_name_type.OTHER,
@@ -33,7 +35,7 @@ local entity_names = {
3335
[df.language_name_type.Hospital]=df.entity_name_type.HOSPITAL,
3436
}
3537

36-
local category_names = {
38+
local category_names = { ---@type table<df.language_name_type, df.language_name_category>
3739
[df.language_name_type.World]=df.language_name_category.Region,
3840
[df.language_name_type.Region]=df.language_name_category.Region,
3941
[df.language_name_type.LegendaryFigure]=df.language_name_category.Unit,
@@ -50,6 +52,9 @@ local category_names = {
5052

5153
local wt = language.word_table
5254

55+
---@param name_type df.language_name_type
56+
---@param civ df.historical_entity
57+
---@return df.language_word_table major, df.language_word_table minor
5358
local function get_word_selectors(name_type, civ)
5459
-- special cases
5560
if name_type == df.language_name_type.Artifact then
@@ -78,15 +83,19 @@ local function get_word_selectors(name_type, civ)
7883
return wt[0][df.language_name_category.River], wt[1][df.language_name_category.River]
7984
end
8085

86+
---@param item df.item
87+
---@return target_type?
8188
local function get_artifact_target(item)
8289
if not item or not item.flags.artifact then return end
83-
local gref = dfhack.items.getGeneralRef(item, df.general_ref_type.IS_ARTIFACT)
90+
local gref = dfhack.items.getGeneralRef(item, df.general_ref_type.IS_ARTIFACT) ---@cast gref df.general_ref_is_artifactst?
8491
if not gref then return end
8592
local rec = df.artifact_record.find(gref.artifact_id)
8693
if not rec then return end
8794
return {name=rec.name}
8895
end
8996

97+
---@param hf df.historical_figure
98+
---@return target_type?
9099
local function get_hf_target(hf)
91100
if not hf then return end
92101
local name = dfhack.units.getVisibleName(hf)
@@ -101,6 +110,8 @@ local function get_hf_target(hf)
101110
return {name=name, sync_names=sync_names, civ_id=hf.civ_id}
102111
end
103112

113+
---@param unit df.unit
114+
---@return target_type?
104115
local function get_unit_target(unit)
105116
if not unit then return end
106117
local hf = df.historical_figure.find(unit.hist_figure_id)
@@ -111,6 +122,8 @@ local function get_unit_target(unit)
111122
return {name=dfhack.units.getVisibleName(unit), civ_id=unit.civ_id}
112123
end
113124

125+
---@param entity df.historical_entity?
126+
---@return df.historical_entity.id?
114127
local function get_civ_id_from_entity(entity)
115128
if not entity then return end
116129
if entity.type == df.historical_entity_type.Civilization then return entity.id end
@@ -124,6 +137,8 @@ local function get_civ_id_from_entity(entity)
124137
end
125138
end
126139

140+
---@param site df.world_site?
141+
---@return df.historical_entity.id?
127142
local function get_civ_id_from_site(site)
128143
if not site then return end
129144
for _,he_link in ipairs(site.entity_links) do
@@ -136,27 +151,38 @@ local function get_civ_id_from_site(site)
136151
end
137152
end
138153

154+
---@param entity df.historical_entity
155+
---@return target_type?
139156
local function get_entity_target(entity)
140157
if not entity then return end
141158
return {name=entity.name, civ_id=get_civ_id_from_entity(entity)}
142159
end
143160

161+
---@param site df.world_site
162+
---@return target_type?
144163
local function get_site_target(site)
145164
if not site then return end
146165
return {name=site.name, civ_id=get_civ_id_from_site(site)}
147166
end
148167

168+
---@param site df.world_site
169+
---@param loc_id integer index into site.buildings
170+
---@return target_type?
149171
local function get_location_target(site, loc_id)
150172
if not site or loc_id < 0 then return end
151173
local loc = utils.binsearch(site.buildings, loc_id, 'id')
152174
if not loc then return end
153175
return {name=loc.name, civ_id=get_civ_id_from_site(site)}
154176
end
155177

178+
---@param fort df.historical_entity
179+
---@param squad df.squad
180+
---@return target_type?
156181
local function get_squad_target(fort, squad)
157182
return {name=squad.name, civ_id=get_civ_id_from_entity(fort)}
158183
end
159184

185+
---@return target_type?
160186
local function get_world_target()
161187
local name = df.global.world.world_data.name
162188
local sync_names = {
@@ -185,12 +211,15 @@ local function select_artifact(cb)
185211
choices, function(_, choice) cb(choice.data.target) end, nil, nil, true)
186212
end
187213

214+
---@param site df.world_site
188215
local function select_location(site, cb)
189216
local choices = {}
190217
for _,loc in ipairs(site.buildings) do
191-
local desc, pen = sitemap.get_location_desc(loc)
218+
---@diagnostic disable-next-line: need-check-nil
219+
local desc, pen = sitemap.get_location_desc(loc) ---@type string, dfhack.colors|dfhack.pen
192220
table.insert(choices, {
193-
text={
221+
text={ -- note: the df.abstract_building base class doesn't have a name field, but all relevant subclasses do, so using the name field is ok.
222+
---@diagnostic disable-next-line: undefined-field
194223
dfhack.translation.translateName(loc.name, true),
195224
' (',
196225
{text=desc, pen=pen},
@@ -203,16 +232,21 @@ local function select_location(site, cb)
203232
choices, function(_, choice) cb(choice.data.target) end, nil, nil, true)
204233
end
205234

235+
---@param entity df.historical_entity
236+
---@param cb fun(target:target_type?):nil
206237
local function select_entity(entity, cb)
207238
cb(get_entity_target(entity))
208239
end
209240

241+
---@param cb fun(target:target_type?):nil
210242
local function select_site(site, cb)
211243
cb(get_site_target(site))
212244
end
213245

246+
---@param fort df.historical_entity
247+
---@param cb fun(target:target_type?):nil
214248
local function select_squad(fort, cb)
215-
local choices = {}
249+
local choices = {} ---@type { text:string, data:{ target:target_type? } }[]
216250
for _,squad_id in ipairs(fort.squads) do
217251
local squad = df.squad.find(squad_id)
218252
if squad then
@@ -226,8 +260,9 @@ local function select_squad(fort, cb)
226260
choices, function(_, choice) cb(choice.data.target) end, nil, nil, true)
227261
end
228262

263+
---@param cb fun(target:target_type?):nil
229264
local function select_unit(cb)
230-
local choices = {}
265+
local choices = {} ---@type { text:string, data:{ target:target_type? } }[]
231266
-- scan through units.all instead of units.active so we can choose starting dwarves on embark prep screen
232267
for _,unit in ipairs(df.global.world.units.all) do
233268
if not dfhack.units.isActive(unit) then goto continue end
@@ -244,6 +279,7 @@ local function select_unit(cb)
244279
nil, nil, true)
245280
end
246281

282+
---@param cb fun(target:target_type?):nil
247283
local function select_world(cb)
248284
cb(get_world_target())
249285
end
@@ -293,7 +329,7 @@ Rename.ATTRS {
293329
}
294330

295331
local function get_language_options()
296-
local options, max_width = {}, 5
332+
local options, max_width = {}, 5 ---@type { label:string, value:integer, pen:dfhack.colors|dfhack.pen }[], integer
297333
for idx, lang in ipairs(translations) do
298334
max_width = math.max(max_width, #lang.name)
299335
table.insert(options, {label=dfhack.capitalizeStringWords(dfhack.lowerCp437(lang.name)), value=idx, pen=COLOR_CYAN})
@@ -371,9 +407,10 @@ local function sort_by_part_of_speech_asc(a, b)
371407
return a_native < b_native
372408
end
373409

410+
---@param info { target:target_type, show_selector:boolean? }
374411
function Rename:init(info)
375412
self.target = info.target
376-
self.cache = {}
413+
self.cache = {} ---@type table< df.language_name_component, { text:(string|table)[]|string, search_key:(fun():string), data:{idx:integer, english:string, native_fn:(fun():string), part_of_speech:df.part_of_speech} }[] >
377414

378415
local function normalize_name()
379416
if self.target.name.type == df.language_name_type.NONE then
@@ -510,6 +547,7 @@ function Rename:init(info)
510547
enabled=function()
511548
local _, comp_choice = self.subviews.component_list:getSelected()
512549
if comp_choice.data.is_first_name then return false end
550+
if comp_choice.data.val == df.language_name_component.NONE then return false end
513551
return self.target.name.words[comp_choice.data.val] >= 0
514552
end,
515553
},
@@ -605,10 +643,11 @@ function Rename:get_component_choices()
605643
},
606644
data={val=df.language_name_component.TheX, is_first_name=true}})
607645
for val, comp in ipairs(df.language_name_component) do
608-
if val < 0 then goto continue end -- ignore language_name_component NONE element with value -1
646+
if val == df.language_name_component.NONE then goto continue end
609647
local text = {
610648
{text=comp:gsub('(%l)(%u)', '%1 %2')}, NEWLINE,
611649
{gap=2, pen=COLOR_YELLOW, text=function()
650+
if val == df.language_name_component.NONE then return '' end
612651
local word = self.target.name.words[val]
613652
if word < 0 then return end
614653
return ('%s'):format(language.words[word].forms[self.target.name.parts_of_speech[val]])
@@ -636,7 +675,7 @@ function Rename:get_component_action_choices()
636675

637676
local randomize_text = {{text='[', pen=COLOR_RED}, 'Random', {text=']', pen=COLOR_RED}}
638677
for val, comp in ipairs(df.language_name_component) do
639-
if val < 0 then goto continue end -- ignore language_name_component NONE element with value -1
678+
if val == df.language_name_component.NONE then goto continue end
640679
local randomize_fn = self:callback('randomize_component_word', comp)
641680
table.insert(choices, {text=randomize_text, data={fn=randomize_fn}})
642681
local clear_text = {
@@ -653,6 +692,7 @@ function Rename:get_component_action_choices()
653692
return choices
654693
end
655694

695+
---@param comp df.language_name_component
656696
function Rename:clear_component_word(comp)
657697
self.target.name.words[comp] = -1
658698
for _, sync_name in ipairs(self.target.sync_names) do
@@ -664,6 +704,7 @@ function Rename:clear_component_word(comp)
664704
end
665705
end
666706

707+
---@param word_idx integer
667708
function Rename:set_first_name(word_idx)
668709
-- support giving names to previously unnamed units
669710
self.target.name.has_name = true
@@ -673,11 +714,15 @@ function Rename:set_first_name(word_idx)
673714
if type(sync_name) == 'function' then
674715
sync_name()
675716
else
717+
sync_name.has_name = true
676718
sync_name.first_name = self.target.name.first_name
677719
end
678720
end
679721
end
680722

723+
---@param component df.language_name_component
724+
---@param word_idx integer
725+
---@param part_of_speech df.part_of_speech
681726
function Rename:set_component_word_by_data(component, word_idx, part_of_speech)
682727
self.target.name.words[component] = word_idx
683728
self.target.name.parts_of_speech[component] = part_of_speech
@@ -700,6 +745,8 @@ function Rename:set_component_word(_, choice)
700745
self:set_component_word_by_data(comp_choice.data.val, choice.data.idx, choice.data.part_of_speech)
701746
end
702747

748+
---@param val integer index into df.language_translation:get_vector()
749+
---@param prev_val integer index into df.language_translation:get_vector()
703750
function Rename:set_language(val, prev_val)
704751
self.target.name.language = val
705752
-- translate current first name into target language
@@ -721,6 +768,7 @@ function Rename:randomize_first_name()
721768
self:set_first_name(choices[math.random(#choices)].data.idx)
722769
end
723770

771+
---@param comp df.language_name_component
724772
function Rename:randomize_component_word(comp)
725773
local choices = self:get_word_choices(df.language_name_component.TheX)
726774
local choice = choices[math.random(#choices)]
@@ -756,6 +804,10 @@ local part_of_speech_to_display = {
756804
[df.part_of_speech.VerbGerund] = 'Present Participle',
757805
}
758806

807+
---@param comp df.language_name_component
808+
---@param idx integer
809+
---@param word df.language_word
810+
---@param part_of_speech df.part_of_speech
759811
function Rename:add_word_choice(choices, comp, idx, word, part_of_speech)
760812
local english = word.forms[part_of_speech]
761813
if #english == 0 then return end
@@ -784,12 +836,13 @@ function Rename:add_word_choice(choices, comp, idx, word, part_of_speech)
784836
})
785837
end
786838

839+
---@param comp df.language_name_component
787840
function Rename:get_word_choices(comp)
788841
if self.cache[comp] then
789842
return self.cache[comp]
790843
end
791844

792-
local choices = {}
845+
local choices = {} ---@type {text:(string|table)[]|string, search_key:(fun():string), data:{idx:integer, english:string, native_fn:(fun():string), part_of_speech:df.part_of_speech}}
793846
for idx, word in ipairs(language.words) do
794847
local flags = word.flags
795848
if comp == df.language_name_component.FrontCompound then
@@ -831,9 +884,11 @@ function Rename:get_word_choices(comp)
831884
end
832885

833886
self.cache[comp] = choices
834-
return choices
887+
return self.cache[comp]
835888
end
836889

890+
---@param sort_widget widgets.CycleHotkeyLabel?
891+
---@param sort_fn function?
837892
function Rename:refresh_list(sort_widget, sort_fn)
838893
local clist = self.subviews.component_list
839894
if not clist then return end
@@ -870,6 +925,7 @@ RenameScreen.ATTRS {
870925
focus_path='rename',
871926
}
872927

928+
---@param info { target:target_type, show_selector:boolean? }
873929
function RenameScreen:init(info)
874930
self:addviews{
875931
Rename{
@@ -924,7 +980,7 @@ UnitEmbarkRenameOverlay.ATTRS {
924980
}
925981

926982
local function get_selected_embark_unit()
927-
local scr = dfhack.gui.getDFViewscreen(true)
983+
local scr = dfhack.gui.getDFViewscreen(true) ---@cast scr df.viewscreen_setupdwarfgamest
928984
return scr.s_unit[scr.selected_u]
929985
end
930986

@@ -984,6 +1040,7 @@ if not dfhack.isWorldLoaded() then
9841040
qerror('This script requires a world to be loaded')
9851041
end
9861042

1043+
---@return target_type?
9871044
local function get_target(opts)
9881045
local target
9891046
if opts.histfig_id then
@@ -1009,6 +1066,7 @@ local function get_target(opts)
10091066
if not squad then qerror('Squad not found') end
10101067
target = squad.name
10111068
elseif opts.unit_id then
1069+
---@diagnostic disable-next-line: param-type-mismatch
10121070
target = get_unit_target(df.unit.find(opts.unit_id))
10131071
if not target then qerror('Unit not found') end
10141072
elseif opts.world then
@@ -1048,6 +1106,7 @@ local function main(args)
10481106
return
10491107
end
10501108

1109+
---@param target target_type
10511110
local function launch(target)
10521111
view = view and view:raise() or RenameScreen{
10531112
target=target,

0 commit comments

Comments
 (0)