bla: no pictures, no colours, just text - and tricky
For the August meeting I needed a presentation tool. So I made one.
I used to make truly baroque power point presentations, but now I needed just one line of text at a time to prevent people reading ahead and losing focus. Also, it is a lot less tinkering with layout, colours, pictures and more focus on how to get the subject at hand across.
The tricky part is non-standard use of the forth dictionary and strings. But it works, with gforth 0.7.3. And it is an example of self-modifying code, or more fancy metaprogramming. Or even more fancy, reflection. Reflection with forth, high level. That's nice, innit? 87 lines of code.
File bla.fth:
\ bla presentation tool -- 2024-07 -- wj -- tested with gforth 0.7.3
\ screen cursor
: csi 27 emit [char] [ emit ; \ csi = Control Sequence Introducer
: hide-cursor csi ." ?25l" ;
: show-cursor csi ." ?25h" ;
\ screen size
: width ( -- n ) form swap drop ;
: height ( -- n ) form drop ;
\ lines needed for a text
: #lines ( u.len -- u.lines ) width / 1+ ; \ Note: rough estimate, which is sufficient for this purpose
\ print centered
: to-startheight ( u.len -- ) >r 0 height 2 / r> #lines 2 / - at-xy ;
: break ( cadr u -- cadr u') \ if there is a space near the end adjust u to it so we get a nice looking text
2dup 2dup >r 1- + r> 1- 20 min 0
?do dup c@ BL = if swap - swap drop unloop exit else 1- then loop 2drop ;
: fill ( u -- u ) dup width - abs 2 / spaces ;
: type-part ( cadr u - cadr' u' ) \ type what fits on the line and update string address and length
dup width < if 2dup fill type dup - exit then \ everything fits on one line, make sure 'u' becomes 0
over width break fill dup >r type cr r@ - swap r> + swap ; \ too long, type the part that fits on the line
create line# 0 , \ currently displayed line from the input file
: bla. ( cadr u -- ) page line# @ . dup to-startheight begin type-part dup 0= until 2drop ;
\ read the text file and store every line in words bla000-bla999
create bla# 0 , \ reading lines from file
: bla#+ bla# @ 1+ 999 min bla# ! ; \ limit at 999 lines
\ warning: modifying text in dictionary, make sure your forth language supports this
: >store ( cadr u -- ) s" create blaxxx 0 , dup allot align dup blaxxx ! blaxxx cell+ swap cmove" evaluate ;
: get> ( -- cadr u ) s" blaxxx cell+ blaxxx @" evaluate ;
\ find in >store and get> all substrings xxx and remember the addresses
\ - the assumption is these addresses will remain constant during the session
create digitadresses 0 , 0 , 0 , 0 , 0 , \ first 3 for >store, the rest for get>
: getxxx-adresses ( -- )
['] >store >body 80 \ limit length to location of xxx substrings -- portability warning
s" xxx" search if over digitadresses ! 3 - swap 3 + swap then
s" xxx" search if over digitadresses cell+ ! 3 - swap 3 + swap then
s" xxx" search if over digitadresses 2 cells + ! then
2drop
['] get> >body 40 \ limit length to location of xxx substrings -- portability warning
s" xxx" search if over digitadresses 3 cells + ! 3 - swap 3 + swap then
s" xxx" search if over digitadresses 4 cells + ! then
2drop ;
\ replace xxx locations by formatted 3 digit bla# e.g "001" using:
: set ( u -- )
0 <# # # # #> \ make string 3 digits
5 0 do 2dup digitadresses i cells + @ swap cmove loop 2drop ;
create fid 0 ,
create buf 1000 allot
align
: bla ( -- )
cr cr ." n|p|q" 500 ms \ on screen reminder of available commands
bla# @ 0= if
s" presentation" r/o open-file throw fid !
getxxx-adresses
begin
buf 1000 fid @ read-line throw
while buf swap bla# @ set >store bla#+
repeat
then
0 line# !
hide-cursor
begin
line# @ set get> bla.
key dup dup [char] q = if show-cursor exit then
[char] n = if line# @ 1+ bla# @ 1- min line# ! then
[char] p = if line# @ 1- 0 max line# ! then
again ;
\ page ." bla presentation tool -- wj 2024" cr width . 1000 ms
\ : tests-break
\ s" 12345678901234567890123" break ~~ 2drop ." 23 expected" cr
\ s" 1234567890123456789012 " break ~~ 2drop ." 22 expected" cr
\ s" 1234 678901234567890123" break ~~ 2drop ." 4 expected" cr
\ s" 1 345678901234567890123" break ~~ 2drop ." 23 expected" cr
\ s" 1 34567890" break ~~ 2drop ." 1 expected" cr
\ s" 234567890" break ~~ 2drop ." 10 expected" cr
\ ;
\ tests-break bye
\ : tests-fill
\ 42 emit width fill 42 emit . cr
\ 42 emit width 2 - fill 42 emit . cr
\ 42 emit 0 fill 42 emit . cr
\ ;
\ tests-fill bye
bla cr bye
Oh, and here is the README presentation file:
File presentation:
README for bla.fth 2024-08-12, wj
About:
bla is a no-nonsense text-ony presentation program
the file 'presentation' is a plain text file containing the presentation
the file 'bla.fth' is a Forth program
Start:
Start bla by typing "gforth bla.fth" on the commandline (tested with gforth 0.7.3 on aarch64)
Use:
bla reads the presentation file and displays a short instruction: "n|p|q" for about half a second as a reminder
... then, the first line of the presentation is shown
In order to:
go to the next page: n key
go to the previous page: p key
quit the program: q key
Solve problems:
Characters too small to read: zoom in on your terminal
My terminal program does not have zoom capability: lower your screen resolution or install a different terminal program
I do not have gforth: download it or try another forth
I want to see a different presentation: copy your text only presentation to a file named 'presentation' in the same place as the bla.fth (you may want to save the current presentation file first) and start bla by typing "gforth bla.fth" on the commandline
Good luck!