summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/typo-man.lmt
blob: 051e888f1df82afee90d6d16b8b58bf8a14bb028 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
if not modules then modules = { } end modules ['typo-man'] = {
    version   = 1.001,
    comment   = "companion to typo-prc.mkiv",
    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
    copyright = "PRAGMA ADE / ConTeXt Development Team",
    license   = "see context related readme files"
}

if not characters then
    -- for testing stand-alone
    require("char-def")
    require("char-ini")
end

local lpegmatch  = lpeg.match
local P, R, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
local global = global or _G

local methods = {
    uppercase = characters.upper,
    lowercase = characters.lower,
    Word      = converters.Word,
    Words     = converters.Words,
}

local function nothing(s) return s end -- we already have that one somewhere

-- table.setmetatableindex(methods,function(t,k)
--     t[k] = nothing
--     return nothing
-- end)

local splitter = lpeg.tsplitat(".")

table.setmetatableindex(methods,function(t,k)
    local s = lpegmatch(splitter,k)
    local v = global
    for i=1,#s do
        v = v[s[i]]
        if not v then
            break
        end
    end
    if not v or v == global then
        v = nothing
    end
    t[k] = v
    return v
end)

local whitespace = lpeg.patterns.whitespace^0
local separator  = whitespace * P("->") * whitespace
local pair       = C((1-separator)^1) * separator * C(P(1)^0)
local list       = Ct((C((1-separator)^1) * separator)^1) * C(P(1)^0)

local pattern = Carg(1) * pair / function(methods,operation,str)
    return methods[operation](str) or str
end

local function apply(str,m)
    return lpegmatch(pattern,str,1,m or methods) or str
end

local function splitspecification(field,m)
    local m, f = lpegmatch(list,field,1,m or methods)
    if m then
        return m, f or field
    else
        return nil, field
    end
end

local function applyspecification(actions,str)
    if actions then
        for i=1,#actions do
            local action = methods[actions[i]]
            if action then
                str = action(str) or str
            end
        end
    end
    return str
end

if not typesetters then typesetters = { } end

typesetters.manipulators = {
    methods            = methods,
    apply              = apply,
    patterns           = {
        pair = pair,
        list = list,
    },
    splitspecification = splitspecification,
    applyspecification = applyspecification,
}

local pattern = Cs((1 - P(1) * P(-1))^0 * (P(".")/"" + P(1)))

methods.stripperiod = function(str) return lpegmatch(pattern,str) end

-- print(apply("hans"))
-- print(apply("uppercase->hans"))
-- print(apply("string.reverse -> hans"))
-- print(apply("uppercase->hans",{ uppercase = string.reverse } ))

-- print(applyspecification(splitspecification("hans")))
-- print(applyspecification(splitspecification("lowercase->uppercase->hans")))
-- print(applyspecification(splitspecification("uppercase->stripperiod->hans.")))

if commands then

    local context = context

    function commands.manipulated(str)
        context(apply(str))
    end

end