ouichat
This commit is contained in:
parent
08b843d80f
commit
65c7627e7e
34 changed files with 352 additions and 639 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,2 +1 @@
|
||||||
/ouichat
|
/target
|
||||||
|
|
||||||
|
|
264
Cargo.lock
generated
Normal file
264
Cargo.lock
generated
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_term"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atty"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "2.33.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_term",
|
||||||
|
"atty",
|
||||||
|
"bitflags",
|
||||||
|
"strsim",
|
||||||
|
"textwrap",
|
||||||
|
"unicode-width",
|
||||||
|
"vec_map",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-segmentation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.80"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numtoa"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ouichat"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"structopt",
|
||||||
|
"termion",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.1.57"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_termios"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||||
|
dependencies = [
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt"
|
||||||
|
version = "0.3.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8"
|
||||||
|
dependencies = [
|
||||||
|
"clap",
|
||||||
|
"lazy_static",
|
||||||
|
"structopt-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "structopt-derive"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.48"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termion"
|
||||||
|
version = "1.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"numtoa",
|
||||||
|
"redox_syscall",
|
||||||
|
"redox_termios",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-segmentation"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vec_map"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
10
Cargo.toml
Normal file
10
Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "ouichat"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Michael Zhang <mail@mzhang.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.34"
|
||||||
|
structopt = "0.3.20"
|
||||||
|
termion = "1.5.5"
|
|
@ -1,57 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import "container/list"
|
|
||||||
|
|
||||||
type BufferNode struct {
|
|
||||||
name string
|
|
||||||
children []*BufferNode
|
|
||||||
messages []*Message
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBufferNode(name string) *BufferNode {
|
|
||||||
return &BufferNode{
|
|
||||||
name: name,
|
|
||||||
children: make([]*BufferNode, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
WALK_DEPTH_FIRST = 0
|
|
||||||
WALK_BREADTH_FIRST = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
type WalkEntry struct {
|
|
||||||
Node *BufferNode
|
|
||||||
Depth int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n*BufferNode) AddChild(child*BufferNode) {
|
|
||||||
n.children = append(n.children, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *BufferNode) Walk(cb func(*WalkEntry), mode int) {
|
|
||||||
queue := list.New()
|
|
||||||
queue.PushBack(&WalkEntry{
|
|
||||||
Node: n,
|
|
||||||
Depth: 0,
|
|
||||||
})
|
|
||||||
|
|
||||||
for queue.Len() > 0 {
|
|
||||||
next := queue.Front()
|
|
||||||
queue.Remove(next)
|
|
||||||
entry := next.Value.(*WalkEntry)
|
|
||||||
cb(entry)
|
|
||||||
|
|
||||||
for _, child := range entry.Node.children {
|
|
||||||
childEntry := &WalkEntry{
|
|
||||||
Node: child,
|
|
||||||
Depth: entry.Depth + 1,
|
|
||||||
}
|
|
||||||
if mode == WALK_DEPTH_FIRST {
|
|
||||||
queue.PushFront(childEntry)
|
|
||||||
} else if mode == WALK_BREADTH_FIRST {
|
|
||||||
queue.PushBack(childEntry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package core
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type Message struct {
|
|
||||||
Time time.Time `json:"time"`
|
|
||||||
MessageID string
|
|
||||||
Author string
|
|
||||||
AuthorID string
|
|
||||||
Contents string
|
|
||||||
}
|
|
Binary file not shown.
BIN
fonts/roboto.ttf
BIN
fonts/roboto.ttf
Binary file not shown.
9
go.mod
9
go.mod
|
@ -1,9 +0,0 @@
|
||||||
module ouichat
|
|
||||||
|
|
||||||
go 1.14
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
|
||||||
github.com/veandco/go-sdl2 v0.4.4
|
|
||||||
gopkg.in/irc.v3 v3.1.3
|
|
||||||
)
|
|
17
go.sum
17
go.sum
|
@ -1,17 +0,0 @@
|
||||||
github.com/MONKEY-WORKS/cassowary v0.0.0-20180307084501-6ee9ddb566f5 h1:KE9sasTMSjdsNIxvLyKMArAkzDyvwUo3O6ZqpOJNGWc=
|
|
||||||
github.com/MONKEY-WORKS/cassowary v0.0.0-20180307084501-6ee9ddb566f5/go.mod h1:kx7TtzC7VssZelylEr4cXP8Y/RVcBWT7ngGQg4MVijE=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/monkey-works/cassowary v0.0.0-20180307084501-6ee9ddb566f5 h1:PqoJpAn2FCPtiQ0/PcuRDZ14Bl6vg6zukOQmoeYLdsU=
|
|
||||||
github.com/monkey-works/cassowary v0.0.0-20180307084501-6ee9ddb566f5/go.mod h1:M/BEaa1gf6g5yzH31758qbbAMp0WjZh2KGP6LnCxiJE=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
github.com/veandco/go-sdl2 v0.4.4 h1:coOJGftOdvNvGoUIZmm4XD+ZRQF4mg9ZVHmH3/42zFQ=
|
|
||||||
github.com/veandco/go-sdl2 v0.4.4/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/irc.v3 v3.1.3 h1:yeTiJ365882L8h4AnBKYfesD92y5R5ZhGiylu9DfcPY=
|
|
||||||
gopkg.in/irc.v3 v3.1.3/go.mod h1:shO2gz8+PVeS+4E6GAny88Z0YVVQSxQghdrMVGQsR9s=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
74
main.go
74
main.go
|
@ -1,74 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
"github.com/veandco/go-sdl2/ttf"
|
|
||||||
|
|
||||||
"ouichat/core"
|
|
||||||
"ouichat/plugins"
|
|
||||||
"ouichat/ui"
|
|
||||||
)
|
|
||||||
|
|
||||||
func run() int {
|
|
||||||
var err error
|
|
||||||
|
|
||||||
// Initialize libraries
|
|
||||||
if err = sdl.Init(sdl.INIT_EVERYTHING); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer sdl.Quit()
|
|
||||||
if err = ttf.Init(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer ttf.Quit()
|
|
||||||
|
|
||||||
// create window
|
|
||||||
window, err := sdl.CreateWindow(
|
|
||||||
"ouichat",
|
|
||||||
sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED,
|
|
||||||
1024, 768,
|
|
||||||
sdl.WINDOW_SHOWN,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
defer window.Destroy()
|
|
||||||
|
|
||||||
// create buffer tree
|
|
||||||
tree := core.NewBufferNode("ouichat")
|
|
||||||
|
|
||||||
// start plugins
|
|
||||||
man := plugins.NewPluginManager(tree)
|
|
||||||
man.Spawn(plugins.NewIrcPlugin("acm"))
|
|
||||||
|
|
||||||
// initialize ui
|
|
||||||
ui, err := ui.NewUI(window, tree)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
defer ui.Close()
|
|
||||||
|
|
||||||
// main loop
|
|
||||||
for {
|
|
||||||
exit := ui.RenderLoop()
|
|
||||||
window.UpdateSurface()
|
|
||||||
|
|
||||||
if exit {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var exitcode int
|
|
||||||
sdl.Main(func() {
|
|
||||||
exitcode = run()
|
|
||||||
})
|
|
||||||
os.Exit(exitcode)
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
package plugins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"ouichat/core"
|
|
||||||
|
|
||||||
"gopkg.in/irc.v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
type IrcPlugin struct {
|
|
||||||
name string
|
|
||||||
client *irc.Client
|
|
||||||
messages chan *irc.Message
|
|
||||||
man *PluginManager
|
|
||||||
root *core.BufferNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewIrcPlugin(name string) *IrcPlugin {
|
|
||||||
conn, err := tls.Dial("tcp", "acm.umn.edu:6669", &tls.Config{})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// messages := make(chan *irc.Message)
|
|
||||||
config := irc.ClientConfig{
|
|
||||||
Nick: "ouichat",
|
|
||||||
User: "ouichat",
|
|
||||||
Name: "ouichat",
|
|
||||||
Handler: irc.HandlerFunc(func(c *irc.Client, m *irc.Message) {
|
|
||||||
fmt.Printf("%+v\n", m)
|
|
||||||
// messages <- m
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
client := irc.NewClient(conn, config)
|
|
||||||
return &IrcPlugin{
|
|
||||||
name: name,
|
|
||||||
client: client,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func(p*IrcPlugin) Name() string {
|
|
||||||
return p.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *IrcPlugin) Init(man *PluginManager, root *core.BufferNode) {
|
|
||||||
p.man = man
|
|
||||||
p.root = root
|
|
||||||
go p.client.Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *IrcPlugin) Buffers() *core.BufferNode {
|
|
||||||
return p.root
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
package plugins
|
|
||||||
|
|
||||||
import "ouichat/core"
|
|
||||||
|
|
||||||
// PluginManager is a convenience type that handles everything related to plugins
|
|
||||||
type PluginManager struct {
|
|
||||||
root *core.BufferNode
|
|
||||||
plugins []Plugin
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewPluginManager(root *core.BufferNode) *PluginManager {
|
|
||||||
return &PluginManager{
|
|
||||||
root: root,
|
|
||||||
plugins: make([]Plugin, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (man *PluginManager) Spawn(plugin Plugin) {
|
|
||||||
node := core.NewBufferNode(plugin.Name())
|
|
||||||
man.root.AddChild(node)
|
|
||||||
plugin.Init(man, node)
|
|
||||||
man.plugins = append(man.plugins, plugin)
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package plugins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"ouichat/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Plugin interface {
|
|
||||||
// Name is a unique name
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// Start is executed before anything
|
|
||||||
Init(man *PluginManager, root *core.BufferNode)
|
|
||||||
|
|
||||||
// Buffers gets a list of the buffers underneath this one
|
|
||||||
// the root one given to the plugin must be returned
|
|
||||||
Buffers() *core.BufferNode
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
package plugins
|
|
|
@ -1 +0,0 @@
|
||||||
package plugins
|
|
4
src/cli_opts.rs
Normal file
4
src/cli_opts.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
pub struct Options {}
|
1
src/config/mod.rs
Normal file
1
src/config/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub struct Config {}
|
1
src/gui/buffer.rs
Normal file
1
src/gui/buffer.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
24
src/gui/mod.rs
Normal file
24
src/gui/mod.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
mod buffer;
|
||||||
|
mod window;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use termion::{
|
||||||
|
raw::{IntoRawMode, RawTerminal},
|
||||||
|
screen::AlternateScreen,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Gui {
|
||||||
|
screen: AlternateScreen<RawTerminal<io::Stdout>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Gui {
|
||||||
|
pub fn init() -> Result<Self> {
|
||||||
|
let stdin = io::stdin();
|
||||||
|
let stdout = io::stdout();
|
||||||
|
let screen = AlternateScreen::from(stdout.into_raw_mode()?);
|
||||||
|
|
||||||
|
Ok(Gui { screen })
|
||||||
|
}
|
||||||
|
}
|
1
src/gui/window.rs
Normal file
1
src/gui/window.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
7
src/lib.rs
Normal file
7
src/lib.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
mod cli_opts;
|
||||||
|
mod config;
|
||||||
|
mod gui;
|
||||||
|
mod ouichat;
|
||||||
|
|
||||||
|
pub use crate::cli_opts::Options;
|
||||||
|
pub use crate::ouichat::Ouichat;
|
13
src/main.rs
Normal file
13
src/main.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use ouichat::{Options, Ouichat};
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let opts = Options::from_args();
|
||||||
|
println!("{:?}", opts);
|
||||||
|
|
||||||
|
let ouichat = Ouichat::new()?;
|
||||||
|
ouichat.main_loop();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
9
src/ouichat/main_loop.rs
Normal file
9
src/ouichat/main_loop.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use super::Ouichat;
|
||||||
|
|
||||||
|
impl Ouichat {
|
||||||
|
pub fn main_loop(mut self) {
|
||||||
|
loop {
|
||||||
|
println!("hello");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
src/ouichat/mod.rs
Normal file
17
src/ouichat/mod.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
mod main_loop;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use crate::gui::Gui;
|
||||||
|
|
||||||
|
pub struct Ouichat {
|
||||||
|
gui: Gui,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ouichat {
|
||||||
|
pub fn new() -> Result<Self> {
|
||||||
|
let gui = Gui::init()?;
|
||||||
|
|
||||||
|
Ok(Ouichat { gui })
|
||||||
|
}
|
||||||
|
}
|
11
ui/colors.go
11
ui/colors.go
|
@ -1,11 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import "github.com/veandco/go-sdl2/sdl"
|
|
||||||
|
|
||||||
var (
|
|
||||||
BACKGROUND = sdl.Color{R: 46, G: 46, B: 50, A: 255}
|
|
||||||
BACKGROUND2 = sdl.Color{R: 37, G: 37, B: 41, A: 255}
|
|
||||||
DIVIDER = sdl.Color{R: 32, G: 32, B: 36, A: 255}
|
|
||||||
TEXT = sdl.Color{R: 151, G: 151, B: 156, A: 255}
|
|
||||||
CARET = sdl.Color{R: 147, G: 221, B: 250, A: 255}
|
|
||||||
)
|
|
|
@ -1,4 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
type Scroller struct {
|
|
||||||
}
|
|
81
ui/ui.go
81
ui/ui.go
|
@ -1,81 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
"github.com/veandco/go-sdl2/ttf"
|
|
||||||
|
|
||||||
"ouichat/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
FrameRate = 60
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
sansFont *ttf.Font
|
|
||||||
monoFont *ttf.Font
|
|
||||||
)
|
|
||||||
|
|
||||||
type UI struct {
|
|
||||||
win *sdl.Window
|
|
||||||
rdr *sdl.Renderer // SDL renderer
|
|
||||||
root View
|
|
||||||
focused *View
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUI(win *sdl.Window, tree *core.BufferNode) (*UI, error) {
|
|
||||||
rdr, err := sdl.CreateRenderer(win, 0, 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if sansFont == nil {
|
|
||||||
if sansFont, err = ttf.OpenFont("fonts/roboto.ttf", 16); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if monoFont == nil {
|
|
||||||
if monoFont, err = ttf.OpenFont("fonts/roboto-mono.ttf", 16); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
root := NewRootView(tree)
|
|
||||||
|
|
||||||
return &UI{
|
|
||||||
win: win,
|
|
||||||
rdr: rdr,
|
|
||||||
root: root,
|
|
||||||
focused: nil,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ui *UI) RenderLoop() bool {
|
|
||||||
// handle events first
|
|
||||||
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
|
||||||
switch event.(type) {
|
|
||||||
case *sdl.KeyboardEvent:
|
|
||||||
// fmt.Printf("event: %+v\n", event)
|
|
||||||
case *sdl.QuitEvent:
|
|
||||||
println("Quit")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// render
|
|
||||||
ui.rdr.SetDrawColor(BACKGROUND.R, BACKGROUND.G, BACKGROUND.B, BACKGROUND.A)
|
|
||||||
ui.rdr.Clear()
|
|
||||||
w, h := ui.win.GetSize()
|
|
||||||
ui.root.Draw(ui.rdr, 0, 0, int(w), int(h))
|
|
||||||
|
|
||||||
ui.rdr.Present()
|
|
||||||
sdl.Delay(1000 / FrameRate)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ui *UI) Close() {
|
|
||||||
ui.rdr.Destroy()
|
|
||||||
sansFont.Close()
|
|
||||||
monoFont.Close()
|
|
||||||
}
|
|
25
ui/util.go
25
ui/util.go
|
@ -1,25 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
"github.com/veandco/go-sdl2/ttf"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateText(r *sdl.Renderer, font *ttf.Font, text string, color sdl.Color) (*sdl.Texture, int32, int32, error) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
surf *sdl.Surface
|
|
||||||
txt *sdl.Texture
|
|
||||||
)
|
|
||||||
|
|
||||||
if surf, err = font.RenderUTF8Blended(text, color); err != nil {
|
|
||||||
return nil, -1, -1, err
|
|
||||||
}
|
|
||||||
defer surf.Free()
|
|
||||||
|
|
||||||
if txt, err = r.CreateTextureFromSurface(surf); err != nil {
|
|
||||||
return nil, -1, -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return txt, surf.W, surf.H, nil
|
|
||||||
}
|
|
35
ui/view.go
35
ui/view.go
|
@ -1,35 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
idLock = &sync.Mutex{}
|
|
||||||
id = 0
|
|
||||||
)
|
|
||||||
|
|
||||||
// View is a rectangular widget
|
|
||||||
type View interface {
|
|
||||||
// Name returns a unique way to identify this view
|
|
||||||
// Use ViewID to create a unique ID
|
|
||||||
Name() string
|
|
||||||
|
|
||||||
// Draw the view using the given dimensions and offset
|
|
||||||
Draw(r *sdl.Renderer, x, y int32, w, h int) error
|
|
||||||
|
|
||||||
GetWidth() int
|
|
||||||
GetMinWidth() int
|
|
||||||
}
|
|
||||||
|
|
||||||
func ViewID(name string) string {
|
|
||||||
idLock.Lock()
|
|
||||||
defer idLock.Unlock()
|
|
||||||
|
|
||||||
next := id
|
|
||||||
id += 1
|
|
||||||
return fmt.Sprintf("%s_%d", name, next)
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import "github.com/veandco/go-sdl2/sdl"
|
|
||||||
|
|
||||||
type BufferView struct {
|
|
||||||
name string
|
|
||||||
textbox *TextBox
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBufferView(name string) *BufferView {
|
|
||||||
return &BufferView{
|
|
||||||
name: ViewID(name),
|
|
||||||
textbox: NewTextBox(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BufferView) Name() string {
|
|
||||||
return v.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BufferView) GetWidth() int {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BufferView) GetMinWidth() int {
|
|
||||||
return 400
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *BufferView) Draw(r *sdl.Renderer, x, y int32, w, h int) error {
|
|
||||||
v.textbox.Draw(r, x, y+int32(h)-40, w, 40)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
|
|
||||||
"ouichat/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
type RootView struct {
|
|
||||||
name string
|
|
||||||
split *VSplitView
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRootView(tree *core.BufferNode) *RootView {
|
|
||||||
name := ViewID("root")
|
|
||||||
|
|
||||||
split := NewVSplitView()
|
|
||||||
split.AddChild(NewTreeView(tree))
|
|
||||||
split.AddChild(NewBufferView("empty"))
|
|
||||||
|
|
||||||
return &RootView{
|
|
||||||
name,
|
|
||||||
split,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *RootView) Name() string {
|
|
||||||
return v.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *RootView) GetWidth() int {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *RootView) GetMinWidth() int {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *RootView) Draw(r *sdl.Renderer, x, y int32, w, h int) error {
|
|
||||||
// don't do anything but forward it to the split
|
|
||||||
return v.split.Draw(r, x, y, w, h)
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
|
|
||||||
"ouichat/core"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TreeView struct {
|
|
||||||
name string
|
|
||||||
tree *core.BufferNode
|
|
||||||
width uint
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTreeView(tree *core.BufferNode) *TreeView {
|
|
||||||
return &TreeView{
|
|
||||||
name: ViewID("tree"),
|
|
||||||
tree: tree,
|
|
||||||
width: 200,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TreeView) Name() string {
|
|
||||||
return v.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TreeView) GetWidth() int {
|
|
||||||
return int(v.width)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TreeView) GetMinWidth() int {
|
|
||||||
return 200
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *TreeView) Draw(r *sdl.Renderer, x, y int32, w, h int) error {
|
|
||||||
var (
|
|
||||||
txt *sdl.Texture
|
|
||||||
tw, th int32
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if txt, tw, th, err = CreateText(r, sansFont, "BUFFERS", TEXT); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer txt.Destroy()
|
|
||||||
r.Copy(txt, nil, &sdl.Rect{X: 5, Y: 5, W: tw, H: th})
|
|
||||||
|
|
||||||
v.tree.Walk(func(entry *core.WalkEntry) {
|
|
||||||
fmt.Printf("%s%+v\n", strings.Repeat(" ", entry.Depth), entry.Node)
|
|
||||||
}, core.WALK_DEPTH_FIRST)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
)
|
|
||||||
|
|
||||||
type VSplitView struct {
|
|
||||||
children []View
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewVSplitView() *VSplitView {
|
|
||||||
children := make([]View, 0)
|
|
||||||
return &VSplitView{
|
|
||||||
children,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *VSplitView) AddChild(child View) {
|
|
||||||
v.children = append(v.children, child)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *VSplitView) Draw(r *sdl.Renderer, x, y int32, w, h int) error {
|
|
||||||
totalWidth := w - int(len(v.children)) + 1
|
|
||||||
widths := make([]int, len(v.children))
|
|
||||||
remainingChildren := 0
|
|
||||||
for i, child := range v.children {
|
|
||||||
cw := child.GetWidth()
|
|
||||||
if cw >= 0 {
|
|
||||||
totalWidth -= cw
|
|
||||||
widths[i] = cw
|
|
||||||
} else {
|
|
||||||
remainingChildren += 1
|
|
||||||
widths[i] = -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
eachChild := totalWidth / remainingChildren
|
|
||||||
for i := range v.children {
|
|
||||||
if widths[i] == -1 {
|
|
||||||
widths[i] = eachChild
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
runningX := int32(0)
|
|
||||||
for i, child := range v.children {
|
|
||||||
child.Draw(r, runningX, y, widths[i], h)
|
|
||||||
runningX += int32(widths[i] + 1)
|
|
||||||
|
|
||||||
if err := r.SetDrawColor(DIVIDER.R, DIVIDER.G, DIVIDER.B, DIVIDER.A); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := r.DrawLine(runningX-1, y, int32(runningX)-1, y+int32(h)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package ui
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/veandco/go-sdl2/gfx"
|
|
||||||
"github.com/veandco/go-sdl2/sdl"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
blinkTimer = time.Now()
|
|
||||||
)
|
|
||||||
|
|
||||||
type TextBox struct {
|
|
||||||
value string
|
|
||||||
hasFocus bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTextBox() *TextBox {
|
|
||||||
return &TextBox{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *TextBox) Draw(r *sdl.Renderer, x, y int32, w, h int) error {
|
|
||||||
r.SetDrawColor(BACKGROUND2.R, BACKGROUND2.G, BACKGROUND2.B, BACKGROUND2.A)
|
|
||||||
r.FillRect(&sdl.Rect{X: x, Y: y, W: int32(w), H: int32(h)})
|
|
||||||
|
|
||||||
if int64(time.Now().Sub(blinkTimer).Seconds())%2 == 0 {
|
|
||||||
cx := x + 5
|
|
||||||
gfx.ThickLineColor(r, cx, y+5, cx, y+int32(h)-5, 3, CARET)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue