123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 |
- --[[
- Copyright (c) 2021 <roberto.vpt@protonmail.com> . All rights reserved.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ]]--
- --[[
- **2021-11-26 Roberto Soccoli
- # RENDER GEMLINE ver 1
- Dopo una mia proposta iniziale, che non era allineata con gli usi della
- comunità Gemini che principalmento usano interfacce testuali, ho cercato di
- implementare le mie idee assecondando l'uso comune.
- Il corretto uso dei tag è devoluto allo scrivente.
- > Questa versione è predisposta per essere usata nel client DEMO di
- > solderpunk senza sostanziali modifiche.
- ## I TAG DI EVIDENZIAZIONE BOLD E ITALIC
- * I tag sono * per *BOLD* e " per "ITALIC".
- * I tag sono riconosciuti solo a inizio o fine parola, ** altrimenti sono testo.
- * I tag isolati *sono mostrati*.
- * Se ci sono entrambi "*bold non viene mostrato*".
- * I tag raddoppiati, ""**non sono mostrati**"".
- ## VALORI TAG
- 0 SPAZIO
- 1 BOLD mostrato *
- 2 ITALIC mostrato "
- 3 entrambi, mostrato solo "
- 4 NULL
- 5 bold nascosto
- 6 italic nascosto
- 7 entrambi nascosti
- 2021-11-29
- Il formattare in un testo da scrivere direttamente su terminale non permette una buona paginazione.
- Gemline è meglio che torni la tabella rows ed il livello superiore farà quanto deve.
- Peraltro la paginazione deve essere semplice, con testo abbastanza corto e le linee complete.
- Le pagine vanno calcolate sul numero di righe sommate per linea.
- ]]--
- -- danno fastidio se li metto anche qui??
- preformatted = false
- links = {}
- socket = require("socket")
- socket.url = require("socket.url")
- function render ( line, margin )
- -- A CAPO GIUSTIFICATO, BOLD E ITALIC
- margin = margin or 74 -- 2/3=51, 1/2=38 e 1/3=27
- -- indentazione a 4 caratteri per supportare più di 9 link
- -- per =>_ che diventa _1>_ o 10>_
- local isIndent = false
- local indent = " "
- local start = 1
- local len = 0
- local tags = true -- not for #, ## and ###
- local title = false -- onli #
- local words = {} -- first step
- local rows = {} -- line rows
- local row = {}
- local url
-
- function skip()
- if line and start < #line then
- while string.byte( line, start ) < 33 do
- if start == #line then break end
- start = start + 1
- end
- end
- end
-
- function toWords ( text )
- text = text or ""
- local p = 1
- while p <= #text do
- local i, f = string.find( text, "%s+", p )
- if i then
- if i > p then
- local temp = string.sub( text, p, i - 1 )
- if #temp == 1 and string.find( temp, "^%p+" ) then
- words[#words+1] = 4
- end
- words[#words+1] = temp
- end
- words[#words+1] = 0
- p = f + 1
- else
- local temp = string.sub( text, p )
- if #temp == 1 and string.find( temp, "^%p+" ) then
- words[#words+1] = 4
- end
- words[#words+1] = temp
- break
- end
- end
- end
-
- function switch ( pos )
- if pos == 1 or words[pos-1] == 0 then -- apertura
- if (words[pos] & 2) == 2 then
- if words[pos] < 4 then row[#row+1] = '“' end
- row[#row+1] = "\27[3m"
- end
- if (words[pos] & 1) == 1 then
- row[#row+1] = "\27[1m"
- if words[pos] == 1 then row[#row+1] = '*' end
- end
- else
- if (words[pos] & 1) == 1 then
- if words[pos] == 1 then row[#row+1] = '*' end
- row[#row+1] = "\27[22m"
- end
- if (words[pos] & 2) == 2 then
- row[#row+1] = "\27[23m"
- if words[pos] < 4 then row[#row+1] = '”' end
- end
- end
- end
- -- MAIN
- if line and #line > 0 then
- if string.sub(line,1,3) == "```" then
- preformatted = not preformatted
- elseif preformatted then
- return line .. "\n"
- elseif string.sub( line, 1, 1 ) == ">" then
- indent = " ┃ "
- row[#row+1] = indent
- start = 2
- elseif string.sub( line, 1, 2 ) == "=>" then
- start = 3
- while string.byte( line, start ) < 33 do start = start + 1 end
- local i, f = string.find( line, "%s+", start )
- local link
- if i then
- link = string.sub( line, start, i - 1 )
- start = f + 1
- else
- link = string.sub( line, start )
- end
- table.insert(links, socket.url.absolute(url, link))
- local temp = string.sub( " "..#links, -2 )
- row[#row+1] = "\27[34m"..temp..">\27[39m "
- elseif string.sub( line, 1, 2 ) == "* " then
- row[#row+1] = " \27[1m•\27[m "
- start = 3
- elseif string.sub( line, 1, 1 ) == "#" then
- indent = ""
- tags = false
- if string.sub( line, 1, 3 ) == "###" then
- row[#row+1] = "\27[1m\27[4m"
- start = 4
- elseif string.sub( line, 1, 2 ) == "##" then
- row[#row+1] ="\27[1m\27[21m"
- start = 3
- elseif string.sub( line, 1, 1 ) == "#" then
- indent = " "
- row[#row+1] = indent.."\27[1m"
- title = true
- start = 2
- end
- else
- indent = ""
- end
- -- LINE INIT
- if start > 1 then
- skip()
- else
- skip()
- if start > 1 then
- indent = " "
- row[#row+1] = indent
- end
- end
- if #indent > 0 then
- isIndent = true
- len = 4
- end
- -- TEXT LOAD
- -- first round: line to words, spaces and text tags
- while start <= #line do
- local pos
- if tags then
- pos, f = string.find( line, '["%*]+', start )
- end
- if pos then
- if pos > start then
- toWords( string.sub( line, start, pos - 1 ) )
- end
- words[#words+1] = string.sub( line, pos, f )
- start = f + 1
- else
- toWords( string.sub( line, start ) )
- break
- end
- end
- -- second round: find and compile text tags
- for n = 1, #words do
- if type( words[n] ) == "string" then
- local tag = string.sub( words[n], 1, 1 )
- if ( tag == '*' or tag == '"' ) and
- -- una tag è circondato almeno da uno spazio
- (
- n == 1 or n == #words or
- type( words[n-1] ) ~= type( words[n+1] )
- )
- then
- local temp = words[n]
- --print( temp )
- local code = 0
- for t = 1, #temp do
- tag = string.sub( temp, t, t )
- if tag == '*' then
- if ( code & 1 ) == 1 then -- bold
- code = ( code & 3 ) + 4 -- nascosto
- else
- code = ( code & 6 ) + 1 -- set bold
- end
- elseif tag == '"' then
- if ( code & 2 ) == 2 then -- italic
- code = ( code & 3 ) + 4 -- nascosto
- else
- code = ( code & 5 ) + 2 -- set italic
- end
- end
- end -- for
- words[n] = code
- end
- end -- solo stringhe, salta gli spazi
- end -- end for
- -- ROW FORMAT
- local head = 1
- local tail = 1
- local spaces = 0
- for n = 1, #words do
- if type( words[ n ] ) == "string" then
- if len + #words[n] > margin then
- local riporto = words[n]
- local rip = #riporto
- pos = n+1 -- salva posizione successiva
- local trat = string.find( riporto, '-', 1, true )
- if trat and trat <= margin - len then
- -- divide la parola al trattino
- riporto = string.sub( words[n], trat + 1 )
- rip = #riporto
- words[n] = string.sub( words[n], 1, trat )
- len = len + trat
- tail = n
- else
- -- riporto a capo
- tail = n - 1
- -- elimina fino a spazio finale
- if words[tail] ~= 0 then -- sono tags
- if words[tail] & 1 == 1 then
- riporto = "\27[1m"..riporto
- end
- if words[tail] < 4 then
- len = len - 1
- rip = rip + 1
- if words[tail] == 1 then
- riporto = "*"..riporto
- end
- end
- if words[tail] & 2 == 2 then
- riporto = "\27[3m"..riporto
- if words[tail] < 4 then
- riporto = "“"..riporto
- end
- end
- tail = tail - 1
- end
- -- lo spazio viene saltato
- spaces = spaces - 1
- len = len - 1
- tail = tail - 1
- end
- -- giustifica la riga
- local a = margin - len
- local t = a + spaces
- local x = t / spaces
- local s = 0
- for m = head, tail do
- if type( words[m] ) == "string" then
- row[#row+1] = words[m]
- else
- if words[m] == 0 then
- spaces = spaces - 1
- s = s + x
- local temp = math.floor( s + 0.5 )
- t=t-temp
- if spaces == 1 then temp = t end
- row[#row+1] = string.rep( " ", temp )
- s = s - temp
- else
- switch ( m )
- end
- end
- end
- -- si va a capo
- row[#row+1] = "\n" -- CHIUSURA
- rows[#rows+1] = table.concat( row )
- -- nuova row
- row = {}
- row[1] = indent..riporto
- riporto = ""
- len = rip
- if isIndent then len = len + 4 end
- spaces = 0
- -- PRONTI AD AVANZARE
- head = pos -- OK
- else
- len = len + #words[n]
- end
- else -- SPACE AND TAGS
- if words[n] < 4 then len = len + 1 end
- if words[n] == 0 then spaces = spaces + 1 end
- end
- end -- fine scansione
- -- parte non giustificata
- for m = head, #words do
- if type( words[m] ) == "string" then
- row[#row+1] = words[m]
- else
- if words[m] == 0 then
- row[#row+1] = " "
- else
- switch( m )
- end
- end
- end
- row = table.concat( row ) -- compreso margine
- if title then -- centrato
- local s = math.tointeger( math.floor(( margin - #row + 0.5 ) / 2 ) )
- row = string.rep( " ", s )..row
- end
- rows[#rows+1] = row
- -- CHIUSURA ULTIMA RIGA
- rows[#rows+1] = "\27[m\n"
- else
- rows[#rows+1] = "\n"
- end
- return rows
- end
- return render
-
-
|