local hgap_success = false
local hgap = hgap_default
while hgap <= hgap_limit_reg and regularparent == true do --verify
local prevseason2 = firstpart..lspace..(nstart-t-hgap)..hyph..string.match(nstart-hgap, '%d?%d$') ..tspace..lastpart
local nextseason2 = firstpart..lspace..(nstart+t+hgap)..hyph..string.match(nstart+2*t+hgap, '%d?%d$')..tspace..lastpart
local prevseason4 = firstpart..lspace..(nstart-t-hgap)..hyph..(nstart-hgap) ..tspace..lastpart
local nextseason4 = firstpart..lspace..(nstart+t+hgap)..hyph..(nstart+2*t+hgap)..tspace..lastpart
if t == 1 then --test abbreviated range first, then full range, to be frugal with expensive functions
if catexists(prevseason2) or --use 'or', in case we're at the edge of the cat structure,
catexists(nextseason2) or --or we hit a "–00"/"–2000" situation on one side
catexists(prevseason4) or
catexists(nextseason4)
then
hgap_success = true
break
end
elseif t > 1 then --test full range first, then abbreviated range, to be frugal with expensive functions
if catexists(prevseason4) or --use 'or', in case we're at the edge of the cat structure,
catexists(nextseason4) or --or we hit a "–00"/"–2000" situation on one side
catexists(prevseason2) or
catexists(nextseason2)
then
hgap_success = true
break
end
end
hgap = hgap + 1
end
if hgap_success == false then
hgap = tonumber(testgap) or hgap_default --tracked via defaultgapcat
end  
--preliminary scan to determine ir/regular spacing of nearby cats;
--to limit expensive function calls, MOS:DATERANGE-violating cats are ignored;
--an irregular-term-length series should follow "YYYY..hyph..YYYY" throughout
if hgap <= hgap_limit_reg then --also to isolate temp vars
--find # of nav-visible ir/regular-term-length cats
local bwanchor = nstart --backward anchor/common year
local fwanchor = bwanchor + t --forward anchor/common year
if regularparent == 'isolated' then
fwanchor = bwanchor
end
local spangreen = '[<span>j, g, k = ' --used for/when debugging via list-all-links=yes
local spanblue = '<span>'
local spanred = ' (<span>'
local span = '</span>'
local lastg = nil --to check for run-on searches
local lastk = nil --to check for run-on searches
local endfound = false --switch used to stop searching forward
local iirregs = 0 --index of tirregs[] for j < 0, since search starts from parent
local j = -3 --index of tirregs[] for j > 0 & pseudo nav position
while j <= 3 do  
if j < 0 then --search backward from parent
local gbreak = false --switch used to break out of g-loop
local g = 0 --gap size
while g <= hgap_limit_irreg do
local k = 0 --term length: 0 = "0-length", 1+ = normal
while k <= term_limit do
local from = bwanchor - k - g
local to = bwanchor - g
local full = mw.text.trim( firstpart..lspace..from..hyph..to..tspace..lastpart )
if k == 0 then
if regularparent ~= 'isolated' then --+restrict to g == 0 if repeating year problems arise
to = '0-length'
full = mw.text.trim( firstpart..lspace..from..tspace..lastpart )
if catlinkfollowr( , full ).rtarget ~= nil then --#R followed
table.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full..spanred..'#R ignored'..span..')' )
full, to = *, * --don't use/follow 0-length cat #Rs from nav_hyphen; otherwise gets messy
end
end
end
if (k >= 1) or --the normal case; only continue k = 0 if 0-length found
(to == '0-length') --ghetto "continue" (thx Lua) to avoid expensive searches for "UK MPs 1974-1974", etc.
then
table.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full )
if (k == 1) and
(g == 0 or g == 1) and
(catexists(full) == false)
then --allow bare-bones MOS:DATERANGE alternation, in case we're on a 0|1-gap, 1-year term series
local to2 = string.match(to, '%d%d$')
if to2 and to2 ~= '00' then --and not at a century transition (i.e. 1999–2000)
to = to2
full = mw.text.trim( firstpart..lspace..from..hyph..to..tspace..lastpart )
table.insert( tlistallbwd, spangreen..j..', '..g..', '..k..span..'] '..full )
end
end
if catexists(full) then
if to == '0-length' then
trackcat(13, 'Navseasoncats range irregular, 0-length')
end
tlistallbwd[#tlistallbwd] = spanblue..tlistallbwd[#tlistallbwd]..span..' (found)'
ttlens[ find_duration(full) ] = 1
tgaps[g] = 1
iirregs = iirregs + 1
tirregs['from-'..iirregs] = from
tirregs['to-'..iirregs] = to
bwanchor = from --ratchet down
if to ~= '0-length' then
gbreak = true
break
else
g = 0 --soft-reset g, to keep stepping thru k
j = j + 1 --save, but keep searching thru k
if j > 3 then --lest we keep searching & finding 0-length cats ("MEPs for the Republic of Ireland 1973" & down)
gbreak = true
break
end
end
end
end --ghetto "continue"
k = k + 1
lastk = k
end --while k
if gbreak == true then break end
g = g + 1
lastg = g
end --while g
end --if j < 0  
if j > 0 and endfound == false then --search forward from parent
local gbreak = false --switch used to break out of g-loop
local g = 0 --gap size
while g <= hgap_limit_irreg do
local k = -2 --term length: -2 = "0-length", -1 = "2020–present", 0 = "2020–", 1+ = normal
while k <= term_limit do
local from = fwanchor + g
local to4 = fwanchor + k + g --override carefully
local to2 = nil --last 2 digits of to4, IIF exists
if k == -1 then to4 = 'present' --see if end-cat exists (present)
elseif k == 0 then to4 = '' end --see if end-cat exists (blank)
local full = mw.text.trim( firstpart..lspace..from..hyph..to4..tspace..lastpart )
if k == -2 then
if regularparent ~= 'isolated' then --+restrict to g == 0 if repeating year problems arise
to4 = '0-length' --see if 0-length cat exists
full = mw.text.trim( firstpart..lspace..from..tspace..lastpart )
if catlinkfollowr( , full ).rtarget ~= nil then --#R followed
table.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full..spanred..'#R ignored'..span..')' )
full, to4 = *, * --don't use/follow 0-length cat #Rs from nav_hyphen; otherwise gets messy
end
end
end
if (k >= -1) or --only continue k = -2 if 0-length found
(to4 == '0-length') --ghetto "continue" (thx Lua) to avoid expensive searches for "UK MPs 1974-1974", etc.
then
table.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full )
if (k == 1) and
(g == 0 or g == 1) and
(catexists(full) == false)
then --allow bare-bones MOS:DATERANGE alternation, in case we're on a 0|1-gap, 1-year term series
to2 = string.match(to4, '%d%d$')
if to2 and to2 ~= '00' then --and not at a century transition (i.e. 1999–2000)
full = mw.text.trim( firstpart..lspace..from..hyph..to2..tspace..lastpart )
table.insert( tlistallfwd, spangreen..j..', '..g..', '..k..span..'] '..full )
end
end
if catexists(full) then
if to4 == '0-length' then
if rtarget(, full) == full then --only use 0-length cats that don't #R
trackcat(13, 'Navseasoncats range irregular, 0-length')
end
end
tirregs['from'..j] = from
tirregs['to'..j] = (to2 or to4)
if (k == -1) or (k == 0) then
endfound = true --tentative
else --k == { -2, > 0 }
tlistallfwd[#tlistallfwd] = spanblue..tlistallfwd[#tlistallfwd]..span..' (found)'
ttlens[ find_duration(full) ] = 1
tgaps[g] = 1
endfound = false
if to4 ~= '0-length' then --k > 0
fwanchor = to4 --ratchet up
gbreak = true
break --only break on k > 0 b/c old end-cat #Rs still exist like "Members of the Scottish Parliament 2011–"
else --k == -2
j = j + 1 --save, but keep searching k's, in case "1974" → "1974-1979"
if j > 3 then --lest we keep searching & finding 0-length cats ("2018 CONCACAF Champions League" & up)
gbreak = true
break
end
end
end
end
end --ghetto "continue"
k = k + 1
lastk = k
end --while k
if gbreak == true then break end
g = g + 1
lastg = g
end --while g
end --if j > 0  
if (lastg == (hgap_limit_irreg + 1)) and
(lastk == (term_limit + 1))
then --search exhausted
if j < 0 then j = 0 --bwd search exhausted; continue fwd
elseif j > 0 then break end --fwd search exhausted
end  
j = j + 1
end --while j <= 3
end --if hgap <= hgap_limit_reg  
--begin navhyphen
local navh = '{|\n'..'|\n'  
local terminalcat = false --switch used to hide future cats
local terminaltxt = nil
local i = -3 --nav position
while i <= 3 do