mirror of
https://github.com/makew0rld/amfora.git
synced 2024-09-27 23:05:55 -04:00
parent
36c2206785
commit
6a708d339d
@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
### Added
|
||||||
|
- Link and heading lines are wrapped just like regular text lines
|
||||||
|
- Wrapped list items are indented to stay behind the bullet (#35)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Pages are rewrapped dynamically, whenever the terminal size changes (#33)
|
- Pages are rewrapped dynamically, whenever the terminal size changes (#33)
|
||||||
|
|
||||||
|
@ -13,6 +13,38 @@ import (
|
|||||||
"gitlab.com/tslocum/cview"
|
"gitlab.com/tslocum/cview"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// wrapLine wraps a line to the provided width, and adds the provided prefix and suffix to each wrapped line.
|
||||||
|
// It recovers from wrapping panics and should never cause a panic.
|
||||||
|
// It returns a slice of lines, without newlines at the end.
|
||||||
|
//
|
||||||
|
// Set includeFirst to true if the prefix and suffix should be applied to the first wrapped line as well
|
||||||
|
func wrapLine(line string, width int, prefix, suffix string, includeFirst bool) []string {
|
||||||
|
// Anonymous function to allow recovery from potential WordWrap panic
|
||||||
|
var ret []string
|
||||||
|
func() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
// Use unwrapped line instead
|
||||||
|
if includeFirst {
|
||||||
|
ret = []string{prefix + line + suffix}
|
||||||
|
} else {
|
||||||
|
ret = []string{line}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
wrapped := cview.WordWrap(line, width)
|
||||||
|
for i := range wrapped {
|
||||||
|
if !includeFirst && i == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wrapped[i] = prefix + wrapped[i] + suffix
|
||||||
|
}
|
||||||
|
ret = wrapped
|
||||||
|
}()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// convertRegularGemini converts non-preformatted blocks of text/gemini
|
// convertRegularGemini converts non-preformatted blocks of text/gemini
|
||||||
// into a cview-compatible format.
|
// into a cview-compatible format.
|
||||||
// It also returns a slice of link URLs.
|
// It also returns a slice of link URLs.
|
||||||
@ -33,25 +65,15 @@ func convertRegularGemini(s string, numLinks, width int) (string, []string) {
|
|||||||
// Headings
|
// Headings
|
||||||
if viper.GetBool("a-general.color") {
|
if viper.GetBool("a-general.color") {
|
||||||
if strings.HasPrefix(lines[i], "###") {
|
if strings.HasPrefix(lines[i], "###") {
|
||||||
lines[i] = "[fuchsia::b]" + lines[i] + "[-::-]"
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "[fuchsia::b]", "[-::-]", true)...)
|
||||||
}
|
} else if strings.HasPrefix(lines[i], "##") {
|
||||||
if strings.HasPrefix(lines[i], "##") {
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "[lime::b]", "[-::-]", true)...)
|
||||||
lines[i] = "[lime::b]" + lines[i] + "[-::-]"
|
} else if strings.HasPrefix(lines[i], "#") {
|
||||||
}
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "[red::b]", "[-::-]", true)...)
|
||||||
if strings.HasPrefix(lines[i], "#") {
|
|
||||||
lines[i] = "[red::b]" + lines[i] + "[-::-]"
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Just bold, no colors
|
// Just bold, no colors
|
||||||
if strings.HasPrefix(lines[i], "###") {
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "[::b]", "[-::-]", true)...)
|
||||||
lines[i] = "[::b]" + lines[i] + "[::-]"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(lines[i], "##") {
|
|
||||||
lines[i] = "[::b]" + lines[i] + "[::-]"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(lines[i], "#") {
|
|
||||||
lines[i] = "[::b]" + lines[i] + "[::-]"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
@ -82,78 +104,67 @@ func convertRegularGemini(s string, numLinks, width int) (string, []string) {
|
|||||||
|
|
||||||
links = append(links, url)
|
links = append(links, url)
|
||||||
|
|
||||||
|
// Wrap and add link text
|
||||||
|
|
||||||
|
// Wrap the link text, but add some spaces to indent the wrapped lines past the link number
|
||||||
|
wrappedLink := wrapLine(linkText, width,
|
||||||
|
strings.Repeat(" ", len(strconv.Itoa(numLinks+len(links)))+4), // +4 for spaces and brackets
|
||||||
|
"",
|
||||||
|
false, // Don't indent the first line, it's the one with link number
|
||||||
|
)
|
||||||
|
|
||||||
|
// Set the style tags
|
||||||
|
// Add them to the first line
|
||||||
|
|
||||||
if viper.GetBool("a-general.color") {
|
if viper.GetBool("a-general.color") {
|
||||||
pU, err := urlPkg.Parse(url)
|
pU, err := urlPkg.Parse(url)
|
||||||
if err == nil && (pU.Scheme == "" || pU.Scheme == "gemini" || pU.Scheme == "about") {
|
if err == nil && (pU.Scheme == "" || pU.Scheme == "gemini" || pU.Scheme == "about") {
|
||||||
// A gemini link
|
// A gemini link
|
||||||
// Add the link text in blue (in a region), and a gray link number to the left of it
|
// Add the link text in blue (in a region), and a gray link number to the left of it
|
||||||
lines[i] = `[silver::b][` + strconv.Itoa(numLinks+len(links)) + "[]" + "[-::-] " +
|
wrappedLink[0] = `[silver::b][` + strconv.Itoa(numLinks+len(links)) + "[]" + "[-::-] " +
|
||||||
`[dodgerblue]["` + strconv.Itoa(numLinks+len(links)-1) + `"]` + linkText + `[""][-]`
|
`[dodgerblue]["` + strconv.Itoa(numLinks+len(links)-1) + `"]` +
|
||||||
|
wrappedLink[0]
|
||||||
} else {
|
} else {
|
||||||
// Not a gemini link, use purple instead
|
// Not a gemini link, use purple instead
|
||||||
lines[i] = `[silver::b][` + strconv.Itoa(numLinks+len(links)) + "[]" + "[-::-] " +
|
wrappedLink[0] = `[silver::b][` + strconv.Itoa(numLinks+len(links)) + "[]" + "[-::-] " +
|
||||||
`[#8700d7]["` + strconv.Itoa(numLinks+len(links)-1) + `"]` + linkText + `[""][-]`
|
`[#8700d7]["` + strconv.Itoa(numLinks+len(links)-1) + `"]` +
|
||||||
|
wrappedLink[0]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No colours allowed
|
// No colours allowed
|
||||||
lines[i] = `[::b][` + strconv.Itoa(numLinks+len(links)) + "[][::-] " +
|
wrappedLink[0] = `[::b][` + strconv.Itoa(numLinks+len(links)) + "[][::-] " +
|
||||||
`["` + strconv.Itoa(numLinks+len(links)-1) + `"]` + linkText + `[""]`
|
`["` + strconv.Itoa(numLinks+len(links)-1) + `"]` +
|
||||||
|
wrappedLink[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wrappedLink[len(wrappedLink)-1] += `[""][-]` // Close region and formatting at the end
|
||||||
|
|
||||||
|
wrappedLines = append(wrappedLines, wrappedLink...)
|
||||||
|
|
||||||
// Lists
|
// Lists
|
||||||
} else if strings.HasPrefix(lines[i], "* ") {
|
} else if strings.HasPrefix(lines[i], "* ") {
|
||||||
if viper.GetBool("a-general.bullets") {
|
if viper.GetBool("a-general.bullets") {
|
||||||
lines[i] = " \u2022" + lines[i][1:]
|
// Wrap list item, and indent wrapped lines past the bullet
|
||||||
|
wrappedItem := wrapLine(lines[i][1:], width, " ", "", false)
|
||||||
|
// Add bullet
|
||||||
|
wrappedItem[0] = " \u2022" + wrappedItem[0]
|
||||||
|
wrappedLines = append(wrappedLines, wrappedItem...)
|
||||||
}
|
}
|
||||||
// Optionally list lines could be colored here too, if color is enabled
|
// Optionally list lines could be colored here too, if color is enabled
|
||||||
}
|
|
||||||
|
|
||||||
// Final processing of each line: wrapping
|
|
||||||
|
|
||||||
if strings.TrimSpace(lines[i]) == "" {
|
|
||||||
// Just add empty line without processing
|
|
||||||
wrappedLines = append(wrappedLines, "")
|
|
||||||
} else {
|
|
||||||
if (strings.HasPrefix(lines[i], "[silver::b]") && viper.GetBool("a-general.color")) || strings.HasPrefix(lines[i], "[::b]") {
|
|
||||||
// It's a link line, so don't wrap it
|
|
||||||
wrappedLines = append(wrappedLines, lines[i])
|
|
||||||
} else if strings.HasPrefix(lines[i], ">") {
|
} else if strings.HasPrefix(lines[i], ">") {
|
||||||
// It's a quote line, add extra quote symbols to the start of each wrapped line
|
// It's a quote line, add extra quote symbols and italics to the start of each wrapped line
|
||||||
|
|
||||||
// Remove beginning quote and maybe space
|
// Remove beginning quote and maybe space
|
||||||
lines[i] = strings.TrimPrefix(lines[i], ">")
|
lines[i] = strings.TrimPrefix(lines[i], ">")
|
||||||
lines[i] = strings.TrimPrefix(lines[i], " ")
|
lines[i] = strings.TrimPrefix(lines[i], " ")
|
||||||
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "> [::i]", "[::-]", true)...)
|
||||||
|
|
||||||
// Text is also made italic, lower down in code
|
} else if strings.TrimSpace(lines[i]) == "" {
|
||||||
|
// Just add empty line without processing
|
||||||
// Anonymous function to allow recovery from potential WordWrap panic
|
wrappedLines = append(wrappedLines, "")
|
||||||
func() {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
// Add unwrapped line instead
|
|
||||||
wrappedLines = append(wrappedLines, "> [::i]"+lines[i]+"[::-]")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
temp := cview.WordWrap(lines[i], width)
|
|
||||||
for i := range temp {
|
|
||||||
temp[i] = "> [::i]" + temp[i] + "[::-]"
|
|
||||||
}
|
|
||||||
wrappedLines = append(wrappedLines, temp...)
|
|
||||||
}()
|
|
||||||
} else {
|
} else {
|
||||||
// Anonymous function to allow recovery from potential WordWrap panic
|
// Regular line, just wrap it
|
||||||
func() {
|
wrappedLines = append(wrappedLines, wrapLine(lines[i], width, "", "", true)...)
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
// Add unwrapped line instead
|
|
||||||
wrappedLines = append(wrappedLines, lines[i])
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
wrappedLines = append(wrappedLines, cview.WordWrap(lines[i], width)...)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user