mirror of
https://github.com/makew0rld/amfora.git
synced 2024-12-04 14:46:29 -05:00
ANSI and plain renderers done but untested, gemtext started
This commit is contained in:
parent
8f216f569b
commit
d2d5846b0e
71
render/gemtext.go
Normal file
71
render/gemtext.go
Normal file
@ -0,0 +1,71 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Renderer for gemtext. Other Renderers are in renderer.go.
|
||||
|
||||
type GemtextRenderer struct {
|
||||
r *io.PipeReader
|
||||
w *io.PipeWriter
|
||||
|
||||
// scanner is used to process line by line.
|
||||
scanner *bufio.Scanner
|
||||
|
||||
// scanWriter is used to send data to the scanner, which reads out of the other
|
||||
// end of the pipe.
|
||||
scanWriter *io.PipeWriter
|
||||
|
||||
// lineEnd holds the rest of line when the Read call cuts off the line being returned.
|
||||
lineEnd []byte
|
||||
|
||||
links chan string
|
||||
|
||||
// numLinks is the number of links that exist so far.
|
||||
numLinks int
|
||||
// width is the number of columns to wrap to.
|
||||
width int
|
||||
// proxied is whether the request is through the gemini:// scheme.
|
||||
proxied bool
|
||||
|
||||
// pre indicates whether the renderer is currently in a preformatted block
|
||||
// or not.
|
||||
pre bool
|
||||
}
|
||||
|
||||
// NewGemtextRenderer.
|
||||
//
|
||||
// width is the number of columns to wrap to.
|
||||
//
|
||||
// proxied is whether the request is through the gemini:// scheme.
|
||||
// If it's not a gemini:// page, set this to true.
|
||||
func NewGemtextRenderer(width int, proxied bool) *GemtextRenderer {
|
||||
pr, pw := io.Pipe()
|
||||
scanReader, scanWriter := io.Pipe()
|
||||
scanner := bufio.NewScanner(scanReader)
|
||||
links := make(chan string, 10)
|
||||
|
||||
return &GemtextRenderer{
|
||||
r: pr,
|
||||
w: pw,
|
||||
scanner: scanner,
|
||||
scanWriter: scanWriter,
|
||||
lineEnd: make([]byte, 0),
|
||||
links: links,
|
||||
numLinks: 0,
|
||||
width: width,
|
||||
proxied: proxied,
|
||||
pre: false,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *GemtextRenderer) Links() <-chan string {
|
||||
return r.links
|
||||
}
|
||||
|
||||
func (r *GemtextRenderer) Write(p []byte) (n int, err error) {
|
||||
// Just write to the scanner, all logic is in Read()
|
||||
return r.scanWriter.Write(p)
|
||||
}
|
@ -41,7 +41,7 @@ func RenderPlainText(s string) string {
|
||||
// It used to add a left margin, now this is done elsewhere.
|
||||
// The function is kept for convenience and in case rendering
|
||||
// is needed in the future.
|
||||
return s
|
||||
return cview.Escape(s)
|
||||
}
|
||||
|
||||
// wrapLine wraps a line to the provided width, and adds the provided prefix and suffix to each wrapped line.
|
||||
@ -270,7 +270,6 @@ func convertRegularGemini(s string, numLinks, width int, proxied bool) (string,
|
||||
// It also returns a slice of link URLs.
|
||||
//
|
||||
// width is the number of columns to wrap to.
|
||||
// leftMargin is the number of blank spaces to prepend to each line.
|
||||
//
|
||||
// proxied is whether the request is through the gemini:// scheme.
|
||||
// If it's not a gemini:// page, set this to true.
|
||||
|
91
render/renderer.go
Normal file
91
render/renderer.go
Normal file
@ -0,0 +1,91 @@
|
||||
package render
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/makeworld-the-better-one/amfora/config"
|
||||
"github.com/spf13/viper"
|
||||
"gitlab.com/tslocum/cview"
|
||||
)
|
||||
|
||||
// Renderer renderers network bytes into something that can be displayed on a
|
||||
// cview.TextView.
|
||||
type Renderer interface {
|
||||
io.ReadWriter
|
||||
|
||||
// Links returns a channel that yields Link URLs as they are parsed.
|
||||
// It is buffered. The channel might be closed to indicate links are supported
|
||||
// for this renderer.
|
||||
Links() <-chan string
|
||||
}
|
||||
|
||||
type PlaintextRenderer struct {
|
||||
*io.PipeReader
|
||||
w *io.PipeWriter
|
||||
}
|
||||
|
||||
func NewPlaintextRenderer() *PlaintextRenderer {
|
||||
pr, pw := io.Pipe()
|
||||
return &PlaintextRenderer{pr, pw}
|
||||
}
|
||||
|
||||
func (r *PlaintextRenderer) Write(p []byte) (n int, err error) {
|
||||
// TODO: The escaping will fail if the Write bytes end in the middle of a tag
|
||||
// How can this be avoided by users of this func?
|
||||
return r.w.Write(cview.EscapeBytes(p))
|
||||
}
|
||||
|
||||
func (r *PlaintextRenderer) Links() <-chan string {
|
||||
ch := make(chan string)
|
||||
close(ch)
|
||||
return ch
|
||||
}
|
||||
|
||||
type ANSIRenderer struct {
|
||||
*io.PipeReader
|
||||
pw *io.PipeWriter
|
||||
ansiWriter io.Writer // cview.ANSIWriter
|
||||
buf bytes.Buffer
|
||||
}
|
||||
|
||||
func NewANSIRenderer() *ANSIRenderer {
|
||||
pr, pw := io.Pipe()
|
||||
|
||||
var ansiWriter io.Writer = nil // When ANSI is disabled
|
||||
var buf bytes.Buffer
|
||||
|
||||
if viper.GetBool("a-general.color") && viper.GetBool("a-general.ansi") {
|
||||
// ANSI enabled
|
||||
ansiWriter = cview.ANSIWriter(&buf)
|
||||
}
|
||||
return &ANSIRenderer{pr, pw, ansiWriter, buf}
|
||||
}
|
||||
|
||||
func (r *ANSIRenderer) Write(p []byte) (n int, err error) {
|
||||
if r.ansiWriter == nil {
|
||||
// ANSI disabled
|
||||
return r.pw.Write(ansiRegex.ReplaceAll(p, []byte{}))
|
||||
}
|
||||
// ANSI enabled
|
||||
|
||||
r.buf.Reset()
|
||||
r.ansiWriter.Write(p) // Shouldn't error because everything it writes to are all bytes.Buffer
|
||||
return r.pw.Write(
|
||||
// The ANSIWriter injects tags like [-:-:-]
|
||||
// but this will reset the background to use the user's terminal color.
|
||||
// These tags need to be replaced with resets that use the theme color.
|
||||
bytes.ReplaceAll(
|
||||
r.buf.Bytes(),
|
||||
[]byte("[-:-:-]"),
|
||||
[]byte(fmt.Sprintf("[-:%s:-]", config.GetColorString("bg"))),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (r *ANSIRenderer) Links() <-chan string {
|
||||
ch := make(chan string)
|
||||
close(ch)
|
||||
return ch
|
||||
}
|
Loading…
Reference in New Issue
Block a user