shithub: hell

Download patch

ref: 4d18579f8c4bfe20dbd00aed0e370b4e7f1961ac
parent: 6cefdc9f5a9cc2a2621d3cd832310b97a139bdc1
parent: 3866de6a3e1c5309b68c7659f78ffd3bb8bff370
author: penny64 <penny64@noreply.codeberg.org>
date: Sun Oct 19 21:51:27 EDT 2025

Merge pull request 'Platform support for Plan9' (#12) from plan9_port into main

Reviewed-on: https://codeberg.org/penny64/hellclient/pulls/12

git/query: bad hash 0c54172cf4a1629f4d99f5975c7242c434b14171
--- a/hellclient.go
+++ b/hellclient.go
@@ -8,14 +8,11 @@
 	"time"
 
 	mastodon "codeberg.org/penny64/hellclient-go-mastodon"
-	"github.com/ergochat/readline"
 )
 
-var (
-	ErrInterrupt = readline.ErrInterrupt
-	EOF          = io.EOF
-)
+var EOF = io.EOF
 
+
 type postref struct {
 	prefix  string
 	ref     string
@@ -26,7 +23,7 @@
 type Hellclient struct {
 	//if you're gonna touch or read anything here lock the mutex with hc.lock()
 	isPaused      bool
-	rl            *readline.Instance
+	rl            *readline
 	prompt        *PromptBar
 	attacher      *StatusAttachmentHolder
 	client        *mastodon.Client
@@ -72,24 +69,24 @@
 
 func NewHellclient() (*Hellclient, error) {
 	var hc Hellclient
-	config := &readline.Config{
+	config := &Config{
 		Prompt: "Hell> ",
 		FuncFilterInputRune: func(r rune) (rune, bool) {
-			if r == readline.CharCtrlJ {
+			if r == CharCtrlJ {
 				hc.multiLineMode = !hc.multiLineMode
 				hc.prompt.UpdatePrompt()
 				return r, false
 			}
-			if r == readline.CharInterrupt {
+			if r == CharInterrupt {
 				return toPUA(r), true
 			}
-			if r == readline.CharEnter && hc.multiLineMode {
+			if r == 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 {
+			if key == toPUA(CharEnter) && hc.multiLineMode {
 				// handle multi-line input
 				line = line[:len(line)-1]
 				line = append(line, '\n')
@@ -97,7 +94,7 @@
 			}
 
 			//If we get an interupt just clear the line if it's not empty
-			if key == toPUA(readline.CharInterrupt) {
+			if key == toPUA(CharInterrupt) {
 				if len(line) > 1 {
 					return nil, 0, true
 				}
@@ -107,7 +104,7 @@
 			return nil, 0, false
 		},
 	}
-	rl, err := readline.NewEx(config)
+	rl, err := NewReadline(config)
 	if err != nil {
 		return nil, err
 	}
--- a/index.html
+++ b/index.html
@@ -242,6 +242,9 @@
 href="https://penny64.codeberg.page/hellclient-downloads/linux/hell">Linux</a></li>
 <li><a
 href="https://penny64.codeberg.page/hellclient-downloads/mac/hell">Mac</a></li>
+<li><a
+href="https://penny64.codeberg.page/hellclient-downloads/plan9/hell">Plan
+9</a></li>
 </ul>
 </body>
 </html>
--- a/main.go
+++ b/main.go
@@ -3,8 +3,6 @@
 import (
 	"context"
 	"fmt"
-	"io"
-	"os"
 	"runtime/debug"
 	"strconv"
 	"strings"
@@ -23,15 +21,7 @@
 
 	rl := hc.rl
 	client := *hc.client
-
-	//Horrible io pipe hack
-	//Replaces system stdout with the readline one
-	r, w, _ := os.Pipe()
-	os.Stdout = w
-
-	go func() {
-		io.Copy(rl.Stdout(), r)
-	}()
+	enablePipeHack(rl)
 
 	homeMap := hc.homeMap
 	debugMap := hc.debugMap
--- a/prompt.go
+++ b/prompt.go
@@ -5,7 +5,6 @@
 	"fmt"
 	"strings"
 
-	"github.com/ergochat/readline"
 )
 
 // Returns text to add to the status bar
@@ -17,7 +16,7 @@
 type PromptBar struct {
 	prompt string
 	items  []PromptItem
-	rl     *readline.Instance
+	rl     *readline
 }
 
 // Render the prompt and update the readline prompt
--- /dev/null
+++ b/readline.go
@@ -1,0 +1,43 @@
+//go:build !plan9
+package main
+
+import (
+	"os"
+	"io"
+	native "github.com/ergochat/readline"
+)
+
+type readline struct {
+	*native.Instance
+}
+
+var (
+	ErrInterrupt = native.ErrInterrupt
+)
+
+type Config = native.Config
+
+const (
+	CharCtrlJ     = native.CharCtrlJ
+	CharInterrupt = native.CharInterrupt
+	CharEnter     = native.CharEnter
+)
+
+func NewReadline(config *Config) (*readline, error) {
+	instance, err := native.NewEx(config)
+	if err != nil {
+		return nil, err
+	}
+	return &readline{instance}, nil
+}
+
+func enablePipeHack(rl *readline) {
+	//Horrible io pipe hack
+	//Replaces system stdout with the readline one
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	go func() {
+		io.Copy(rl.Stdout(), r)
+	}()
+}
--- /dev/null
+++ b/readline_plan9.go
@@ -1,0 +1,70 @@
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"strings"
+)
+
+//not relevant
+const (
+	CharCtrlJ     = 0
+	CharInterrupt = 0
+	CharEnter     = 0
+)
+
+type readline struct {
+	config Config
+}
+
+type Config struct {
+	Prompt string
+
+	//These are unused on Plan 9
+	FuncFilterInputRune func(rune) (rune, bool)
+	Listener          func(line []rune, pos int, key rune) (newLine []rune, newPos int, ok bool)
+}
+
+func (rl *readline) GetConfig() *Config {
+	return &Config{Prompt: rl.config.Prompt}
+}
+
+func NewReadline(config *Config) (*readline, error) {
+	return &readline{config: *config}, nil
+}
+
+func (rl *readline) ReadLineWithConfig(cfg *Config) (string, error) {
+	fmt.Print(cfg.Prompt)
+	scanner := bufio.NewScanner(os.Stdin)
+
+	// Scan for the next token (by default, a line)
+	scanner.Scan()
+
+	// Get the text of the scanned line
+	input := scanner.Text()
+	return strings.TrimSpace(input), nil
+}
+
+func (rl *readline) Stdout() io.Writer {
+	return os.Stdout
+}
+
+func (rl *readline) Close() {
+	return
+}
+
+func (rl *readline) SetPrompt(prompt string) {
+	rl.config.Prompt = prompt
+}
+
+func (rl *readline) SetDefault(string) {
+}
+
+func (rl *readline) Readline() (string, error) {
+	return rl.ReadLineWithConfig(&rl.config)
+}
+
+func enablePipeHack(rl *readline) {
+}
--- a/readme.md
+++ b/readme.md
@@ -53,3 +53,4 @@
 * [Windows](https://penny64.codeberg.page/hellclient-downloads/win/hell.exe)
 * [Linux](https://penny64.codeberg.page/hellclient-downloads/linux/hell)
 * [Mac](https://penny64.codeberg.page/hellclient-downloads/mac/hell)
+* [Plan 9](https://penny64.codeberg.page/hellclient-downloads/plan9/hell)
--