ref: 78ac6a671de03d1101955f2f3b390bfae7fc4673
parent: 58a0909ef0e68e01874fad0e4fb01fbe6c47a2d6
author: penny <penny@limitedideas.org>
date: Mon Sep 8 20:19:44 EDT 2025
Modal multi line mode
--- a/hellclient.go
+++ b/hellclient.go
@@ -7,6 +7,7 @@
"strings"
"sync"
"time"
+ "os"
"github.com/ergochat/readline"
"github.com/mattn/go-mastodon"
@@ -25,19 +26,20 @@
type Hellclient struct {//if you're gonna touch or read anything here lock the mutex with hc.lock()
- isPaused bool
- rl *readline.Instance
- client *mastodon.Client
- currentuser *mastodon.Account
- dispatch chan *mastodon.Toot
- block sync.Mutex
- recentpost *mastodon.Status
- preferences *Hellprefs
+ isPaused bool
+ rl *readline.Instance
+ client *mastodon.Client
+ currentuser *mastodon.Account
+ dispatch chan *mastodon.Toot
+ block sync.Mutex
+ recentpost *mastodon.Status
+ preferences *Hellprefs
+ multiLineMode bool
//Global status map for status indexes
//Needs to be converted to a postref struct
homeMap map[string]*mastodon.Status
- homeref *postref
+ homeref *postref
//Contextual indexes for commands
ctxref *postref
urlMap map[string][]string
@@ -49,12 +51,59 @@
apidelay time.Duration
}
+//Use this to make private versions of runes to stop default behavior
+func toPUA(r rune) rune {+ const (
+ puaStart = 0xE000
+ puaEnd = 0xF8FF
+ puaSize = puaEnd - puaStart + 1
+ )
+ return rune(int32(puaStart) + (int32(r) % int32(puaSize)))
+}
+
func NewHellclient() (*Hellclient, error) {- rl, err := readline.New("Hell> ")- rl.CaptureExitSignal()
+ var hc Hellclient
+ config := &readline.Config{+ Prompt: "Hell> ",
+ FuncFilterInputRune: func(r rune) (rune, bool) {+ if r == readline.CharCtrlJ { // ctrl-j+ hc.multiLineMode = !hc.multiLineMode
+ hc.updatePrompt()
+ return r, false
+ }
+ if r == readline.CharKill {+ return toPUA(r), true
+ }
+ if r == readline.CharEnter && hc.multiLineMode {+ return toPUA(r), true
+ }
+ return r, true
+ },
+ Listener: func(line []rune, pos int, key rune) ([]rune, int, bool) {+ if key == toPUA(readline.CharEnter) && hc.multiLineMode {+ // handle multi-line input
+ line = line[:len(line) - 1]
+ line = append(line, '\n')
+ return line, pos, true
+ }
+
+ //If we get an interupt just clear the line if it's not empty
+ if key == toPUA(readline.CharKill) {+ if len(line) > 1 {+ return nil, 0, true
+ }
+ os.Exit(0)
+ return []rune("Goodbye!\n"), 0, true+ }
+
+ return nil, 0, false
+ },
+ }
+ rl, err := readline.NewEx(config)
if err != nil {return nil, err
}
+
account, err := loadConfig()
if err != nil {return nil, err
@@ -67,8 +116,6 @@
dispatch := make(chan *mastodon.Toot, 15)
- var hc Hellclient
-
defer func() {//Got some stuff to do when we're done
hc.updatePrompt()
@@ -83,12 +130,12 @@
ref: "a",
postmap: homeMap,
}
-
+
homeref := &postref{ref: "a",
postmap: homeMap,
}
-
+
debugMap := make(map[string]interface{})urlMap := make(map[string][]string)
prefs := &Hellprefs{apidelay: time.Second * 3}@@ -113,6 +160,9 @@
unread, err := hc.client.GetUnreadNotifications(context.Background(), nil, nil, 0)
if err == nil { sb.WriteString(fmt.Sprintf("ur:%v ", unread.Count))+ }
+ if hc.multiLineMode {+ sb.WriteString("MULTI-LINE ")}
if hc.isPaused { sb.WriteString("STREAMING PAUSED ")--- a/main.go
+++ b/main.go
@@ -9,8 +9,8 @@
"strconv"
"strings"
- "github.com/mattn/go-mastodon"
"github.com/k3a/html2text"
+ "github.com/mattn/go-mastodon"
)
func main() {@@ -35,7 +35,6 @@
homeMap := hc.homeMap
debugMap := hc.debugMap
lastindex := ""
- interupted := false //use this to check if we were interupted last turn
recentpost := &hc.recentpost
if err != nil {@@ -50,23 +49,10 @@
//If we get an interupt error, we'll return to read the next line
//If the next line is empty, exit the program
//If it isn't empty, we were just clearing the line
- if interupted {- if len(line) == 0 {- os.Exit(0)
- } else {- interupted = false
- return
- }
- }
+
if err != nil {- if err == EOF || err == ErrInterrupt {- interupted = true
- return
- }
- if err != nil {- fmt.Println("Error:", err)- return
- }
+ fmt.Println("Error:", err)+ return
}
command, arguments := processInput(line)
--- a/mastodon.go
+++ b/mastodon.go
@@ -84,7 +84,7 @@
preformats := make(map[string]string)
for node := range doc.Descendants() {- if node.Data == "pre" && node.FirstChild != nil {+ if (node.Data == "pre" || node.Data == "") && node.FirstChild != nil { preformats[fmt.Sprintf("%p%p", hc, node.FirstChild)] = node.FirstChild.Data node.FirstChild.Data = fmt.Sprintf("%p%p", hc, node.FirstChild)}
@@ -128,9 +128,9 @@
if err != nil {return "", nil
}
-
+
renderedPlainText := rendered.String()
-
+
return renderedPlainText, preformats
}
--- a/notifications.go
+++ b/notifications.go
@@ -25,11 +25,11 @@
if err != nil {return
}
-
+
marker := markers["notifications"]
marker.ID = ID
marker.Timeline = "notifications"
-
+
err = hc.client.SetTimelineMarkers(context.Background(), &[]mastodon.Marker{*marker})return
}
--
⑨