helium

main vHelium
Dozens B. McCuzzins 2024-08-03 17:09:10 -06:00
parent 365fabdf67
commit 7ec9978919
17 changed files with 550 additions and 383 deletions

View File

@ -18,8 +18,9 @@ See `just compile`.
- [x] random table entries (ADDED in vHydrogen) - [x] random table entries (ADDED in vHydrogen)
- [x] expanding macros (ADDED in vHydrogen) - [x] expanding macros (ADDED in vHydrogen)
- [ ] table files plugin: syntax highlighting + folding - [x] table files plugin: syntax highlighting + folding (ADDED vHelium)
- [ ] expansion filters - [x] expansion filters (ADDED vHelium)
- [ ] table context
## Resources ## Resources

15
doc/History.md 100644
View File

@ -0,0 +1,15 @@
# History
`tbls` began as the Story module for a board game I was writing.
When I completed all the features for the board game itself,
I wanted to add some kind of a generative story engine
based on the state of the game
and on player moves.
This ended up complicating the game quite a bit,
and also I couldn't figure out how or where
to actually incorporate the story.
So I scrapped it for that particular project,
but continued to develop the story engine on its own.
It became `tbls`.

View File

@ -1,4 +1,6 @@
## Tutorial # Tutorial
## Random Selections
At its most basic, `tbls` selects a random element from a table. At its most basic, `tbls` selects a random element from a table.
@ -17,21 +19,19 @@ Shovels
Ace Ace
One One
Two Two
... [...]
Ten
Eleven
Twelve
Thief
Queen Queen
King King
Beast Beast
``` ```
`tbls` might return "Whistles" from suit. `tbls` might return "Whistles" from suit.
Or "Twelve" from card. Or "Two" from card.
## Expansion
But wait there's more. But wait there's more.
`tbls` will also expand macros found in table entries. `tbls` will also expand certain text found in a table entry.
Let's add another table: Let's add another table:
@ -43,6 +43,39 @@ Let's add another table:
When you place the name of a table in `[squarebrackets]`, When you place the name of a table in `[squarebrackets]`,
then `tbls` views that as a placeholder then `tbls` views that as a placeholder
for a random item from that table. for a random item from that table.
And it will expand the text. It will expand that text.
So this might end up being "Thief of Shovels" So 'draw' might end up being "Thief of Shovels"
or "Twelve or Cups". or "Twelve or Cups".
## Filters
`tbls` can run arbitary filters on text after expanding it.
Example filters can be found in `src/flib.fnl`.
To apply filters,
dot-chain them at the end
of a table reference.
Consider the following tables:
```
:: origin
Evelyn eats one [fruit]
Evelyn eats many [fruit.s]
:: fruit
banana
apple
pear
```
`s`, `plural`, and `pluralize`
are all different ways
to call the 'plural' filter function.
Example output:
```
Evelyn eats one pear
Evelyn eats one bananas
```

View File

@ -5,5 +5,5 @@
name: tbls name: tbls
author: dozens@tilde.team author: dozens@tilde.team
created: 2024-07-31 created: 2024-07-31
updated: 2024-08-01 updated: 2024-08-03
version: Hydrogen version: Helium

View File

@ -32,3 +32,11 @@ bump:
# show full metadata # show full metadata
meta: meta:
awk 'FNR==1{print ""}{print}' doc/*.rec | recsel -t meta -j version awk 'FNR==1{print ""}{print}' doc/*.rec | recsel -t meta -j version
# install vim plugin
install-plugin:
cp -r vim-tbls/* ~/.config/nvim
# install binary
install-binary: compile
cp tbls ~/bin

16
src/filter.fnl 100644
View File

@ -0,0 +1,16 @@
(local {: contains?} (require :src.table))
(local {:split split-full} (require :src.string))
(local split (partial split-full "[^%.]*"))
(fn filter [s]
(let [filters (require :src.flib)
[str & funs] (split s)]
(var res str)
(each [_ f (ipairs funs)]
(each [_ filter (pairs filters)]
(when (contains? filter.call f)
(set res (filter.fun res)))))
res))
{: filter
}

30
src/flib.fnl 100644
View File

@ -0,0 +1,30 @@
(fn capitalize [s]
(s:gsub "." string.upper 1))
(fn uppercase [s]
(string.upper s))
(fn lowercase [s]
(string.lower s))
(fn plural [s]
(.. s :s))
{
:capitalize {
:call [:c :cap :capital :capitalize]
:fun capitalize
}
:uppercase {
:call [:u :upper :uppercase]
:fun uppercase
}
:lowercase {
:call [:l :lower :lowercase]
:fun lowercase
}
:plural {
:call [:s :plural :pluralize]
:fun plural
}
}

View File

@ -40,8 +40,7 @@
(fn main [] (fn main []
(let [opts (parse-args arg) (let [opts (parse-args arg)
corpus (create-corpus opts.input) corpus (create-corpus opts.input)]
]
(if opts.key (if opts.key
(print (flatten corpus (. corpus opts.key))) (print (flatten corpus (. corpus opts.key)))
(print (flatten corpus opts.string))))) (print (flatten corpus opts.string)))))

View File

@ -1,20 +1,8 @@
;; helper funs ;; helper funs
(local tbl { (local tbl (require :src.table))
:contains? (fn contains [t x] (local {: filter} (require :src.filter))
"does sequence t contain element x?" (local {:split _split} (require :src.string))
(accumulate [found false (local split (partial _split "[^%.]*"))
_ v (ipairs t)
&until found] ; escape early
(or found (= x v))))
:keys (fn keys [t]
"takes a table returns a sequential list of its keys"
(local out [])
(each [k v (pairs t)] (table.insert out k))
out)
})
(fn has-key? [t k]
(tbl.contains? (tbl.keys t) k))
(fn lines [filename callback] (fn lines [filename callback]
(case (pcall #(with-open [file (io.open filename)] (each [line (file:lines)] (callback line)))) (case (pcall #(with-open [file (io.open filename)] (each [line (file:lines)] (callback line))))
@ -22,7 +10,7 @@
(fn _create-corpus [lines data] (fn _create-corpus [lines data]
(var current-key nil) (var current-key nil)
(var corpus {}) (local corpus {})
(lines data (lines data
#(let [key (string.match $1 "^::%s+([%a-]+)") #(let [key (string.match $1 "^::%s+([%a-]+)")
blank? (or (= nil $1) (= "" $1)) blank? (or (= nil $1) (= "" $1))
@ -50,7 +38,7 @@
seed (math.randomseed random) ;; SIDE EFFECT seed (math.randomseed random) ;; SIDE EFFECT
whatever (handle:close) ;; SIDE EFFECT whatever (handle:close) ;; SIDE EFFECT
idx (math.random len) idx (math.random len)
keys (accumulate [acc [] k v (pairs t)] (do (table.insert acc k) acc)) keys (accumulate [acc [] k _ (pairs t)] (do (table.insert acc k) acc))
rndkey (. keys idx) rndkey (. keys idx)
] ]
(. t rndkey))) (. t rndkey)))
@ -60,18 +48,22 @@
"string" origin "string" origin
"table" (one-of origin) "table" (one-of origin)
_ (error "Origin must be a table or a string")) _ (error "Origin must be a table or a string"))
template-pattern "%[[%a-]+%]" ; [word] template-pattern "%[[%a-%.]+%]" ; [word]
word-pattern "%[([%a-]+)%]" ; word word-pattern "%[([%a-%.]+)%]" ; word
(i j) (string.find str template-pattern) ; indices (i j) (string.find str template-pattern) ; indices
word (string.match str word-pattern)] ; the actual keyword raw-word (or (string.match str word-pattern) str)
[word & fs] (split raw-word)
]
(if (not i) (if (not i)
str str
(do (do
(assert (has-key? corpus word) (assert (tbl.has-key? corpus word)
(string.format "Error trying to expand \"%s\". Corpus does not contain a table called \"%s\"" str word)) (string.format "Error trying to expand \"%s\". Corpus does not contain a table called \"%s\"" str word))
(let [next-str (string.format "%s%s%s" (let [next-str (string.format "%s%s%s"
(string.sub str 1 (- i 1)) (string.sub str 1 (- i 1))
(one-of (. corpus word)) (if (length fs)
(filter (.. (one-of (. corpus word)) "." (table.concat fs ".")))
(one-of (. corpus word)))
(string.sub str (+ j 1)))] (string.sub str (+ j 1)))]
(flatten corpus next-str j)))))) ;; this is a tail call! (flatten corpus next-str j)))))) ;; this is a tail call!

7
src/string.fnl 100644
View File

@ -0,0 +1,7 @@
(fn split [pattern str]
(let [res []]
(each [seg (str:gmatch pattern)]
(table.insert res seg))
res))
{: split}

20
src/table.fnl 100644
View File

@ -0,0 +1,20 @@
(fn contains? [t x]
"does sequence t contain element x?"
(accumulate [found false
_ v (ipairs t)
&until found] ; escape early
(or found (= x v))))
(fn keys [t]
"takes a table returns a sequential list of its keys"
(local out [])
(each [k _ (pairs t)] (table.insert out k))
out)
(fn has-key? [t k]
(contains? (keys t) k))
{: contains?
: keys
: has-key?
}

View File

@ -2,349 +2,350 @@
:: name :: name
## Entry point / origin ## Entry point / origin
[morpheme][word] [epithet] [morpheme.c][word] [epithet]
[prefix] [morpheme][word] [prefix] [morpheme.c][word]
[prefix] [morpheme][word] [epithet] [prefix] [morpheme.c][word.s]
[morpheme][word]'[morpheme] [prefix] [morpheme.c][word] [epithet]
[morpheme] [morpheme][word] [morpheme.c][word]'[morpheme.c]
[morpheme.c] [morpheme.c][word]
:: morpheme :: morpheme
## A random sound ## A random sound
Brog brog
Guyn guyn
Driz driz
Oy oy
Poin poin
Broin broin
Dray dray
Hoy hoy
Khu khu
Elbb elbb
Zee zee
Teg teg
Thig thig
Volor volor
Moror moror
Zarn zarn
Zark zark
Zarzl zarzl
Zhong zhong
Zok zok
Krinc krinc
Prunc prunc
Seld seld
Serd serd
Quo quo
Quog quog
Wast wast
Writ writ
Wub wub
Eem eem
Eo eo
Ev ev
Wuld wuld
Rond rond
Trop trop
Yhoo yhoo
Urdd urdd
Ing ing
Ogg ogg
Phef phef
Aph aph
Fro fro
Drov drov
Frol frol
Gis gis
Hirn hirn
Wilk wilk
Rof rof
Roch roch
Thip thip
Throg throg
Teng teng
Tirk tirk
Tenk tenk
Twu twu
Twal twal
Yuth yuth
Yirg yirg
Ull ull
Uk uk
Iv iv
Irch irch
Ok ok
Ort ort
Ool ool
Oon oon
Oos oos
Oop oop
Pur pur
Purth purth
Pux pux
Pix pix
Ang ang
Ank ank
Ack ack
Arr arr
Arc arc
Sor sor
Shri shri
Sarc sarc
Sib sib
Spo spo
Snil snil
Dral dral
Dax dax
Druz druz
Droon droon
Tiong tiong
Snid snid
Phra phra
Vang vang
Gawp gawp
Hool hool
Grul grul
Dhoop dhoop
Jair jair
Qim qim
Quisl quisl
Fiaz fiaz
Prax prax
Aal aal
Righ righ
Ugh ugh
Yog yog
Yig yig
Yair yair
Var var
Vaq vaq
Skog skog
Drij drij
Volg volg
Dem dem
Ghil ghil
Uvar uvar
Err err
Azil azil
Obil obil
Zanzil zanzil
Zhat zhat
Blug blug
Blig blig
Hroo hroo
Waf waf
Xar xar
Grar grar
Lorp lorp
Vuh vuh
Ee ee
Ay ay
Oo oo
Ux ux
Ix ix
Whal whal
Mun mun
Ilun ilun
Fargl fargl
Xab xab
Frang frang
Bao bao
Bif bif
Xif xif
Zij zij
Quix quix
Vonch vonch
Van van
Klanc klanc
Lug lug
Nirm nirm
Zirm zirm
Sil sil
Wev wev
Vil vil
Vran vran
Quiv quiv
Squan squan
Squank squank
Squop squop
Akun akun
Apar apar
Epar epar
Iq iq
Exy exy
Eny eny
Ery ery
Uth uth
Ist ist
Ost ost
Hrosh hrosh
Imb imb
Omb omb
Onk onk
Arem arem
Urum urum
Irim irim
Irik irik
Eliv eliv
Wep wep
Wroov wroov
Droov droov
Seef seef
Hiqa hiqa
Ayy ayy
Jaal jaal
Khee khee
Ish ish
Xiliv xiliv
Whij whij
Koj koj
Krong krong
Swue swue
Aur aur
Eth eth
Qeth qeth
Neth neth
Veth veth
Yeth yeth
Aer aer
Aen aen
Ain ain
Aun aun
Uon uon
Xiv xiv
Ung ung
Ong ong
Eng eng
Ehal ehal
Dhar dhar
Dhom dhom
Hom hom
Kom kom
Rom rom
Qom qom
Eez eez
Dhezz dhezz
Elpz elpz
Upz upz
Akz akz
Auz auz
Goaz goaz
Goz goz
Mepz mepz
Tepz tepz
Crunz crunz
Grenz grenz
Purb purb
Ony ony
Igy igy
Eart eart
Ehng ehng
Leng leng
Jub jub
Zhoon zhoon
Zhewt zhewt
Juju juju
Lhop lhop
Lhow lhow
Ewl ewl
Ewil ewil
Avul avul
Ap ap
Ip ip
Ep ep
Eb eb
En en
El el
Ek ek
Eh eh
Ez ez
Es es
Ej ej
Ol ol
Om om
Ob ob
Oc oc
Ot ot
Oz oz
Os os
Oq oq
Mork mork
Morg morg
Borg borg
Franken franken
Pranken pranken
Lankim lankim
Khim khim
Khem khem
Vinken vinken
Inken inken
Swohd swohd
Glup glup
Blubil blubil
Bulbil bulbil
Ziz ziz
Miz miz
Lilip lilip
Soong soong
Yolp yolp
Grang grang
Grunc grunc
Gharn gharn
Bral bral
Criv criv
Durn durn
Flom flom
Griv griv
Harn harn
Jurn jurn
Klom klom
Larn larn
Mird mird
Norl norl
Plen plen
Qarn qarn
Rilk rilk
Skiv skiv
Tarm tarm
Ulm ulm
Vorn vorn
Wim wim
Yorn yorn
Blen blen
Cril cril
Dorn dorn
Frel frel
Glim glim
Jiln jiln
Kren kren
Lom lom
Morn morn
Nix nix
Polm polm
Quen quen
Ralk ralk
Shil shil
Trok trok
Ulk ulk
Vlim vlim
Yiln yiln
Brim brim
Crev crev
Dril dril
Flon flon
Gril gril
Jorn jorn
Kliv kliv
Lorn lorn
Mirk mirk
Norn norn
Plim plim
Qril qril
Rik rik
Skon skon
Trel trel
Ulv ulv
Vril vril
:: word :: word
## A regular old word ## A regular old word
@ -1011,3 +1012,4 @@ Sister
Sour Sour
Pickled Pickled
The Machine known as The Machine known as
# vim:set filetype=tbls:

View File

@ -5,11 +5,11 @@
(let [corpus (create-corpus "test/morpheme-word-epithet.txt") (let [corpus (create-corpus "test/morpheme-word-epithet.txt")
origin-key :name origin-key :name
origin-table ["[morpheme][word] [epithet]" origin-table ["[morpheme.c][word] [epithet]"
"[prefix] [morpheme][word] [epithet]" "[prefix] [morpheme.c][word] [epithet]"
"[prefix] [morpheme][word]" "[prefix] [morpheme.c][word]"
] ]
origin-string "[morpheme][word] [epithet]" origin-string "[morpheme.c][word] [epithet]"
get-story-with-key get-story-with-key
(partial flatten corpus (. corpus origin-key)) (partial flatten corpus (. corpus origin-key))
get-story-with-table get-story-with-table

25
vim-tbls/README.md 100644
View File

@ -0,0 +1,25 @@
# vim-tbls
syntax, filtetype detection, folding, and navigation for tbls files
## installing
1. find out where your `syntax` and `ftdetect` files are. e.g. `$HOME/.config/nvim/` or `$HOME/.vim/`.
2. copy `syntax/tbls.vim` and `ftdetect/tbls.vim` to the appropriate folders
after installing, any `.tbl` file should be detected.
to use syntax for, e.g. a `.txt` file, in vim do `:set filetype=tbls`
## using
the syntax defines a foldable table block as the region between a `:: header` and a blank line.
all folding commands should work.
(e.g. `zj` and `zk` to jump to next fold. see `:help fold`.)
the plugin file sets the foldmethod to syntax,
so your tables should start out folded if folding in enabled.
the plugin file also maps `]]` and `[[`
(next section and previous section, respectively)
to jump between table headers.

View File

@ -0,0 +1 @@
au BufRead,BufNewFile *.tbl set filetype=tbls

View File

@ -0,0 +1,3 @@
setlocal foldmethod=syntax
nnoremap <silent><buffer> ]] m':call search('^::', "W")<CR>
nnoremap <silent><buffer> [[ m':call search('^::', "bW")<CR>

View File

@ -0,0 +1,15 @@
if exists("b:current_syntax")
finish
endif
syntax match tblsComment "^#.*$"
syntax match tblsTitle "^:\+ .*$"
syntax match tblsRef "\[[^\]]*\]"
syntax region tblsTable start=":: .*" end="^$" fold transparent
highlight default link tblsComment Comment
highlight default link tblsTitle Statement
highlight default link tblsRef Type
let b:current_syntax = "tbls"