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
--- 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)
--
⑨