ntg-context - mailing list for ConTeXt users
 help / color / mirror / Atom feed
* Exploring the Lua innards of ConTeXt: showtable
@ 2012-09-17 15:47 Sietse Brouwer
  2012-09-17 16:45 ` Hans Hagen
  0 siblings, 1 reply; 2+ messages in thread
From: Sietse Brouwer @ 2012-09-17 15:47 UTC (permalink / raw)
  To: mailing list for ConTeXt users

[-- Attachment #1: Type: text/plain, Size: 2671 bytes --]

Hi all,

ConTeXt mkiv stores all sorts of things in Lua tables, but 'what goes
where' does not tend to be documented. So here is a function to print
out a table's contents to get something like the following excerpt.

The excerpt is from the output of
`userdata.showtable(structures.lists)` in a document with three
\placefigures and one \placeformula. Note the reference in
T.cached.1.references.reference, and the caption in
T.cached.1.titledata.title (T stands for the table yone passed to
showtables); and note how the tables of figures 2 and 3 are not
printed, because they follow the same pattern as table 1. (You can
tell showtable to print everything, natch.)

T.addto           : function: 0xa4c8818
T.analyze         : function: 0xb1c27b0
T.cached          : table: 0xb1c2240
T.cached.1 : table: 0xc3f7b18
T.cached.1.metadata   : table: 0xc3f7d58
T.cached.1.metadata.kind     : float
T.cached.1.metadata.name     : figure
T.cached.1.prefixdata : table: 0xc3f7c68
T.cached.1.prefixdata.connector : .
T.cached.1.prefixdata.prefix    : no
T.cached.1.references : table: 0xc3f7ba8
T.cached.1.references.reference : ref:asdf
T.cached.1.titledata  : table: 0xc3f7b40
T.cached.1.titledata.title : caption 1
T.cached.2 : table: 0xc467bb8 (like T.cached.1)
T.cached.3 : table: 0xc4731a8 (like T.cached.1)
T.cached.4 : table: 0xc47c988
T.cached.4.metadata   : table: 0xc47d628
T.cached.4.metadata.kind     : formula
T.cached.4.metadata.name     : formula

(You can't see it in this e-mail, but the colons of entries in the
same subtable nicely line up with each other.)

Usage: put showtable.lua in your working directory and run the following code:

\starttext
% \placefigure[][ref:asdf]{caption 1}{picture 1}
\startluacode
    require('showtable')
    userdata.showtable(structures.lists)
\stopluacode
\stoptext

Extra options can be passed as part of an options table. (This allows
overriding one option without respecifying the others.)
userdata.showtable(
    structures.lists,
    { everything=true, -- descend even into similar-looking siblings
    tablename='S.L' }
)

Output is printed to the terminal, alas, because I couldn't discover
how to print to the log. Anybody know anything about this?

Hopefully this may be useful to someone, next time they they're
hunting for something in the bowels of ConTeXt. Interesting tables to
look at:
* userdata.showtable(commands) contains a great miscellanea of helper commands
* userdata.showtable(context) also contains a great miscellanea of commands
* userdata.showtable(tex) seems to show lua access functions to some
plain tex stuff
* userdata.showtable(lxml) gives a list of lxml-related functions

Cheers,
Sietse

[-- Attachment #2: showtable.lua --]
[-- Type: application/octet-stream, Size: 8290 bytes --]

-------- General description

-- Usage:
-- u.print_table(
--      thetable,   -- The table to print, one line per entry
--      { tablename,  -- Its name, if you want that printed at the start
--        everything, -- Whether to descend repeatedly into similar subtables.
--                       False by default.
--        statter,    -- A function which is called on a table before
--                       printing its entry and possibly descending into
--                       it. Defaults to `getstats()`, but you can specify
--                       your own plug-in replacement. Expected to return
--                       a table containing at least `maxkeylength`,
--                       `signature`, and `ordertable`. The stats table is
--                       passed to the printer function, and also to the
--                       do_print_table that descends into the table.
--        printer     -- Defaults to `printline()`. Prints the current line,
--      }                on the basis of `(k, v, path, stats_of_self,
--                       stats_of_v, known)`. `known` will be true if v is
--                       a table, and we have previously seen a sibling
--                       table with the same signature.
-- )

-- Output is something like the following:
-- T.aap                 : 1
-- T.function: 0x9e39a78 : nil
-- T.karolus             : table: 0x9e3d228
-- T.karolus.aap                : function: 0x9e39998
-- T.karolus.noot               : 8
-- T.karolus.wimpjewimpjewimpje : jjjjjj
-- T.noot                : 2
-- T.wortel              : table: 0x9e3d0b0 (like T.karolus)

-------- Functions

-- Traverse a table once, and return a table with the following fields:
--      `maxkeylength`: the longest key name in the table.
--      `signature`: used by do_print_table. If the same signature is
--          encountered twice, then the second time the default
--          behaviour of do_print_table is to not descend.
--      `ordertable`: used by do_print_table to traverse over the the keys
--          of thetable in (alphabetical) order
--
-- The table is also passed to the printer function. (Default one is
-- `printline`.) So, you may specify an alternative printing function
-- that depends on knowledge of other fields, and write an alternative
-- to getstats that collects that knowledge and returns it in its table.

local function getstats(thetable)
    local signaturetable = { }
    -- k is not sortable; tostring(k) is. So: 
    -- store the string in ordertable; 
    -- store string->object maps in string_orig_table;
    -- sort the strings, and put back the objects
    local ordertable = { } -- stores tostring(k). Is sortable.
    local string_orig_table = { }    -- maps tostring(k) to k.
    local maxkeylength = 0

    for k, v in pairs(thetable) do
        -- gather 'key:type' for the signatures
        table.insert(signaturetable, tostring(k) .. ':' .. type(v))
        -- store strings for sorting, string->object for replacing
        table.insert(ordertable, tostring(k))
        string_orig_table[tostring(k)] = k

        -- update max_key_length
        local l = string.len(tostring(k))
        if maxkeylength < l then maxkeylength = l end
    end

    -- sort the strings, then put back the objects.
    table.sort(ordertable)
    for i, kstring in ipairs(ordertable) do
        ordertable[i] = string_orig_table[kstring]
    end

    -- turn the signature table into a proper signature
    table.sort(signaturetable)
    signature = table.concat(signaturetable, '--')

    -- return the statistics table
    return({
        signature = signature,
        ordertable = ordertable,
        maxkeylength = maxkeylength
    })
end

-- Given a key and a value, plus some extra info, pretty-print them.
-- k: the key. Required.
-- v: the value. Required.
-- stats_of_self: Required. a table that contains these entries: 
--     maxkeylength: the length of the longest key in the table that
--          contains k and its siblings
--     depth: recursion level. Initially level 0.
--     path: If k is at the.table.k, the path is "the.table".
-- stats_of_v: Required if known == true. Must contain these entries:
--      similar_sibling
-- known: whether a similar sibling exists. If yes, printline refers to
--      that sib.
local function printline(k, v, stats_of_self, stats_of_v, known)
    path         = stats_of_self.path or ''
    maxkeylength = stats_of_self.maxkeylength
    k            = tostring(k)
    v            = tostring(v)

    if known then
        v = tostring(v) .. ' (like ' .. stats_of_v.similar_sibling .. ')' 
    end
    -- stats.maxkeylength = longest key in current v
    --       maxkeylength = longest key among k and its siblings
    padding = string.rep(' ', maxkeylength - string.len(k))
    print(path .. '.' .. k .. padding .. ' : ' .. v)
end

-- Print a table, one line per entry. If the entry is itself a table,
-- recurse into it (unless the table is known, and `everything` =
-- `false`.)
local function do_print_table(thetable, stats_of_self, 
                              everything, statter, printer)
    local setofchildsigs = { }

    -- Traverse the entries of thetable in alphabetical order
    -- (alphabetical order kindly supplied by ordertable)
    for i, k in ipairs(stats_of_self.ordertable) do

        local v = thetable[k]
        -- if it's a table, decide whether to descend;
        if type(v) == "table" then
            -- construct the signature
            local stats_of_v = statter(v)
            -- Attention! The stats table also stores the values
            -- depth and path, and not just what the statter returns.
            stats_of_v.depth = stats_of_self.depth + 1
            stats_of_v.path  = stats_of_self.path .. '.' .. k

            -- if the sig is known, and we don't print everything, 
            -- print 'the.table : (like the.siblingtable)'
            if setofchildsigs[stats_of_v.signature] and 
                    not everything then
                stats_of_v.similar_sibling = 
                    setofchildsigs[stats_of_v.signature]
                printer(k, v, stats_of_self, stats_of_v, true)

            -- for unknown sigs, or if we print everything: 
            -- record the sig, print the line, and descend.
            else
                setofchildsigs[stats_of_v.signature] = 
                    stats_of_self.path .. '.' .. k
                printer(k, v, stats_of_self, stats_of_v, false)
                do_print_table(
                    v, stats_of_v, 
                    everything, statter, printer
                )
            end
        -- end of the 'if it's a table' block
        -- if it's not a table, simply print it.
        else
            printer(k, v, stats_of_self, stats_of_v, false)
        end
    end -- end for
end

-- Front-end that takes care of default options.
-- specify an option like so:
-- print_table(jan, {everything = true})
local function print_table(thetable, opts)
    local opts = opts or { }
    local tablename  = opts.tablename  or 'T'
    local everything = opts.everything or false
    local statter    = opts.statter    or getstats
    local printer    = opts.printer    or printline

    local stats = statter(thetable)
    -- Attention! The stats table also stores the values depth and path,
    -- and not just what the statter returns.
    stats.depth = 0
    stats.path = tablename
    do_print_table(thetable, stats, everything, statter, printer)
end            

-------- Make it available

userdata = userdata or { }
userdata.showtable = print_table

-------- Testing code, for them what want it.

--[[
    jan = { 
        aap = 1, 
        noot = 2, 
        wortel = { 
            wimpjewimpjewimpje = 'asdfjkl', 
            aap = function (x)
              print 'asdf'
            end,   
            noot = 8
        },
        [999] = 12,
        karolus = { 
            wimpjewimpjewimpje = 'jjjjjj', 
            aap = function (x)
                print 'asdf'
            end,   
            noot = 8
        }
    }

    -- keys can be functions or objects, too
    vent = function(x) print('jk') end
    jan[vent] = 66

    userdata.showtable(jan)
    print('\n====\n')
    userdata.showtable(jan, {everything = true})
--]]

[-- Attachment #3: Type: text/plain, Size: 485 bytes --]

___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://tex.aanhet.net
archive  : http://foundry.supelec.fr/projects/contextrev/
wiki     : http://contextgarden.net
___________________________________________________________________________________

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Exploring the Lua innards of ConTeXt: showtable
  2012-09-17 15:47 Exploring the Lua innards of ConTeXt: showtable Sietse Brouwer
@ 2012-09-17 16:45 ` Hans Hagen
  0 siblings, 0 replies; 2+ messages in thread
From: Hans Hagen @ 2012-09-17 16:45 UTC (permalink / raw)
  To: mailing list for ConTeXt users

On 17-9-2012 17:47, Sietse Brouwer wrote:
> Hi all,
>
> ConTeXt mkiv stores all sorts of things in Lua tables, but 'what goes
> where' does not tend to be documented. So here is a function to print
> out a table's contents to get something like the following excerpt.

Keep in mind that many datatables are not frozen in stone i.e. their 
structure might change at some point (I still need to finish cleaning up 
some structure related code, after that most will stay as it is).

In case you don't this one:

context s-inf-03.mkiv

It reports some info about what sits in a table (d means data).

> The excerpt is from the output of
> `userdata.showtable(structures.lists)` in a document with three
> \placefigures and one \placeformula. Note the reference in
> T.cached.1.references.reference, and the caption in
> T.cached.1.titledata.title (T stands for the table yone passed to
> showtables); and note how the tables of figures 2 and 3 are not
> printed, because they follow the same pattern as table 1. (You can
> tell showtable to print everything, natch.)
>
> T.addto           : function: 0xa4c8818
> T.analyze         : function: 0xb1c27b0
> T.cached          : table: 0xb1c2240
> T.cached.1 : table: 0xc3f7b18
> T.cached.1.metadata   : table: 0xc3f7d58
> T.cached.1.metadata.kind     : float
> T.cached.1.metadata.name     : figure
> T.cached.1.prefixdata : table: 0xc3f7c68
> T.cached.1.prefixdata.connector : .
> T.cached.1.prefixdata.prefix    : no
> T.cached.1.references : table: 0xc3f7ba8
> T.cached.1.references.reference : ref:asdf
> T.cached.1.titledata  : table: 0xc3f7b40
> T.cached.1.titledata.title : caption 1
> T.cached.2 : table: 0xc467bb8 (like T.cached.1)
> T.cached.3 : table: 0xc4731a8 (like T.cached.1)
> T.cached.4 : table: 0xc47c988
> T.cached.4.metadata   : table: 0xc47d628
> T.cached.4.metadata.kind     : formula
> T.cached.4.metadata.name     : formula
>
> (You can't see it in this e-mail, but the colons of entries in the
> same subtable nicely line up with each other.)
>
> Usage: put showtable.lua in your working directory and run the following code:
>
> \starttext
> % \placefigure[][ref:asdf]{caption 1}{picture 1}
> \startluacode
>      require('showtable')
>      userdata.showtable(structures.lists)
> \stopluacode
> \stoptext
>
> Extra options can be passed as part of an options table. (This allows
> overriding one option without respecifying the others.)
> userdata.showtable(
>      structures.lists,
>      { everything=true, -- descend even into similar-looking siblings
>      tablename='S.L' }
> )
>
> Output is printed to the terminal, alas, because I couldn't discover
> how to print to the log. Anybody know anything about this?

commands.writestatus("mylog",str)

or:

local myreporter = logs.reporter("tables")

myreporter(....)

> Hopefully this may be useful to someone, next time they they're
> hunting for something in the bowels of ConTeXt. Interesting tables to
> look at:
> * userdata.showtable(commands) contains a great miscellanea of helper commands

the commands namespace is used for commands that pipe something to tex 
and/or are calles in a command at the tex end

> * userdata.showtable(context) also contains a great miscellanea of commands

this is the print-to-tex namespace

> * userdata.showtable(tex) seems to show lua access functions to some
> plain tex stuff
> * userdata.showtable(lxml) gives a list of lxml-related functions
>
> Cheers,
> Sietse
>
>
>
> ___________________________________________________________________________________
> If your question is of interest to others as well, please add an entry to the Wiki!
>
> maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
> webpage  : http://www.pragma-ade.nl / http://tex.aanhet.net
> archive  : http://foundry.supelec.fr/projects/contextrev/
> wiki     : http://contextgarden.net
> ___________________________________________________________________________________
>


-- 

-----------------------------------------------------------------
                                           Hans Hagen | PRAGMA ADE
               Ridderstraat 27 | 8061 GH Hasselt | The Netherlands
     tel: 038 477 53 69 | voip: 087 875 68 74 | www.pragma-ade.com
                                              | www.pragma-pod.nl
-----------------------------------------------------------------
___________________________________________________________________________________
If your question is of interest to others as well, please add an entry to the Wiki!

maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
webpage  : http://www.pragma-ade.nl / http://tex.aanhet.net
archive  : http://foundry.supelec.fr/projects/contextrev/
wiki     : http://contextgarden.net
___________________________________________________________________________________


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-09-17 16:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-17 15:47 Exploring the Lua innards of ConTeXt: showtable Sietse Brouwer
2012-09-17 16:45 ` Hans Hagen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).