summaryrefslogtreecommitdiff
path: root/macros/luatex/latex/semesterplannerlua/semesterplannerlua_dmenu.lua
blob: d267d680715bd60e9ae2d6a90621eb570907bdd3 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/usr/bin/env texlua

----------------------
-- HELPER_FUNCTIONS --
----------------------
local function check_installed(prog)
    local r = os.execute("which " .. prog .. "&> /dev/null")
    return r
end

local function help()
    print("Displays a dmenu prompt with the last, current and next events and copies location/url [+password] to the clipboard")
    print()
    print("USAGE:")
    print(string.format("\t%s dataFile [ignoreType ...]", arg[0]))
    print()
    print("OPTIONS:")
    print()
    print("ARGS:")
    print(string.format("\t%-12s\t%s", "<dataFile>",   "path to the input csv file with 'start', 'end', 'title', 'location', 'password', 'type' headers (not written in the file)"))
    print(string.format("\t%-12s\t%s", "",   "location may contain '\\href{location}{url}' in which casethe two fields are extracted"))
    print(string.format("\t%-12s\t%s", "<ignoreType>", "entries with that type are ignored"))
end

local function dur2str(dur)
    return string.format("%02d:%02d", dur//60, dur%60)
end

local function contains(t, ele)
    for _,v in pairs(t) do
        if v == ele then return true end
    end
    return false
end

-------------------
-- PREREQUISITES --
-------------------
if not check_installed("dmenu") then
    print("Error: dmenu has to be installed (options -l, -i and -p required, but these are in the default anyway)")
    os.exit(-1)
end
if not check_installed("xsel") then
    print("Error: xsel has to be installed")
    os.exit(-1)
end

if #arg < 1 then
    print("Error: At least one argument has to be given")
    print()
    help()
    os.exit(-1)
end
if arg[1] == "-h" or arg[1] == "--help" then
    help()
    os.exit(0)
end

local type_exclude = {}
for i=1,#arg do
    table.insert(type_exclude, arg[i])
end

-----------
-- MAIN --
----------

local maxes = {title=0, location=0, type=0}

local before = {diff=25*60*7}
local after  = {diff=25*60*7}

local c = {}

local current   = os.date("*t")
local today     = tonumber(os.date("%u")) - 1
current.minutes = current.min + (today*24 + current.hour)*60

local inputs = loadfile(arg[1], "t", {})() -- easy loading comes with the disadvantage that arbitrary code which is in that file gets executed
for _,ele in ipairs(inputs) do
    if not contains(type_exclude, ele["type"]) then
        ele.start, ele["end"] = tonumber(ele.start), tonumber(ele["end"])
        ele.url      = ele.location:match([[\href ?{(.*)}{.*}]])
        ele.location = ele.location:match([[\href ?{.*}{(.*)}]]) or ele.location

        if maxes.title    < #ele.title    then maxes.title    = #ele.title    end
        if maxes.location < #ele.location then maxes.location = #ele.location end
        if maxes.type     < #ele.type     then maxes.type     = #ele.type     end

        if current.minutes > ele.start and current.minutes < ele["end"] then
            ele.diff = current.minutes-ele["start"]
            table.insert(c, ele)
        elseif current.minutes < ele.start then
            if ele.start - current.minutes < before.diff then
                before = {diff=ele.start-current.minutes}
            end
            if ele.start - current.minutes <= before.diff then
                ele.diff = before.diff
                table.insert(before, ele)
            end
        elseif current.minutes > ele["end"] then
            if current.minutes - ele["end"] < after.diff then
                after = {diff=current.minutes-ele["end"]}
            end
            if current.minutes - ele["end"] <= after.diff then
                ele.diff = after.diff
                table.insert(after, ele)
            end
        end
    end
end

maxes = {title=maxes.title < 100 and maxes.title or 99, location=maxes.location < 100 and maxes.location or 99, type=maxes.type < 100 and maxes.type or 99}

local dmenu_in,map = {},{}
for _,x in ipairs(after) do
    local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # ended %s ago", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
    table.insert(dmenu_in, s)
    map[s] = x
end

for _,x in ipairs(c) do
    local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # began %s ago", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
    table.insert(dmenu_in, s)
    map[s] = x
end

for _,x in ipairs(before) do
    local s = string.format("%-".. maxes.title+1+maxes.type .."s %-".. maxes.location+2 .."s # begins in %s", x.title.."-"..x.type, "("..x.location..")", dur2str(x.diff))
    table.insert(dmenu_in, s)
    map[s] = x
end

local dmenu_ins = table.concat(dmenu_in, "\n")

print(dmenu_ins)
-- TODO check for forbidden strings in dmenu_in
local proc = io.popen(string.format("echo '%s' | dmenu -i -l %d -p 'Select entry'", dmenu_ins, #dmenu_in), "r")
local dmenu_out = proc:read("l")
if not dmenu_out then
    os.execute("notify-send 'Uni' 'Nothing selected'")
    os.exit()
end

local sel = map[dmenu_out]
assert(sel, "Error building/reading the lookup table")
if sel.url and sel.url ~= "" then
    os.execute(string.format("echo -n '%s' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied URL to clipboard'", sel.url))
elseif sel.location and sel.location ~= "" then
    os.execute(string.format("echo -n '%s' | xsel -b && notify-send -h -- string:x-canonical-private-synchronous:uni 'Uni' 'Copied URL to clipboard'", sel.location))
    os.execute(string.format("echo -n 'https://portal.mytum.de/campus/roomfinder/search_room_results?searchstring=%s&building=Alle&search=Suche+starten' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied Roomfinder-url to clipboard'", sel.location))
end

if sel.password and sel.password ~= "" then
    os.execute(string.format("sleep 3 && echo -n '%s' | xsel -b && notify-send -h string:x-canonical-private-synchronous:uni 'Uni' 'Copied password to clipboard'", sel.password))
end