1
0
Fork
You've already forked ponder.lua
0
small utility that helps pondering
  • Lua 100%
2026年03月09日 09:19:03 +01:00
.gitignore Initial commit 2026年02月22日 18:45:53 +01:00
LICENSE Added a license to the project. Nothing more, nothing less. 2026年02月22日 20:29:08 +01:00
ponder.lua so i started to work on a simple ELIZA implementation that is not quite as cringey as the original. the goal would be to have a relatively simple chat that mirrors what I'm saying in order to spur being able to express things. 2026年03月09日 09:19:03 +01:00
README.md so i started to work on a simple ELIZA implementation that is not quite as cringey as the original. the goal would be to have a relatively simple chat that mirrors what I'm saying in order to spur being able to express things. 2026年03月09日 09:19:03 +01:00

ponder.lua

small utility that helps pondering

I do some journaling every day and sometimes I reflect on things. nano is my go-to editor for linear writing. Every now and then I find myself doing the same reflective exercises, like asking "What? So What? Now What?" 1 , and in other moments I just wish to save an ELIZA 2 discussion as a plaintext file.

So let's try to do this as a little utility! And, besides, I also want to learn Lua and this seems like a good oportunity.


-- the reflection needs to be saved somewhere
<<save>>
-- question helper function
<<question>>
-- questions for every type of reflection
<<header>>
-- let's start with a simple exercise
<<what>>
-- an attempt to implement a simple ELIZA
<<eliza>>
-- entry point to the script
<<cmd>>

Saving Reflections

This function will write a given reflection to a markdown file with a little bit of frontmatter. That's all there is to it.


function save(topic, tags, reflection)
 -- we need a timestamp for our reflection
 local timestamp = os.time()
 -- and a file to write to
 local file = io.open(os.date('%Y-%m-%d', timestamp) .. ' ' .. topic .. '.md', 'w')
 file:write('---\n')
 file:write('title: "' .. topic .. '"\n')
 file:write('timestamp: ' .. timestamp .. '\n')
 if tags ~= '' then
 file:write('tags:\n')
 for tag in string.gmatch(tags, '([^,]+)') do
 file:write(' - ' .. tag .. '\n')
 end
 end
 file:write('---\n')
 file:write(reflection)
 file:close()
 print('\nOkay bye!')
end

Question

Small helper function for asking a question and returning question and answer.


function question(q)
 -- asking
 print('\n~ ' .. q)
 io.write('~ ')
 -- answering
 return io.read()
end

Header

This questions are asked before every reflection. They help me organize the reflections later.


function header()
 -- let's use four variables to safe topic and reflections
 local topic = question('Topic of your reflection?')
 -- I like tags as transversal connectors
 local tags = question('Any tags for this reflection?')
 return topic, tags
end

What?

This reflection follows the classical What? So What? Now What? pattern. First you describe what you did, in pratical terms. Then you try to explress why that is important or meaningful. And lastly you state how you plan to continue.


function what()
 local topic, tags = header()
 local reflection = '# ' .. topic
 local questions = {'What?', 'So What?', 'Now What?'}
 for i = 1, #questions do
 local answer = question(questions[i])
 reflection = reflection .. '\n\n## ' .. questions[i] .. '\n' .. answer
 end
 reflection = reflection .. '\n'
 -- goodbye
 save(topic, tags, reflection)
 
end

ELIZA

I was wondering if chatting would be a nice way of reflecting. ELIZA seemed to work for some people so I will try to create a simple implementation of that and see where it goes. The idea would be to start with something of concern and have ELIZA bounce back questions that keep cognitive engagement going. After I would just save the entire chat.


function eliza()
 local topic, tags = header()
 local reflection = '# ' .. topic
 local chatting = true
 -- exit values
 local exits = {'quit', 'goodbye', 'bye'}
 local q = ''
 local a = ''
 -- questions
 local welcome_qs = {'What brought you here today?', 'Hi, how are you feeling today?', 'What\'s up?'}
 local generic_qs = {}
 local want_ts = {'want', 'need', 'long', 'crave'}
 local want_qs = {'You mentioned you #1ed #2?', 'Why is it you #1 #2?'}
 
 -- keep on chatting
 while chatting do
 -- create a local copy with lower characters only; easier to search thing
 local _a = a:lower()
 -- introduction question
 if _a == '' or _a:find('h%allo') or _a:find('hi[ ,.!?]*$') then
 q = welcome_qs[math.random(1, #welcome_qs)]
 else
 q = 'generic question'
 end
 -- last answer contained one of the want trigger-words
 for i = 1, #want_ts do
 local trigger = want_ts[i]
 if _a:find(trigger) then
 local x = _a:match(trigger .. 's? ([^,]*)')
 x = x:gsub('[.,!?]', '')
 q = string.gsub(want_qs[math.random(1, #want_qs)], '#1', trigger)
 q = q:gsub('#2', x)
 end
 end
 a = question(q)
 reflection = reflection .. '\n\n## ' .. q .. '\n' .. a
 -- check if the answer contained an exit key word
 for i = 1, #exits do
 if a == exits[i] then
 chatting = false
 end
 end
 end
 reflection = reflection .. '\n'
 -- goodbye
 save(topic, tags, reflection)
end

CMD

Let's let ponder know which reflection we want, and I just default to "What?" for now.


-- set default to what
local type = 'what'
-- check what was passed
if arg[1] then
 type = arg[1]
end
-- execute the correct reflection
if type == 'what' then
 what()
end
if type == 'eliza' then
 eliza()
end

Ideas

  • Markov Chain?

License