reconcile all apps with template.tlv
They may take more or less from it (sieve.tlv in particular takes nothing since call depth doesn't help at all there), but what they take is in the right order so that you can compare across apps.
This commit is contained in:
parent
af9d7a16f3
commit
a8d0c1a56a
30
anagrams.tlv
30
anagrams.tlv
|
@ -61,21 +61,6 @@
|
|||
>end
|
||||
>
|
||||
>-- TODO: backport utf-8 support from Lua 5.3
|
||||
- __teliva_timestamp: original
|
||||
debugy:
|
||||
>debugy = 5
|
||||
- __teliva_timestamp: original
|
||||
dbg:
|
||||
>-- helper for debug by print; overlay debug information towards the right
|
||||
>-- reset debugy every time you refresh screen
|
||||
>function dbg(window, s)
|
||||
> local oldy = 0
|
||||
> local oldx = 0
|
||||
> oldy, oldx = window:getyx()
|
||||
> window:mvaddstr(debugy, 60, s)
|
||||
> debugy = debugy+1
|
||||
> window:mvaddstr(oldy, oldx, '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
|
@ -177,8 +162,7 @@
|
|||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Mon Feb 21 17:45:04 2022
|
||||
- __teliva_timestamp: original
|
||||
sort_letters:
|
||||
>function sort_letters(s)
|
||||
> tmp = {}
|
||||
|
@ -220,12 +204,6 @@
|
|||
> l[#l+1] = elems[i]
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>Show all anagrams of a given word
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
|
@ -233,6 +211,12 @@
|
|||
>menu = {
|
||||
> {'^h', 'backspace'},
|
||||
>}
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>Show all anagrams of a given word
|
||||
- __teliva_timestamp: original
|
||||
word:
|
||||
>word = ''
|
||||
|
|
|
@ -62,90 +62,10 @@
|
|||
>
|
||||
>-- TODO: backport utf-8 support from Lua 5.3
|
||||
- __teliva_timestamp: original
|
||||
debugy:
|
||||
>debugy = 5
|
||||
- __teliva_timestamp: original
|
||||
dbg:
|
||||
>-- helper for debug by print; overlay debug information towards the right
|
||||
>-- reset debugy every time you refresh screen
|
||||
>function dbg(window, s)
|
||||
> local oldy = 0
|
||||
> local oldx = 0
|
||||
> oldy, oldx = window:getyx()
|
||||
> window:mvaddstr(debugy, 60, s)
|
||||
> debugy = debugy+1
|
||||
> window:mvaddstr(oldy, oldx, '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if x == expected then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..tostring(expected)..' but got '..x)
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
> teliva_first_failure = msg
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
>function map(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> table.insert(result, f(x))
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
reduce:
|
||||
>-- only for arrays
|
||||
>function reduce(l, f, init)
|
||||
> result = init
|
||||
> for _, x in ipairs(l) do
|
||||
> result = f(result, x)
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
filter:
|
||||
>-- only for arrays
|
||||
>function filter(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> if f(x) then
|
||||
> table.insert(result, x)
|
||||
> end
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
find_index:
|
||||
>function find_index(arr, x)
|
||||
> for n, y in ipairs(arr) do
|
||||
> if x == y then
|
||||
> return n
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
trim:
|
||||
>function trim(s)
|
||||
> return s:gsub('^%s*', ''):gsub('%s*$', '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
split:
|
||||
>function split(s, d)
|
||||
> result = {}
|
||||
> for match in (s..d):gmatch("(.-)"..d) do
|
||||
> table.insert(result, match);
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {}
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
|
@ -161,11 +81,6 @@
|
|||
> end
|
||||
> window:refresh()
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {}
|
||||
- __teliva_timestamp: original
|
||||
update:
|
||||
>function update(window)
|
||||
|
@ -197,3 +112,6 @@
|
|||
> update(Window)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>beginnings of a file browser..
|
||||
|
|
19
gemini.tlv
19
gemini.tlv
|
@ -76,21 +76,6 @@
|
|||
> debugy = debugy+1
|
||||
> window:mvaddstr(oldy, oldx, '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if x == expected then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..tostring(expected)..' but got '..x)
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
> teliva_first_failure = msg
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
|
@ -355,7 +340,7 @@
|
|||
init_colors:
|
||||
>function init_colors()
|
||||
> for i=0,7 do
|
||||
> curses.init_pair(i, i, 8)
|
||||
> curses.init_pair(i, i, -1)
|
||||
> end
|
||||
> curses.init_pair(8, 7, 0)
|
||||
> curses.init_pair(9, 7, 1)
|
||||
|
@ -364,7 +349,7 @@
|
|||
> curses.init_pair(12, 7, 4)
|
||||
> curses.init_pair(13, 7, 5)
|
||||
> curses.init_pair(14, 7, 6)
|
||||
> curses.init_pair(15, 8, 15)
|
||||
> curses.init_pair(15, -1, 15)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
main:
|
||||
|
|
364
life.tlv
364
life.tlv
|
@ -16,6 +16,370 @@
|
|||
#
|
||||
# If these constraints are violated, Teliva may unceremoniously crash. Please
|
||||
# report bugs at http://akkartik.name/contact
|
||||
- __teliva_timestamp: original
|
||||
str_helpers:
|
||||
>-- some string helpers from http://lua-users.org/wiki/StringIndexing
|
||||
>
|
||||
>-- index characters using []
|
||||
>getmetatable('').__index = function(str,i)
|
||||
> if type(i) == 'number' then
|
||||
> return string.sub(str,i,i)
|
||||
> else
|
||||
> return string[i]
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- ranges using (), selected bytes using {}
|
||||
>getmetatable('').__call = function(str,i,j)
|
||||
> if type(i)~='table' then
|
||||
> return string.sub(str,i,j)
|
||||
> else
|
||||
> local t={}
|
||||
> for k,v in ipairs(i) do
|
||||
> t[k]=string.sub(str,v,v)
|
||||
> end
|
||||
> return table.concat(t)
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- iterate over an ordered sequence
|
||||
>function q(x)
|
||||
> if type(x) == 'string' then
|
||||
> return x:gmatch('.')
|
||||
> else
|
||||
> return ipairs(x)
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- insert within string
|
||||
>function string.insert(str1, str2, pos)
|
||||
> return str1:sub(1,pos)..str2..str1:sub(pos+1)
|
||||
>end
|
||||
>
|
||||
>function string.remove(s, pos)
|
||||
> return s:sub(1,pos-1)..s:sub(pos+1)
|
||||
>end
|
||||
>
|
||||
>-- TODO: backport utf-8 support from Lua 5.3
|
||||
- __teliva_timestamp: original
|
||||
debugy:
|
||||
>debugy = 5
|
||||
- __teliva_timestamp: original
|
||||
dbg:
|
||||
>-- helper for debug by print; overlay debug information towards the right
|
||||
>-- reset debugy every time you refresh screen
|
||||
>function dbg(window, s)
|
||||
> local oldy = 0
|
||||
> local oldx = 0
|
||||
> oldy, oldx = window:getyx()
|
||||
> window:mvaddstr(debugy, 60, s)
|
||||
> debugy = debugy+1
|
||||
> window:mvaddstr(oldy, oldx, '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if eq(x, expected) then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..str(expected)..' but got '..str(x))
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
> teliva_first_failure = msg
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
eq:
|
||||
>function eq(a, b)
|
||||
> if type(a) ~= type(b) then return false end
|
||||
> if type(a) == 'table' then
|
||||
> if #a ~= #b then return false end
|
||||
> for k, v in pairs(a) do
|
||||
> if b[k] ~= v then
|
||||
> return false
|
||||
> end
|
||||
> return true
|
||||
> end
|
||||
> end
|
||||
> return a == b
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
str:
|
||||
>-- smarter tostring
|
||||
>-- slow; used only for debugging
|
||||
>function str(x)
|
||||
> if type(x) == 'table' then
|
||||
> local result = ''
|
||||
> result = result..#x..'{'
|
||||
> for k, v in pairs(x) do
|
||||
> result = result..str(k)..'='..str(v)..', '
|
||||
> end
|
||||
> result = result..'}'
|
||||
> return result
|
||||
> end
|
||||
> return tostring(x)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
>function map(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> table.insert(result, f(x))
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
reduce:
|
||||
>-- only for arrays
|
||||
>function reduce(l, f, init)
|
||||
> result = init
|
||||
> for _, x in ipairs(l) do
|
||||
> result = f(result, x)
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
filter:
|
||||
>-- only for arrays
|
||||
>function filter(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> if f(x) then
|
||||
> table.insert(result, x)
|
||||
> end
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
find_index:
|
||||
>function find_index(arr, x)
|
||||
> for n, y in ipairs(arr) do
|
||||
> if x == y then
|
||||
> return n
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
trim:
|
||||
>function trim(s)
|
||||
> return s:gsub('^%s*', ''):gsub('%s*$', '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
split:
|
||||
>function split(s, d)
|
||||
> result = {}
|
||||
> for match in (s..d):gmatch("(.-)"..d) do
|
||||
> table.insert(result, match);
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Mon Feb 21 17:45:04 2022
|
||||
sort_letters:
|
||||
>function sort_letters(s)
|
||||
> tmp = {}
|
||||
> for i=1,#s do
|
||||
> table.insert(tmp, s[i])
|
||||
> end
|
||||
> table.sort(tmp)
|
||||
> local result = ''
|
||||
> for _, c in pairs(tmp) do
|
||||
> result = result..c
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function test_sort_letters(s)
|
||||
> check_eq(sort_letters(''), '', 'test_sort_letters: empty')
|
||||
> check_eq(sort_letters('ba'), 'ab', 'test_sort_letters: non-empty')
|
||||
> check_eq(sort_letters('abba'), 'aabb', 'test_sort_letters: duplicates')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
count_letters:
|
||||
>function count_letters(s)
|
||||
> local result = {}
|
||||
> for i=1,string.len(s) do
|
||||
> local c = s[i]
|
||||
> if result[c] == nil then
|
||||
> result[c] = 1
|
||||
> else
|
||||
> result[c] = result[c] + 1
|
||||
> end
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
append:
|
||||
>-- concatenate list 'elems' into 'l', modifying 'l' in the process
|
||||
>function append(l, elems)
|
||||
> for i=1,#elems do
|
||||
> l[#l+1] = elems[i]
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {}
|
||||
- __teliva_timestamp: original
|
||||
window:
|
||||
>-- constructor for fake screen and window
|
||||
>-- call it like this:
|
||||
>-- local w = window{
|
||||
>-- kbd=kbd('abc'),
|
||||
>-- scr=scr{h=5, w=4},
|
||||
>-- }
|
||||
>-- eventually it'll do everything a real ncurses window can
|
||||
>function window(h)
|
||||
> h.__index = h
|
||||
> setmetatable(h, h)
|
||||
> h.__index = function(table, key)
|
||||
> return rawget(h, key)
|
||||
> end
|
||||
> h.getch = function(self)
|
||||
> return table.remove(h.kbd, 1)
|
||||
> end
|
||||
> h.addch = function(self, c)
|
||||
> local scr = self.scr
|
||||
> if scr.cursy <= scr.h then
|
||||
> scr[scr.cursy][scr.cursx] = c
|
||||
> scr.cursx = scr.cursx+1
|
||||
> if scr.cursx > scr.w then
|
||||
> scr.cursy = scr.cursy+1
|
||||
> scr.cursx = 1
|
||||
> end
|
||||
> end
|
||||
> end
|
||||
> h.addstr = function(self, s)
|
||||
> for i=1,string.len(s) do
|
||||
> self:addch(s[i])
|
||||
> end
|
||||
> end
|
||||
> h.mvaddch = function(self, y, x, c)
|
||||
> self.scr.cursy = y
|
||||
> self.scr.cursx = x
|
||||
> self.addch(c)
|
||||
> end
|
||||
> h.mvaddstr = function(self, y, x, s)
|
||||
> self.scr.cursy = y
|
||||
> self.scr.cursx = x
|
||||
> self:addstr(s)
|
||||
> end
|
||||
> return h
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
kbd:
|
||||
>function kbd(keys)
|
||||
> local result = {}
|
||||
> for i=1,string.len(keys) do
|
||||
> table.insert(result, keys[i])
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
scr:
|
||||
>function scr(props)
|
||||
> props.cursx = 1
|
||||
> props.cursy = 1
|
||||
> for y=1,props.h do
|
||||
> props[y] = {}
|
||||
> for x=1,props.w do
|
||||
> props[y][x] = ' '
|
||||
> end
|
||||
> end
|
||||
> return props
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Thu Mar 3 22:04:15 2022
|
||||
check_screen:
|
||||
>function check_screen(window, contents, message)
|
||||
> local x, y = 1, 1
|
||||
> for i=1,string.len(contents) do
|
||||
> check_eq(contents[i], window.scr[y][x], message..'/'..y..','..x)
|
||||
> x = x+1
|
||||
> if x > window.scr.w then
|
||||
> y = y+1
|
||||
> x = 1
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- putting it all together, an example test of both keyboard and screen
|
||||
>function test_check_screen()
|
||||
> local lines = {
|
||||
> c='123',
|
||||
> d='234',
|
||||
> a='345',
|
||||
> b='456',
|
||||
> }
|
||||
> local w = window{
|
||||
> kbd=kbd('abc'),
|
||||
> scr=scr{h=3, w=5},
|
||||
> }
|
||||
> local y = 1
|
||||
> while true do
|
||||
> local c = w:getch()
|
||||
> if c == nil then break end
|
||||
> w:mvaddstr(y, 1, lines[c])
|
||||
> y = y+1
|
||||
> end
|
||||
> check_screen(w, '345 '..
|
||||
> '456 '..
|
||||
> '123 ',
|
||||
> 'test_check_screen')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
start_reading:
|
||||
>-- primitive for reading files from a file system (or, later, network)
|
||||
>-- returns a channel or nil on error
|
||||
>-- read lines from the channel using :recv()
|
||||
>-- recv() on the channel will indicate end of file.
|
||||
>function start_reading(fs, filename)
|
||||
> local result = task.Channel:new()
|
||||
> local infile = io.open(filename)
|
||||
> if infile == nil then return nil end
|
||||
> task.spawn(reading_task, infile, result)
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function reading_task(infile, chanout)
|
||||
> for line in infile:lines() do
|
||||
> chanout:send(line)
|
||||
> end
|
||||
> chanout:send(nil) -- eof
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
start_writing:
|
||||
>-- primitive for writing files to a file system (or, later, network)
|
||||
>-- returns a channel or nil on error
|
||||
>-- write to the channel using :send()
|
||||
>-- indicate you're done writing by calling :close()
|
||||
>-- file will not be externally visible until :close()
|
||||
>function start_writing(fs, filename)
|
||||
> local result = task.Channel:new()
|
||||
> local initial_filename = os.tmpname()
|
||||
> local outfile = io.open(initial_filename, 'w')
|
||||
> if outfile == nil then return nil end
|
||||
> result.close = function()
|
||||
> result:send(nil) -- end of file
|
||||
> outfile:close()
|
||||
> os.rename(initial_filename, filename)
|
||||
> end
|
||||
> task.spawn(writing_task, outfile, result)
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function writing_task(outfile, chanin)
|
||||
> while true do
|
||||
> local line = chanin:recv()
|
||||
> if line == nil then break end -- end of file
|
||||
> outfile:write(line)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
grid:
|
||||
>-- main data structure
|
||||
|
|
239
sieve.tlv
239
sieve.tlv
|
@ -16,249 +16,14 @@
|
|||
#
|
||||
# If these constraints are violated, Teliva may unceremoniously crash. Please
|
||||
# report bugs at http://akkartik.name/contact
|
||||
- __teliva_timestamp: original
|
||||
str_helpers:
|
||||
>-- some string helpers from http://lua-users.org/wiki/StringIndexing
|
||||
>
|
||||
>-- index characters using []
|
||||
>getmetatable('').__index = function(str,i)
|
||||
> if type(i) == 'number' then
|
||||
> return string.sub(str,i,i)
|
||||
> else
|
||||
> return string[i]
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- ranges using (), selected bytes using {}
|
||||
>getmetatable('').__call = function(str,i,j)
|
||||
> if type(i)~='table' then
|
||||
> return string.sub(str,i,j)
|
||||
> else
|
||||
> local t={}
|
||||
> for k,v in ipairs(i) do
|
||||
> t[k]=string.sub(str,v,v)
|
||||
> end
|
||||
> return table.concat(t)
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- iterate over an ordered sequence
|
||||
>function q(x)
|
||||
> if type(x) == 'string' then
|
||||
> return x:gmatch('.')
|
||||
> else
|
||||
> return ipairs(x)
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- insert within string
|
||||
>function string.insert(str1, str2, pos)
|
||||
> return str1:sub(1,pos)..str2..str1:sub(pos+1)
|
||||
>end
|
||||
>
|
||||
>function string.remove(s, pos)
|
||||
> return s:sub(1,pos-1)..s:sub(pos+1)
|
||||
>end
|
||||
>
|
||||
>-- TODO: backport utf-8 support from Lua 5.3
|
||||
- __teliva_timestamp: original
|
||||
debugy:
|
||||
>debugy = 5
|
||||
- __teliva_timestamp: original
|
||||
dbg:
|
||||
>-- helper for debug by print; overlay debug information towards the right
|
||||
>-- reset debugy every time you refresh screen
|
||||
>function dbg(window, s)
|
||||
> local oldy = 0
|
||||
> local oldx = 0
|
||||
> oldy, oldx = window:getyx()
|
||||
> window:mvaddstr(debugy, 60, s)
|
||||
> debugy = debugy+1
|
||||
> window:mvaddstr(oldy, oldx, '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if eq(x, expected) then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..str(expected)..' but got '..str(x))
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
> teliva_first_failure = msg
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
eq:
|
||||
>function eq(a, b)
|
||||
> if type(a) ~= type(b) then return false end
|
||||
> if type(a) == 'table' then
|
||||
> if #a ~= #b then return false end
|
||||
> for k, v in pairs(a) do
|
||||
> if b[k] ~= v then
|
||||
> return false
|
||||
> end
|
||||
> return true
|
||||
> end
|
||||
> end
|
||||
> return a == b
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
str:
|
||||
>-- smarter tostring
|
||||
>-- slow; used only for debugging
|
||||
>function str(x)
|
||||
> if type(x) == 'table' then
|
||||
> local result = ''
|
||||
> result = result..#x..'{'
|
||||
> for k, v in pairs(x) do
|
||||
> result = result..str(k)..'='..str(v)..', '
|
||||
> end
|
||||
> result = result..'}'
|
||||
> return result
|
||||
> end
|
||||
> return tostring(x)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
>function map(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> table.insert(result, f(x))
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
reduce:
|
||||
>-- only for arrays
|
||||
>function reduce(l, f, init)
|
||||
> result = init
|
||||
> for _, x in ipairs(l) do
|
||||
> result = f(result, x)
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
filter:
|
||||
>-- only for arrays
|
||||
>function filter(l, f)
|
||||
> result = {}
|
||||
> for _, x in ipairs(l) do
|
||||
> if f(x) then
|
||||
> table.insert(result, x)
|
||||
> end
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
find_index:
|
||||
>function find_index(arr, x)
|
||||
> for n, y in ipairs(arr) do
|
||||
> if x == y then
|
||||
> return n
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
trim:
|
||||
>function trim(s)
|
||||
> return s:gsub('^%s*', ''):gsub('%s*$', '')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
split:
|
||||
>function split(s, d)
|
||||
> result = {}
|
||||
> for match in (s..d):gmatch("(.-)"..d) do
|
||||
> table.insert(result, match);
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Mon Feb 21 17:45:04 2022
|
||||
sort_string:
|
||||
>function sort_string(s)
|
||||
> tmp = {}
|
||||
> for i=1,#s do
|
||||
> table.insert(tmp, s[i])
|
||||
> end
|
||||
> table.sort(tmp)
|
||||
> local result = ''
|
||||
> for _, c in pairs(tmp) do
|
||||
> result = result..c
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function test_sort_string(s)
|
||||
> check_eq(sort_string(''), '', 'test_sort_string: empty')
|
||||
> check_eq(sort_string('ba'), 'ab', 'test_sort_string: non-empty')
|
||||
> check_eq(sort_string('abba'), 'aabb', 'test_sort_string: duplicates')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
append:
|
||||
>-- concatenate list 'elems' into 'l', modifying 'l' in the process
|
||||
>function append(l, elems)
|
||||
> for i=1,#elems do
|
||||
> l[#l+1] = elems[i]
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
render:
|
||||
>function render(window)
|
||||
> window:clear()
|
||||
> -- draw stuff to screen here
|
||||
> window:attron(curses.A_BOLD)
|
||||
> window:mvaddstr(1, 5, "example app")
|
||||
> window:attrset(curses.A_NORMAL)
|
||||
> for i=0,15 do
|
||||
> window:attrset(curses.color_pair(i))
|
||||
> window:mvaddstr(3+i, 5, "========================")
|
||||
> end
|
||||
> window:refresh()
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {}
|
||||
- __teliva_timestamp: original
|
||||
update:
|
||||
>function update(window)
|
||||
> local key = window:getch()
|
||||
> -- process key here
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
init_colors:
|
||||
>function init_colors()
|
||||
> for i=0,7 do
|
||||
> curses.init_pair(i, i, -1)
|
||||
> end
|
||||
> curses.init_pair(8, 7, 0)
|
||||
> curses.init_pair(9, 7, 1)
|
||||
> curses.init_pair(10, 7, 2)
|
||||
> curses.init_pair(11, 7, 3)
|
||||
> curses.init_pair(12, 7, 4)
|
||||
> curses.init_pair(13, 7, 5)
|
||||
> curses.init_pair(14, 7, 6)
|
||||
> curses.init_pair(15, -1, 15)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
main:
|
||||
>function main()
|
||||
> init_colors()
|
||||
>
|
||||
> while true do
|
||||
> render(Window)
|
||||
> update(Window)
|
||||
> end
|
||||
>end
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>To show a brief description of the app on the 'big picture' screen, put the text in a special buffer called 'doc:blurb'.
|
||||
|
|
110
template.tlv
110
template.tlv
|
@ -177,8 +177,7 @@
|
|||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Mon Feb 21 17:45:04 2022
|
||||
- __teliva_timestamp: original
|
||||
sort_letters:
|
||||
>function sort_letters(s)
|
||||
> tmp = {}
|
||||
|
@ -220,64 +219,14 @@
|
|||
> l[#l+1] = elems[i]
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
render:
|
||||
>function render(window)
|
||||
> window:clear()
|
||||
> -- draw stuff to screen here
|
||||
> window:attron(curses.A_BOLD)
|
||||
> window:mvaddstr(1, 5, "example app")
|
||||
> window:attrset(curses.A_NORMAL)
|
||||
> for i=0,15 do
|
||||
> window:attrset(curses.color_pair(i))
|
||||
> window:mvaddstr(3+i, 5, "========================")
|
||||
> end
|
||||
> window:refresh()
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {}
|
||||
- __teliva_timestamp: original
|
||||
update:
|
||||
>function update(window)
|
||||
> local key = window:getch()
|
||||
> -- process key here
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
init_colors:
|
||||
>function init_colors()
|
||||
> for i=0,7 do
|
||||
> curses.init_pair(i, i, -1)
|
||||
> end
|
||||
> curses.init_pair(8, 7, 0)
|
||||
> curses.init_pair(9, 7, 1)
|
||||
> curses.init_pair(10, 7, 2)
|
||||
> curses.init_pair(11, 7, 3)
|
||||
> curses.init_pair(12, 7, 4)
|
||||
> curses.init_pair(13, 7, 5)
|
||||
> curses.init_pair(14, 7, 6)
|
||||
> curses.init_pair(15, -1, 15)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
main:
|
||||
>function main()
|
||||
> init_colors()
|
||||
>
|
||||
> while true do
|
||||
> render(Window)
|
||||
> update(Window)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>To show a brief description of the app on the 'big picture' screen, put the text in a special buffer called 'doc:blurb'.
|
||||
>
|
||||
>You can also override the default big picture screen entirely by creating a buffer called 'doc:main'.
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
window:
|
||||
>-- constructor for fake screen and window
|
||||
|
@ -346,8 +295,7 @@
|
|||
> end
|
||||
> return props
|
||||
>end
|
||||
- __teliva_timestamp:
|
||||
>Thu Mar 3 22:04:15 2022
|
||||
- __teliva_timestamp: original
|
||||
check_screen:
|
||||
>function check_screen(window, contents, message)
|
||||
> local x, y = 1, 1
|
||||
|
@ -433,3 +381,53 @@
|
|||
> outfile:write(line)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
render:
|
||||
>function render(window)
|
||||
> window:clear()
|
||||
> -- draw stuff to screen here
|
||||
> window:attron(curses.A_BOLD)
|
||||
> window:mvaddstr(1, 5, "example app")
|
||||
> window:attrset(curses.A_NORMAL)
|
||||
> for i=0,15 do
|
||||
> window:attrset(curses.color_pair(i))
|
||||
> window:mvaddstr(3+i, 5, "========================")
|
||||
> end
|
||||
> window:refresh()
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
update:
|
||||
>function update(window)
|
||||
> local key = window:getch()
|
||||
> -- process key here
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
init_colors:
|
||||
>function init_colors()
|
||||
> for i=0,7 do
|
||||
> curses.init_pair(i, i, -1)
|
||||
> end
|
||||
> curses.init_pair(8, 7, 0)
|
||||
> curses.init_pair(9, 7, 1)
|
||||
> curses.init_pair(10, 7, 2)
|
||||
> curses.init_pair(11, 7, 3)
|
||||
> curses.init_pair(12, 7, 4)
|
||||
> curses.init_pair(13, 7, 5)
|
||||
> curses.init_pair(14, 7, 6)
|
||||
> curses.init_pair(15, -1, 15)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
main:
|
||||
>function main()
|
||||
> init_colors()
|
||||
>
|
||||
> while true do
|
||||
> render(Window)
|
||||
> update(Window)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
doc:blurb:
|
||||
>To show a brief description of the app on the 'big picture' screen, put the text in a special buffer called 'doc:blurb'.
|
||||
>
|
||||
>You can also override the default big picture screen entirely by creating a buffer called 'doc:main'.
|
||||
|
|
|
@ -79,11 +79,11 @@
|
|||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if x == expected then
|
||||
> if eq(x, expected) then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..tostring(expected)..' but got '..x)
|
||||
> print(' expected '..str(expected)..' but got '..str(x))
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
|
@ -91,6 +91,37 @@
|
|||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
eq:
|
||||
>function eq(a, b)
|
||||
> if type(a) ~= type(b) then return false end
|
||||
> if type(a) == 'table' then
|
||||
> if #a ~= #b then return false end
|
||||
> for k, v in pairs(a) do
|
||||
> if b[k] ~= v then
|
||||
> return false
|
||||
> end
|
||||
> return true
|
||||
> end
|
||||
> end
|
||||
> return a == b
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
str:
|
||||
>-- smarter tostring
|
||||
>-- slow; used only for debugging
|
||||
>function str(x)
|
||||
> if type(x) == 'table' then
|
||||
> local result = ''
|
||||
> result = result..#x..'{'
|
||||
> for k, v in pairs(x) do
|
||||
> result = result..str(k)..'='..str(v)..', '
|
||||
> end
|
||||
> result = result..'}'
|
||||
> return result
|
||||
> end
|
||||
> return tostring(x)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
|
@ -146,16 +177,18 @@
|
|||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
>curses.curs_set(0) -- we'll simulate our own cursor
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
>-- arrays of strings to the menu array.
|
||||
>menu = {
|
||||
> {'^k', 'clear'},
|
||||
> {'^w', 'write prose to file "toot" (edit hotkey does NOT save)'},
|
||||
>}
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
>curses.curs_set(0) -- we'll simulate our own cursor
|
||||
- __teliva_timestamp: original
|
||||
main:
|
||||
>function main()
|
||||
|
|
243
zet.tlv
243
zet.tlv
|
@ -79,11 +79,11 @@
|
|||
- __teliva_timestamp: original
|
||||
check_eq:
|
||||
>function check_eq(x, expected, msg)
|
||||
> if x == expected then
|
||||
> if eq(x, expected) then
|
||||
> Window:addch('.')
|
||||
> else
|
||||
> print('F - '..msg)
|
||||
> print(' expected '..tostring(expected)..' but got '..x)
|
||||
> print(' expected '..str(expected)..' but got '..str(x))
|
||||
> teliva_num_test_failures = teliva_num_test_failures + 1
|
||||
> -- overlay first test failure on editors
|
||||
> if teliva_first_failure == nil then
|
||||
|
@ -91,6 +91,37 @@
|
|||
> end
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
eq:
|
||||
>function eq(a, b)
|
||||
> if type(a) ~= type(b) then return false end
|
||||
> if type(a) == 'table' then
|
||||
> if #a ~= #b then return false end
|
||||
> for k, v in pairs(a) do
|
||||
> if b[k] ~= v then
|
||||
> return false
|
||||
> end
|
||||
> return true
|
||||
> end
|
||||
> end
|
||||
> return a == b
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
str:
|
||||
>-- smarter tostring
|
||||
>-- slow; used only for debugging
|
||||
>function str(x)
|
||||
> if type(x) == 'table' then
|
||||
> local result = ''
|
||||
> result = result..#x..'{'
|
||||
> for k, v in pairs(x) do
|
||||
> result = result..str(k)..'='..str(v)..', '
|
||||
> end
|
||||
> result = result..'}'
|
||||
> return result
|
||||
> end
|
||||
> return tostring(x)
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
map:
|
||||
>-- only for arrays
|
||||
|
@ -147,15 +178,47 @@
|
|||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
spaces:
|
||||
>function spaces(n)
|
||||
> for i=1,n do
|
||||
> Window:addch(' ')
|
||||
sort_letters:
|
||||
>function sort_letters(s)
|
||||
> tmp = {}
|
||||
> for i=1,#s do
|
||||
> table.insert(tmp, s[i])
|
||||
> end
|
||||
> table.sort(tmp)
|
||||
> local result = ''
|
||||
> for _, c in pairs(tmp) do
|
||||
> result = result..c
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function test_sort_letters(s)
|
||||
> check_eq(sort_letters(''), '', 'test_sort_letters: empty')
|
||||
> check_eq(sort_letters('ba'), 'ab', 'test_sort_letters: non-empty')
|
||||
> check_eq(sort_letters('abba'), 'aabb', 'test_sort_letters: duplicates')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
count_letters:
|
||||
>function count_letters(s)
|
||||
> local result = {}
|
||||
> for i=1,string.len(s) do
|
||||
> local c = s[i]
|
||||
> if result[c] == nil then
|
||||
> result[c] = 1
|
||||
> else
|
||||
> result[c] = result[c] + 1
|
||||
> end
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
append:
|
||||
>-- concatenate list 'elems' into 'l', modifying 'l' in the process
|
||||
>function append(l, elems)
|
||||
> for i=1,#elems do
|
||||
> l[#l+1] = elems[i]
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
menu:
|
||||
>-- To show app-specific hotkeys in the menu bar, add hotkey/command
|
||||
|
@ -163,6 +226,170 @@
|
|||
>menu = {
|
||||
> {'^e', 'edit'},
|
||||
>}
|
||||
- __teliva_timestamp: original
|
||||
Window:
|
||||
>Window = curses.stdscr()
|
||||
- __teliva_timestamp: original
|
||||
window:
|
||||
>-- constructor for fake screen and window
|
||||
>-- call it like this:
|
||||
>-- local w = window{
|
||||
>-- kbd=kbd('abc'),
|
||||
>-- scr=scr{h=5, w=4},
|
||||
>-- }
|
||||
>-- eventually it'll do everything a real ncurses window can
|
||||
>function window(h)
|
||||
> h.__index = h
|
||||
> setmetatable(h, h)
|
||||
> h.__index = function(table, key)
|
||||
> return rawget(h, key)
|
||||
> end
|
||||
> h.getch = function(self)
|
||||
> return table.remove(h.kbd, 1)
|
||||
> end
|
||||
> h.addch = function(self, c)
|
||||
> local scr = self.scr
|
||||
> if scr.cursy <= scr.h then
|
||||
> scr[scr.cursy][scr.cursx] = c
|
||||
> scr.cursx = scr.cursx+1
|
||||
> if scr.cursx > scr.w then
|
||||
> scr.cursy = scr.cursy+1
|
||||
> scr.cursx = 1
|
||||
> end
|
||||
> end
|
||||
> end
|
||||
> h.addstr = function(self, s)
|
||||
> for i=1,string.len(s) do
|
||||
> self:addch(s[i])
|
||||
> end
|
||||
> end
|
||||
> h.mvaddch = function(self, y, x, c)
|
||||
> self.scr.cursy = y
|
||||
> self.scr.cursx = x
|
||||
> self.addch(c)
|
||||
> end
|
||||
> h.mvaddstr = function(self, y, x, s)
|
||||
> self.scr.cursy = y
|
||||
> self.scr.cursx = x
|
||||
> self:addstr(s)
|
||||
> end
|
||||
> return h
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
kbd:
|
||||
>function kbd(keys)
|
||||
> local result = {}
|
||||
> for i=1,string.len(keys) do
|
||||
> table.insert(result, keys[i])
|
||||
> end
|
||||
> return result
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
scr:
|
||||
>function scr(props)
|
||||
> props.cursx = 1
|
||||
> props.cursy = 1
|
||||
> for y=1,props.h do
|
||||
> props[y] = {}
|
||||
> for x=1,props.w do
|
||||
> props[y][x] = ' '
|
||||
> end
|
||||
> end
|
||||
> return props
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
check_screen:
|
||||
>function check_screen(window, contents, message)
|
||||
> local x, y = 1, 1
|
||||
> for i=1,string.len(contents) do
|
||||
> check_eq(contents[i], window.scr[y][x], message..'/'..y..','..x)
|
||||
> x = x+1
|
||||
> if x > window.scr.w then
|
||||
> y = y+1
|
||||
> x = 1
|
||||
> end
|
||||
> end
|
||||
>end
|
||||
>
|
||||
>-- putting it all together, an example test of both keyboard and screen
|
||||
>function test_check_screen()
|
||||
> local lines = {
|
||||
> c='123',
|
||||
> d='234',
|
||||
> a='345',
|
||||
> b='456',
|
||||
> }
|
||||
> local w = window{
|
||||
> kbd=kbd('abc'),
|
||||
> scr=scr{h=3, w=5},
|
||||
> }
|
||||
> local y = 1
|
||||
> while true do
|
||||
> local c = w:getch()
|
||||
> if c == nil then break end
|
||||
> w:mvaddstr(y, 1, lines[c])
|
||||
> y = y+1
|
||||
> end
|
||||
> check_screen(w, '345 '..
|
||||
> '456 '..
|
||||
> '123 ',
|
||||
> 'test_check_screen')
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
start_reading:
|
||||
>-- primitive for reading files from a file system (or, later, network)
|
||||
>-- returns a channel or nil on error
|
||||
>-- read lines from the channel using :recv()
|
||||
>-- recv() on the channel will indicate end of file.
|
||||
>function start_reading(fs, filename)
|
||||
> local result = task.Channel:new()
|
||||
> local infile = io.open(filename)
|
||||
> if infile == nil then return nil end
|
||||
> task.spawn(reading_task, infile, result)
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function reading_task(infile, chanout)
|
||||
> for line in infile:lines() do
|
||||
> chanout:send(line)
|
||||
> end
|
||||
> chanout:send(nil) -- eof
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
start_writing:
|
||||
>-- primitive for writing files to a file system (or, later, network)
|
||||
>-- returns a channel or nil on error
|
||||
>-- write to the channel using :send()
|
||||
>-- indicate you're done writing by calling :close()
|
||||
>-- file will not be externally visible until :close()
|
||||
>function start_writing(fs, filename)
|
||||
> local result = task.Channel:new()
|
||||
> local initial_filename = os.tmpname()
|
||||
> local outfile = io.open(initial_filename, 'w')
|
||||
> if outfile == nil then return nil end
|
||||
> result.close = function()
|
||||
> result:send(nil) -- end of file
|
||||
> outfile:close()
|
||||
> os.rename(initial_filename, filename)
|
||||
> end
|
||||
> task.spawn(writing_task, outfile, result)
|
||||
> return result
|
||||
>end
|
||||
>
|
||||
>function writing_task(outfile, chanin)
|
||||
> while true do
|
||||
> local line = chanin:recv()
|
||||
> if line == nil then break end -- end of file
|
||||
> outfile:write(line)
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
spaces:
|
||||
>function spaces(n)
|
||||
> for i=1,n do
|
||||
> Window:addch(' ')
|
||||
> end
|
||||
>end
|
||||
- __teliva_timestamp: original
|
||||
init_colors:
|
||||
>function init_colors()
|
||||
|
|
Loading…
Reference in New Issue