2

I created many registers in my document like this, which lets me store vocabulary words, using \definevocabulary{word} and then call the list later with \placeregister[vocabulary]:

\defineregister[vocabulary][pagenumber=no, indicator=no, before=, n=1]
\def\definevocabulary{\vocabulary}
\starttext
    \definevocabulary{fish}
    \definevocabulary{bear}
    \placeregister[vocabulary]
\stoptext

When I call the list, it prints all of the words. There are some situations where I just want a subset of the list to be displayed. For instance, some words are considered as high priority, and I need to just print those. Others might be tagged as "for 5th graders" or "for 6th graders", and I might need to list just one set of those, or a combination such as "for 5th graders and high priority".

The only solution I can think is to create many different registers, and add the words to the ones they fit in, but this seems an overly complex solution:

\defineregister[allvocabulary]
\defineregister[all5thgradevocabulary]
\defineregister[all6thgradevocabulary]
\defineregister[allhighpriorityvocabulary]
\defineregister[all5thgradehighpriorityvocabulary]
\defineregister[all6thgradehighpriorityvocabulary]

Does ConTeXt have any way to tag items going into a register, so that only items meeting specific criteria, sometimes multiple criteria, are listed?

2 Answers 2

4

Why not simply define multiple registers and merge them while displaying.

\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

which gives

enter image description here

1
+400

I put together a bit of a hack using tags. Essentially, the vocabulary contents you defined is stored in lua in structures.registers.collected.vocabulary.entries. I wasn't sure what parts of that table are safe to access or not so I created an external table which keeps track of the tags. Then, when you want to place particular tags, I backup the main vocabulary list, filter it, place it, and then restore it. The result is a bit dirty, but hopefully avoid complications with ConTeXt internals... Perhaps someone can correct me on this.

The full solution:

\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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .