我在我的文档中创建了许多这样的寄存器,它可以让我存储词汇,\definevocabulary{word}
然后使用并稍后调用列表\placeregister[vocabulary]
:
\defineregister[vocabulary][pagenumber=no, indicator=no, before=, n=1]
\def\definevocabulary{\vocabulary}
\starttext
\definevocabulary{fish}
\definevocabulary{bear}
\placeregister[vocabulary]
\stoptext
当我调用列表时,它会打印所有单词。在某些情况下,我只想显示列表的子集。例如,有些单词被视为高优先级,我只需要打印这些单词。其他单词可能被标记为“针对 5 年级学生”或“针对 6 年级学生”,我可能只需要列出其中一组,或者列出“针对 5 年级学生和高优先级”的组合。
我能想到的唯一解决方案是创建许多不同的寄存器,并将单词添加到适合的寄存器中,但这似乎是一个过于复杂的解决方案:
\defineregister[allvocabulary]
\defineregister[all5thgradevocabulary]
\defineregister[all6thgradevocabulary]
\defineregister[allhighpriorityvocabulary]
\defineregister[all5thgradehighpriorityvocabulary]
\defineregister[all6thgradehighpriorityvocabulary]
ConTeXt 是否有办法标记进入登记册的物品,以便只列出符合特定标准(有时是多个标准)的物品?
答案1
为什么不简单地定义多个寄存器并在显示时合并它们。
\defineregister[easyvocabulary][pagenumber=no, indicator=no, before=, n=1]
\defineregister[hardvocabulary][pagenumber=no, indicator=no, before=, n=1]
\starttext
\easyvocabulary{fish}
\hardvocabulary{what}
\easyvocabulary{bear}
\hardvocabulary{aligator}
\subject{Both registers}
\placeregister[easyvocabulary,hardvocabulary]
\subject{Easy words}
\placeregister[easyvocabulary]
\subject{Hard words}
\placeregister[hardvocabulary]
\stoptext
这使
答案2
我使用标签进行了一些 hack。本质上,您定义的词汇表内容存储在 lua 中structures.registers.collected.vocabulary.entries
。我不确定该表的哪些部分可以安全访问,因此我创建了一个外部表来跟踪标签。然后,当您想要放置特定标签时,我会备份主词汇表列表,对其进行过滤,放置它,然后恢复它。结果有点混乱,但希望可以避免 ConTeXt 内部的复杂化……也许有人可以纠正我这一点。
完整解决方案:
\defineregister[vocabulary][pagenumber=no, indicator=no, before=, n=1]
\startluacode
userdata = userdata or {}
userdata.tags = {}
-- Table copy function from https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value
local function copy(obj, seen)
if type(obj) ~= 'table' then return obj end
if seen and seen[obj] then return seen[obj] end
local s = seen or {}
local res = setmetatable({}, getmetatable(obj))
s[obj] = res
for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
return res
end
-- Test for presence of tag
local function isin(item, tags)
for _, tag in ipairs(tags) do
local inner = false
for _, value in ipairs(userdata.tags[tag]) do
if item == value then
inner = true
break
end
end
if not inner then
return false
end
end
return true
end
userdata.add_tags = function(item, s)
-- Split string
local tags = lpeg.split(lpeg.patterns.spacer, s or "")
for _,tag in pairs(tags) do
userdata.tags[tag] = userdata.tags[tag] or {}
table.insert(userdata.tags[tag], item)
end
end
userdata.filter_items = function(s)
local tags = lpeg.split(lpeg.patterns.spacer, s or "")
-- Backup current vocabulary
local vocabulary = structures.registers.collected.vocabulary.entries
userdata.backup = copy(vocabulary)
-- Filter only tags we want
local n = #vocabulary
-- Going backwards to not disrupt order
for i = n, 1, -1 do
if not isin(vocabulary[i].list[1][1], tags) then
table.remove(vocabulary, i)
end
end
end
userdata.restore_items = function()
structures.registers.collected.vocabulary.entries = copy(userdata.backup)
end
\stopluacode
\define[2]\definevocabulary{%
\vocabulary{#1}%
\ctxlua{userdata.add_tags([==[#1]==], [==[#2]==])}%
}
\define[1]\placevocabulary{%
\ctxlua{userdata.filter_items([==[#1]==])}%
\placeregister[vocabulary] %
\ctxlua{userdata.restore_items()}%
}
\starttext
\definevocabulary{fish}{animal water}
\definevocabulary{bear}{animal land}
\definevocabulary{kelp}{plant water}
\definevocabulary{apple}{plant land}
Animals:
\placevocabulary{animal}
\blank[big]
Plants:
\placevocabulary{plant}
\blank[big]
Land plants:
\placevocabulary{plant land}
\stoptext