\startluacode

local nuts   = nodes.nuts
local tonut  = nuts.tonut
local tonode = nuts.tonode
local getfield = nuts.getfield
local getid = nuts.getid
local getnext = nuts.getnext
local getlist = nuts.getlist

local tasks = nodes.tasks
local nodecodes = nodes.nodecodes
local traverse_id = nuts.traverse_id
local dir_code = nodecodes.dir
local hlist_code = nodecodes.hlist
local vlist_code = nodecodes.vlist

function handler(head)
   local found_dir = false
   head = tonut(head)
   for dir_node in traverse_id(dir_code, head) do
      local dir, level = getfield(dir_node, 'dir'), getfield(dir_node, 'level')
      if not found_dir then print('processor') found_dir = true end
      print('dir=' .. dir .. ' level=' .. level)
   end
   return tonode(head)
end

function list_handler(list, found_dir)
   local n = list
   while n do
      local id = getid(n)
      if id == hlist_code or id == vlist_code then list_handler(getlist(n), found_dir)
      elseif id == dir_code then
         local dir, level = getfield(n, 'dir'), getfield(n, 'level')
         if not found_dir then print('shipout') found_dir = true end
         print('dir=' .. dir .. ' level=' .. level)
      end
      n = getnext(n)
   end
end

function handler2(head)
   head = tonut(head)
   local found_dir = false
   list_handler(head, found_dir)
   return tonode(head)
end

tasks.appendaction("processors", "after", "handler")
tasks.enableaction("processors", "handler")

tasks.appendaction("shipouts", "after", "handler2")
tasks.enableaction("shipouts", "handler2")

\stopluacode

\starttext

Foo {\setupalign[r2l]Right to left} Bar.

Foo {\setupalign[r2l]Right {\setupalign[l2r]Left again} Right} Bar.

\stoptext
