mirror of
https://github.com/shazow/ssh-chat.git
synced 2025-07-05 05:04:33 +02:00
chat.Color->chat.Style, highlighting works.
This commit is contained in:
parent
3c4e6994c2
commit
838285ba43
@ -2,6 +2,7 @@ package chat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -101,6 +102,15 @@ func (m *PublicMsg) Render(t *Theme) string {
|
|||||||
return fmt.Sprintf("%s: %s", t.ColorName(m.from), m.body)
|
return fmt.Sprintf("%s: %s", t.ColorName(m.from), m.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PublicMsg) RenderHighlighted(t *Theme, highlight *regexp.Regexp) string {
|
||||||
|
if highlight == nil || t == nil {
|
||||||
|
return m.Render(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
body := highlight.ReplaceAllString(m.body, t.Highlight("${1}"))
|
||||||
|
return fmt.Sprintf("%s: %s", t.ColorName(m.from), body)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *PublicMsg) String() string {
|
func (m *PublicMsg) String() string {
|
||||||
return fmt.Sprintf("%s: %s", m.from.Name(), m.body)
|
return fmt.Sprintf("%s: %s", m.from.Name(), m.body)
|
||||||
}
|
}
|
||||||
@ -212,7 +222,7 @@ type CommandMsg struct {
|
|||||||
*PublicMsg
|
*PublicMsg
|
||||||
command string
|
command string
|
||||||
args []string
|
args []string
|
||||||
room *Room
|
room *Room
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *CommandMsg) Command() string {
|
func (m *CommandMsg) Command() string {
|
||||||
|
@ -28,12 +28,24 @@ const (
|
|||||||
Newline = "\r\n"
|
Newline = "\r\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interface for Colors
|
// Interface for Styles
|
||||||
type Color interface {
|
type Style interface {
|
||||||
String() string
|
String() string
|
||||||
Format(string) string
|
Format(string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// General hardcoded style, mostly used as a crutch until we flesh out the
|
||||||
|
// framework to support backgrounds etc.
|
||||||
|
type style string
|
||||||
|
|
||||||
|
func (c style) String() string {
|
||||||
|
return string(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c style) Format(s string) string {
|
||||||
|
return c.String() + s + Reset
|
||||||
|
}
|
||||||
|
|
||||||
// 256 color type, for terminals who support it
|
// 256 color type, for terminals who support it
|
||||||
type Color256 uint8
|
type Color256 uint8
|
||||||
|
|
||||||
@ -62,12 +74,12 @@ func (c Color0) Format(s string) string {
|
|||||||
|
|
||||||
// Container for a collection of colors
|
// Container for a collection of colors
|
||||||
type Palette struct {
|
type Palette struct {
|
||||||
colors []Color
|
colors []Style
|
||||||
size int
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a color by index, overflows are looped around.
|
// Get a color by index, overflows are looped around.
|
||||||
func (p Palette) Get(i int) Color {
|
func (p Palette) Get(i int) Style {
|
||||||
return p.colors[i%(p.size-1)]
|
return p.colors[i%(p.size-1)]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +97,11 @@ func (p Palette) String() string {
|
|||||||
|
|
||||||
// Collection of settings for chat
|
// Collection of settings for chat
|
||||||
type Theme struct {
|
type Theme struct {
|
||||||
id string
|
id string
|
||||||
sys Color
|
sys Style
|
||||||
pm Color
|
pm Style
|
||||||
names *Palette
|
highlight Style
|
||||||
|
names *Palette
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Theme) Id() string {
|
func (t Theme) Id() string {
|
||||||
@ -122,6 +135,14 @@ func (t Theme) ColorSys(s string) string {
|
|||||||
return t.sys.Format(s)
|
return t.sys.Format(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Highlight a matched string, usually name
|
||||||
|
func (t Theme) Highlight(s string) string {
|
||||||
|
if t.highlight == nil {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return t.highlight.Format(s)
|
||||||
|
}
|
||||||
|
|
||||||
// List of initialzied themes
|
// List of initialzied themes
|
||||||
var Themes []Theme
|
var Themes []Theme
|
||||||
|
|
||||||
@ -131,7 +152,7 @@ var DefaultTheme *Theme
|
|||||||
func readableColors256() *Palette {
|
func readableColors256() *Palette {
|
||||||
size := 247
|
size := 247
|
||||||
p := Palette{
|
p := Palette{
|
||||||
colors: make([]Color, size),
|
colors: make([]Style, size),
|
||||||
size: size,
|
size: size,
|
||||||
}
|
}
|
||||||
j := 0
|
j := 0
|
||||||
@ -151,10 +172,11 @@ func init() {
|
|||||||
|
|
||||||
Themes = []Theme{
|
Themes = []Theme{
|
||||||
Theme{
|
Theme{
|
||||||
id: "colors",
|
id: "colors",
|
||||||
names: palette,
|
names: palette,
|
||||||
sys: palette.Get(8), // Grey
|
sys: palette.Get(8), // Grey
|
||||||
pm: palette.Get(7), // White
|
pm: palette.Get(7), // White
|
||||||
|
highlight: style(Bold + "\033[48;5;11m\033[38;5;16m"), // Yellow highlight
|
||||||
},
|
},
|
||||||
Theme{
|
Theme{
|
||||||
id: "mono",
|
id: "mono",
|
||||||
|
33
chat/user.go
33
chat/user.go
@ -2,13 +2,16 @@ package chat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const messageBuffer = 20
|
const messageBuffer = 20
|
||||||
|
const reHighlight = `\b(%s)\b`
|
||||||
|
|
||||||
var ErrUserClosed = errors.New("user closed")
|
var ErrUserClosed = errors.New("user closed")
|
||||||
|
|
||||||
@ -100,9 +103,28 @@ func (u *User) ConsumeOne(out io.Writer) {
|
|||||||
u.HandleMsg(<-u.msg, out)
|
u.HandleMsg(<-u.msg, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetHighlight sets the highlighting regular expression to match string.
|
||||||
|
func (u *User) SetHighlight(s string) error {
|
||||||
|
re, err := regexp.Compile(fmt.Sprintf(reHighlight, s))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u.Config.Highlight = re
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u User) render(m Message) string {
|
||||||
|
switch m := m.(type) {
|
||||||
|
case *PublicMsg:
|
||||||
|
return m.RenderHighlighted(u.Config.Theme, u.Config.Highlight) + Newline
|
||||||
|
default:
|
||||||
|
return m.Render(u.Config.Theme) + Newline
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) HandleMsg(m Message, out io.Writer) {
|
func (u *User) HandleMsg(m Message, out io.Writer) {
|
||||||
s := m.Render(u.Config.Theme)
|
r := u.render(m)
|
||||||
_, err := out.Write([]byte(s + Newline))
|
_, err := out.Write([]byte(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Printf("Write failed to %s, closing: %s", u.Name(), err)
|
logger.Printf("Write failed to %s, closing: %s", u.Name(), err)
|
||||||
u.Close()
|
u.Close()
|
||||||
@ -127,7 +149,7 @@ func (u *User) Send(m Message) error {
|
|||||||
|
|
||||||
// Container for per-user configurations.
|
// Container for per-user configurations.
|
||||||
type UserConfig struct {
|
type UserConfig struct {
|
||||||
Highlight bool
|
Highlight *regexp.Regexp
|
||||||
Bell bool
|
Bell bool
|
||||||
Quiet bool
|
Quiet bool
|
||||||
Theme *Theme
|
Theme *Theme
|
||||||
@ -138,9 +160,8 @@ var DefaultUserConfig *UserConfig
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
DefaultUserConfig = &UserConfig{
|
DefaultUserConfig = &UserConfig{
|
||||||
Highlight: true,
|
Bell: true,
|
||||||
Bell: false,
|
Quiet: false,
|
||||||
Quiet: false,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Seed random?
|
// TODO: Seed random?
|
||||||
|
2
host.go
2
host.go
@ -92,6 +92,7 @@ func (h *Host) Connect(term *sshd.Terminal) {
|
|||||||
|
|
||||||
// Successfully joined.
|
// Successfully joined.
|
||||||
term.SetPrompt(GetPrompt(user))
|
term.SetPrompt(GetPrompt(user))
|
||||||
|
user.SetHighlight(user.Name())
|
||||||
h.count++
|
h.count++
|
||||||
|
|
||||||
// Should the user be op'd on join?
|
// Should the user be op'd on join?
|
||||||
@ -119,6 +120,7 @@ func (h *Host) Connect(term *sshd.Terminal) {
|
|||||||
// FIXME: This is hacky, how do we improve the API to allow for
|
// FIXME: This is hacky, how do we improve the API to allow for
|
||||||
// this? Chat module shouldn't know about terminals.
|
// this? Chat module shouldn't know about terminals.
|
||||||
term.SetPrompt(GetPrompt(user))
|
term.SetPrompt(GetPrompt(user))
|
||||||
|
user.SetHighlight(user.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user