mirror of
https://github.com/Rudi9719/kbtui.git
synced 2026-03-22 13:17:23 +00:00
Merge kbtui/dev into kbtui/awesome-gocui for support
This commit is contained in:
22
README.md
22
README.md
@ -16,27 +16,31 @@ For support or suggestions check out the [kbtui team](https://keybase.io/team/kb
|
|||||||
* Reactions to messages
|
* Reactions to messages
|
||||||
* Auto #general teams when not given a channel
|
* Auto #general teams when not given a channel
|
||||||
* Pretty format headers in List view from window size
|
* Pretty format headers in List view from window size
|
||||||
|
|
||||||
## Todo
|
|
||||||
* Message editing
|
* Message editing
|
||||||
* Twitter-style feed reading public messages
|
* Twitter-style feed reading public messages
|
||||||
|
|
||||||
|
## Todo
|
||||||
* Track multiple conversations at once
|
* Track multiple conversations at once
|
||||||
|
* Message replies
|
||||||
|
|
||||||
|
|
||||||
### Building and Running
|
### Building and Running
|
||||||
Easiest Way:
|
Easiest Way:
|
||||||
```
|
```
|
||||||
go get -u github.com/rudi9719/kbtui
|
go get -u github.com/rudi9719/kbtui
|
||||||
```
|
```
|
||||||
|
Or you can do the following:
|
||||||
```
|
```
|
||||||
go get ./
|
go get ./
|
||||||
go build
|
go run build.go
|
||||||
|
go run build.go {build, buildBeta... etc}
|
||||||
./kbtui
|
./kbtui
|
||||||
```
|
```
|
||||||
Or
|
|
||||||
```
|
You may see an error with `go get ./` about PATHs, that may be safely ignored.
|
||||||
go get ./
|
|
||||||
go run *.go
|
If you see an error about a missing dependancy during a build, you'll want to resolve that.
|
||||||
```
|
|
||||||
|
|
||||||
Occasionally when @dxb updates his API it will be necessary to run
|
Occasionally when @dxb updates his API it will be necessary to run
|
||||||
`go get -u ./`
|
`go get -u ./`
|
||||||
|
|||||||
24
cmdEdit.go
24
cmdEdit.go
@ -6,8 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/awesome-gocui/gocui"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -37,24 +35,10 @@ func cmdEdit(cmd []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
editString := origMessage.Result.Messages[0].Msg.Content.Text.Body
|
editString := origMessage.Result.Messages[0].Msg.Content.Text.Body
|
||||||
g.Update(func(g *gocui.Gui) error {
|
clearView("Edit")
|
||||||
inputView, err := g.View("Input")
|
popupView("Edit")
|
||||||
if err != nil {
|
printToView("Edit", fmt.Sprintf("/e %d %s", messageId, editString))
|
||||||
return err
|
viewTitle("Edit", fmt.Sprintf(" Editing message %d ", messageId))
|
||||||
} else {
|
|
||||||
editString = fmt.Sprintf("/edit %d %s", messageId, editString)
|
|
||||||
fmt.Fprintf(inputView, editString)
|
|
||||||
viewX, viewY := inputView.Size()
|
|
||||||
if len(editString) < viewX {
|
|
||||||
viewX = len(editString)
|
|
||||||
viewY = 0
|
|
||||||
} else {
|
|
||||||
viewX = viewX / len(editString)
|
|
||||||
}
|
|
||||||
inputView.MoveCursor(viewX, viewY, true)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(cmd) < 3 {
|
if len(cmd) < 3 {
|
||||||
|
|||||||
@ -27,6 +27,7 @@ func cmdJoin(cmd []string) {
|
|||||||
channel.TopicName = cmd[2]
|
channel.TopicName = cmd[2]
|
||||||
printToView("Feed", fmt.Sprintf("You are joining: @%s#%s", channel.Name, channel.TopicName))
|
printToView("Feed", fmt.Sprintf("You are joining: @%s#%s", channel.Name, channel.TopicName))
|
||||||
clearView("Chat")
|
clearView("Chat")
|
||||||
|
viewTitle("Input", fmt.Sprintf(" @%s#%s ", channel.Name, channel.TopicName))
|
||||||
go populateChat()
|
go populateChat()
|
||||||
} else if len(cmd) == 2 {
|
} else if len(cmd) == 2 {
|
||||||
channel.MembersType = keybase.USER
|
channel.MembersType = keybase.USER
|
||||||
@ -34,6 +35,7 @@ func cmdJoin(cmd []string) {
|
|||||||
channel.TopicName = ""
|
channel.TopicName = ""
|
||||||
printToView("Feed", fmt.Sprintf("You are joining: @%s", channel.Name))
|
printToView("Feed", fmt.Sprintf("You are joining: @%s", channel.Name))
|
||||||
clearView("Chat")
|
clearView("Chat")
|
||||||
|
viewTitle("Input", fmt.Sprintf(" @%s ", channel.Name))
|
||||||
go populateChat()
|
go populateChat()
|
||||||
} else {
|
} else {
|
||||||
printToView("Feed", fmt.Sprintf("To join a team use %sjoin <team> <channel>", cmdPrefix))
|
printToView("Feed", fmt.Sprintf("To join a team use %sjoin <team> <channel>", cmdPrefix))
|
||||||
|
|||||||
@ -17,5 +17,6 @@ func cmdStream(cmd []string) {
|
|||||||
stream = true
|
stream = true
|
||||||
channel.Name = ""
|
channel.Name = ""
|
||||||
printToView("Feed", "You are now viewing the formatted stream")
|
printToView("Feed", "You are now viewing the formatted stream")
|
||||||
|
viewTitle("Input", " Not in a chat /j to join ")
|
||||||
clearView("Chat")
|
clearView("Chat")
|
||||||
}
|
}
|
||||||
|
|||||||
1
mage.go
1
mage.go
@ -35,6 +35,7 @@ func BuildAllCommands() {
|
|||||||
func BuildAllCommandsT() {
|
func BuildAllCommandsT() {
|
||||||
sh.Run("go", "build", "-tags", "type_commands,allcommands")
|
sh.Run("go", "build", "-tags", "type_commands,allcommands")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build kbtui with beta functionality
|
// Build kbtui with beta functionality
|
||||||
func BuildBeta() {
|
func BuildBeta() {
|
||||||
sh.Run("go", "build", "-tags", "allcommands,showreactionscmd")
|
sh.Run("go", "build", "-tags", "allcommands,showreactionscmd")
|
||||||
|
|||||||
78
main.go
78
main.go
@ -24,27 +24,19 @@ var lastMessage keybase.ChatAPI
|
|||||||
var g *gocui.Gui
|
var g *gocui.Gui
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
fmt.Println("Checking login")
|
|
||||||
if !k.LoggedIn {
|
if !k.LoggedIn {
|
||||||
fmt.Println("You are not logged in.")
|
fmt.Println("You are not logged in.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("Creating err")
|
|
||||||
var err error
|
var err error
|
||||||
fmt.Println("creating kbtui")
|
|
||||||
g, err = gocui.NewGui(gocui.OutputNormal, false)
|
g, err = gocui.NewGui(gocui.OutputNormal, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Err wasn't nil")
|
|
||||||
fmt.Printf("%+v", err)
|
fmt.Printf("%+v", err)
|
||||||
}
|
}
|
||||||
fmt.Println("defer g.Close()")
|
|
||||||
defer g.Close()
|
defer g.Close()
|
||||||
fmt.Println("SetManagerFunc")
|
|
||||||
g.SetManagerFunc(layout)
|
g.SetManagerFunc(layout)
|
||||||
fmt.Println("Population")
|
|
||||||
go populateList()
|
go populateList()
|
||||||
go updateChatWindow()
|
go updateChatWindow()
|
||||||
fmt.Println("Args")
|
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
os.Args[0] = "join"
|
os.Args[0] = "join"
|
||||||
RunCommand(os.Args...)
|
RunCommand(os.Args...)
|
||||||
@ -54,11 +46,44 @@ func main() {
|
|||||||
if err := initKeybindings(); err != nil {
|
if err := initKeybindings(); err != nil {
|
||||||
fmt.Printf("%+v", err)
|
fmt.Printf("%+v", err)
|
||||||
}
|
}
|
||||||
fmt.Println("Mainloop start")
|
|
||||||
if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
|
if err := g.MainLoop(); err != nil && !gocui.IsQuit(err) {
|
||||||
fmt.Printf("%+v", err)
|
fmt.Printf("%+v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func viewTitle(viewName string, title string) {
|
||||||
|
g.Update(func(g *gocui.Gui) error {
|
||||||
|
updatingView, err := g.View(viewName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
updatingView.Title = title
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func popupView(viewName string) {
|
||||||
|
_, err := g.SetCurrentView(viewName)
|
||||||
|
if err != nil {
|
||||||
|
printToView("Feed", fmt.Sprintf("%+v", err))
|
||||||
|
}
|
||||||
|
_, err = g.SetViewOnTop(viewName)
|
||||||
|
if err != nil {
|
||||||
|
printToView("Feed", fmt.Sprintf("%+v", err))
|
||||||
|
}
|
||||||
|
g.Update(func(g *gocui.Gui) error {
|
||||||
|
updatingView, err := g.View(viewName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
viewX, viewY := updatingView.Size()
|
||||||
|
updatingView.MoveCursor(viewX, viewY, true)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func populateChat() {
|
func populateChat() {
|
||||||
lastMessage.ID = 0
|
lastMessage.ID = 0
|
||||||
chat := k.NewChat(channel)
|
chat := k.NewChat(channel)
|
||||||
@ -206,12 +231,21 @@ func printToView(viewName string, message string) {
|
|||||||
|
|
||||||
func layout(g *gocui.Gui) error {
|
func layout(g *gocui.Gui) error {
|
||||||
maxX, maxY := g.Size()
|
maxX, maxY := g.Size()
|
||||||
|
if editView, err := g.SetView("Edit", maxX/2-maxX/3+1, maxY/2, maxX-2, maxY/2+10, 0); err != nil {
|
||||||
|
if !gocui.IsUnknownView(err) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
editView.Editable = true
|
||||||
|
editView.Wrap = true
|
||||||
|
fmt.Fprintln(editView, "Edit window. Should disappear")
|
||||||
|
}
|
||||||
if feedView, err := g.SetView("Feed", maxX/2-maxX/3, 0, maxX-1, maxY/5, 0); err != nil {
|
if feedView, err := g.SetView("Feed", maxX/2-maxX/3, 0, maxX-1, maxY/5, 0); err != nil {
|
||||||
if !gocui.IsUnknownView(err) {
|
if !gocui.IsUnknownView(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
feedView.Autoscroll = true
|
feedView.Autoscroll = true
|
||||||
feedView.Wrap = true
|
feedView.Wrap = true
|
||||||
|
feedView.Title = "Feed Window"
|
||||||
fmt.Fprintln(feedView, "Feed Window - If you are mentioned or receive a PM it will show here")
|
fmt.Fprintln(feedView, "Feed Window - If you are mentioned or receive a PM it will show here")
|
||||||
}
|
}
|
||||||
if chatView, err2 := g.SetView("Chat", maxX/2-maxX/3, maxY/5+1, maxX-1, maxY-5, 0); err2 != nil {
|
if chatView, err2 := g.SetView("Chat", maxX/2-maxX/3, maxY/5+1, maxX-1, maxY-5, 0); err2 != nil {
|
||||||
@ -232,12 +266,14 @@ func layout(g *gocui.Gui) error {
|
|||||||
}
|
}
|
||||||
inputView.Editable = true
|
inputView.Editable = true
|
||||||
inputView.Wrap = true
|
inputView.Wrap = true
|
||||||
|
inputView.Title = " Not in a chat /j to join"
|
||||||
g.Cursor = true
|
g.Cursor = true
|
||||||
}
|
}
|
||||||
if listView, err4 := g.SetView("List", 0, 0, maxX/2-maxX/3-1, maxY-1, 0); err4 != nil {
|
if listView, err4 := g.SetView("List", 0, 0, maxX/2-maxX/3-1, maxY-1, 0); err4 != nil {
|
||||||
if !gocui.IsUnknownView(err4) {
|
if !gocui.IsUnknownView(err4) {
|
||||||
return err4
|
return err4
|
||||||
}
|
}
|
||||||
|
listView.Title = "Channels"
|
||||||
fmt.Fprintf(listView, "Lists\nWindow\nTo view\n activity")
|
fmt.Fprintf(listView, "Lists\nWindow\nTo view\n activity")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -264,15 +300,15 @@ func layout2(g *gocui.Gui) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInputString() (string, error) {
|
func getInputString(viewName string) (string, error) {
|
||||||
inputView, _ := g.View("Input")
|
inputView, _ := g.View(viewName)
|
||||||
return inputView.Line(0)
|
return inputView.Line(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initKeybindings() error {
|
func initKeybindings() error {
|
||||||
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
|
if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone,
|
||||||
func(g *gocui.Gui, v *gocui.View) error {
|
func(g *gocui.Gui, v *gocui.View) error {
|
||||||
input, err := getInputString()
|
input, err := getInputString("Input")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -287,7 +323,16 @@ func initKeybindings() error {
|
|||||||
}
|
}
|
||||||
if err := g.SetKeybinding("Input", gocui.KeyEnter, gocui.ModNone,
|
if err := g.SetKeybinding("Input", gocui.KeyEnter, gocui.ModNone,
|
||||||
func(g *gocui.Gui, v *gocui.View) error {
|
func(g *gocui.Gui, v *gocui.View) error {
|
||||||
return handleInput()
|
return handleInput("Input")
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := g.SetKeybinding("Edit", gocui.KeyEnter, gocui.ModNone,
|
||||||
|
func(g *gocui.Gui, v *gocui.View) error {
|
||||||
|
popupView("Chat")
|
||||||
|
popupView("Input")
|
||||||
|
return handleInput("Edit")
|
||||||
|
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -345,6 +390,7 @@ func handleMessage(api keybase.ChatAPI) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
fmt.Print("\a")
|
||||||
}
|
}
|
||||||
if api.Msg.Channel.MembersType == channel.MembersType && cleanChannelName(api.Msg.Channel.Name) == channel.Name {
|
if api.Msg.Channel.MembersType == channel.MembersType && cleanChannelName(api.Msg.Channel.Name) == channel.Name {
|
||||||
if channel.MembersType == keybase.TEAM && channel.TopicName != api.Msg.Channel.TopicName {
|
if channel.MembersType == keybase.TEAM && channel.TopicName != api.Msg.Channel.TopicName {
|
||||||
@ -374,9 +420,9 @@ func handleMessage(api keybase.ChatAPI) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleInput() error {
|
func handleInput(viewName string) error {
|
||||||
clearView("Input")
|
clearView(viewName)
|
||||||
inputString, _ := getInputString()
|
inputString, _ := getInputString(viewName)
|
||||||
if inputString == "" {
|
if inputString == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,27 +0,0 @@
|
|||||||
// +ignore
|
|
||||||
// +build type_commands autoreactcmd
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"samhofi.us/x/keybase"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
command := TypeCommand{
|
|
||||||
Cmd: []string{"text"},
|
|
||||||
Name: "AutoReact",
|
|
||||||
Description: "Automatically reacts to every incoming message with an emoji",
|
|
||||||
Exec: tcmdAutoReact,
|
|
||||||
}
|
|
||||||
|
|
||||||
RegisterTypeCommand(command)
|
|
||||||
}
|
|
||||||
|
|
||||||
func tcmdAutoReact(m keybase.ChatAPI) {
|
|
||||||
msgID := m.Msg.ID
|
|
||||||
channel := m.Msg.Channel
|
|
||||||
chat := k.NewChat(channel)
|
|
||||||
chat.React(msgID, ":+1:")
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
// +ignore
|
// +build !rm_basic_commands type_commands showreactionscmd
|
||||||
// +build type_commands showreactionscmd
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user