DEC VT dumb terminals support
MODIFY
shortcuts/dialog.go
shortcuts/dialog.go
package shortcuts
import (
+ "log"
+ "os"
+ "regexp"
+
"github.com/Bios-Marcel/cordless/config"
"github.com/Bios-Marcel/cordless/ui/tviewutil"
"github.com/Bios-Marcel/tview"
"github.com/gdamore/tcell"
- "log"
)
+func checkVT() bool {
+ VTxxx, err := regexp.MatchString("(vt)[0-9]+", os.Getenv("TERM"))
+ if err != nil {
+ panic(err)
+ }
+ return VTxxx
+}
+
+var vtxxx = checkVT()
+
func ShowShortcutsDialog(app *tview.Application, onClose func(), beforeShow func(view *tview.Flex)) {
var table *ShortcutTable
var shortcutDescription *tview.TextView
@@ -60,11 +73,17 @@ func ShowShortcutsDialog(app *tview.Application, onClose func(), beforeShow func
shortcutDescription = tview.NewTextView()
shortcutDescription.SetDynamicColors(true)
+ if vtxxx {
+ shortcutDescription.SetText("R [::r]Reset shortcut[::-]" +
+ "[::-] Backspace [::r]Delete shortcut" +
+ "[::-] Enter [::r]Change shortcut" +
+ "[::-] Esc [::r]Close dialog")
+ } else {
shortcutDescription.SetText("[" + primaryTextColor + "][:" + primitiveBGColor + "]R [:" + primaryTextColor + "][" + primitiveBGColor + "]Reset shortcut" +
"[" + primaryTextColor + "][:" + primitiveBGColor + "] Backspace [:" + primaryTextColor + "][" + primitiveBGColor + "]Delete shortcut" +
"[" + primaryTextColor + "][:" + primitiveBGColor + "] Enter [:" + primaryTextColor + "][" + primitiveBGColor + "]Change shortcut" +
"[" + primaryTextColor + "][:" + primitiveBGColor + "] Esc [:" + primaryTextColor + "][" + primitiveBGColor + "]Close dialog")
-
+ }
table.SetFocusNext(func() { app.SetFocus(resetButton) })
table.SetFocusPrevious(func() { app.SetFocus(exitButton) })

MODIFY
shortcuts/table.go
shortcuts/table.go
@@ -35,6 +35,9 @@ func NewShortcutTable() *ShortcutTable {
table.SetSelectable(true, false)
table.SetBorder(true)
+ if vtxxx {
+ table.SetSelectedStyle(tcell.ColorBlack, tcell.ColorWhite, tcell.AttrReverse)
+ }
//Header + emptyrow
table.SetFixed(2, 3)

MODIFY
ui/channeltree.go
ui/channeltree.go
package ui
import (
+ "os"
+ "regexp"
"sort"
"sync"
+ "github.com/gdamore/tcell"
+
"github.com/Bios-Marcel/cordless/ui/tviewutil"
"github.com/Bios-Marcel/discordgo"
@@ -23,6 +27,16 @@ const (
channelRead
)
+func checkVT() bool {
+ VTxxx, err := regexp.MatchString("(vt)[0-9]+", os.Getenv("TERM"))
+ if err != nil {
+ panic(err)
+ }
+ return VTxxx
+}
+
+var vtxxx = checkVT()
+
// ChannelTree is the component that displays the channel hierarchy of the
// currently loaded guild and allows interactions with those channels.
type ChannelTree struct {
@@ -137,8 +151,12 @@ func createTopLevelChannelNodes(channelTree *ChannelTree, channel *discordgo.Cha
channelNode := createChannelNode(channel)
if !readstate.HasBeenRead(channel, channel.LastMessageID) {
channelTree.channelStates[channelNode] = channelUnread
+ if vtxxx {
+ channelNode.SetAttributes(tcell.AttrBlink)
+ } else {
channelNode.SetColor(config.GetTheme().AttentionColor)
}
+ }
channelTree.GetRoot().AddChild(channelNode)
}
@@ -155,8 +173,12 @@ func createSecondLevelChannelNodes(channelTree *ChannelTree, channel *discordgo.
if ok && channelID == channel.ParentID {
if !readstate.HasBeenRead(channel, channel.LastMessageID) {
channelTree.channelStates[channelNode] = channelUnread
+ if vtxxx {
+ channelNode.SetAttributes(tcell.AttrBlink)
+ } else {
channelNode.SetColor(config.GetTheme().AttentionColor)
}
+ }
node.AddChild(channelNode)
break
@@ -277,8 +299,11 @@ func (channelTree *ChannelTree) MarkChannelAsUnread(channelID string) {
referenceChannelID, ok := node.GetReference().(string)
if ok && referenceChannelID == channelID {
channelTree.channelStates[node] = channelUnread
+ if vtxxx {
+ node.SetAttributes(tcell.AttrBlink)
+ } else {
node.SetColor(config.GetTheme().AttentionColor)
-
+ }
return false
}
@@ -298,8 +323,12 @@ func (channelTree *ChannelTree) MarkChannelAsRead(channelID string) {
if channelTree.channelStates[node] != channelLoaded {
channelTree.channelStates[node] = channelRead
+ if vtxxx {
+ node.SetAttributes(tcell.AttrNone)
+ } else {
node.SetColor(config.GetTheme().PrimaryTextColor)
}
+ }
return false
}
@@ -318,7 +347,11 @@ func (channelTree *ChannelTree) MarkChannelAsMentioned(channelID string) {
if stateError == nil {
node.SetText("(@You) " + channel.Name)
}
+ if vtxxx {
+ node.SetAttributes(tcell.AttrBlink)
+ } else {
node.SetColor(config.GetTheme().AttentionColor)
+ }
return false
}
@@ -333,7 +366,11 @@ func (channelTree *ChannelTree) MarkChannelAsLoaded(channelID string) {
for node, state := range channelTree.channelStates {
if state == channelLoaded {
channelTree.channelStates[node] = channelRead
+ if vtxxx {
+ node.SetAttributes(tcell.AttrNone)
+ } else {
node.SetColor(config.GetTheme().PrimaryTextColor)
+ }
break
}
}
@@ -346,7 +383,11 @@ func (channelTree *ChannelTree) MarkChannelAsLoaded(channelID string) {
if stateError == nil {
node.SetText(channel.Name)
}
+ if vtxxx {
+ node.SetAttributes(tcell.AttrUnderline)
+ } else {
node.SetColor(tview.Styles.ContrastBackgroundColor)
+ }
return false
}

MODIFY
ui/chatview.go
ui/chatview.go
@@ -502,13 +502,26 @@ func (chatView *ChatView) formatDefaultMessageText(message *discordgo.Message) s
}
var color string
+ if vtxxx {
+ if chatView.state.User.ID == user.ID {
+ color = "[::r]"
+ } else {
+ color = "[::b]"
+ }
+ } else {
if chatView.state.User.ID == user.ID {
color = "[" + tviewutil.ColorToHex(config.GetTheme().AttentionColor) + "]"
} else {
color = "[" + tviewutil.ColorToHex(config.GetTheme().LinkColor) + "]"
}
+ }
- replacement := color + "@" + userName + "[" + tviewutil.ColorToHex(config.GetTheme().PrimaryTextColor) + "]"
+ var replacement string
+ if vtxxx {
+ replacement = color + "@" + userName + "[::-]"
+ } else {
+ replacement = color + "@" + userName + "[" + tviewutil.ColorToHex(config.GetTheme().PrimaryTextColor) + "]"
+ }
messageText = strings.NewReplacer(
"<@"+user.ID+">", replacement,
"<@!"+user.ID+">", replacement,

MODIFY
ui/editor.go
ui/editor.go
@@ -565,6 +565,18 @@ func (editor *Editor) SetBorderColor(color tcell.Color) {
editor.internalTextView.SetBorderColor(color)
}
+// SetBorderAttributes delegates to the underlying components SetBorderAttributes
+// method.
+func (editor *Editor) SetBorderAttributes(attr tcell.AttrMask) {
+ editor.internalTextView.SetBorderAttributes(attr)
+}
+
+// SetBorderFocusAttributes delegates to the underlying components SetBorderFocusAttributes
+// method.
+func (editor *Editor) SetBorderFocusAttributes(attr tcell.AttrMask) {
+ editor.internalTextView.SetBorderFocusAttributes(attr)
+}
+
// SetInputCapture sets the alternative input capture that will be used if the
// components default controls aren't being triggered.
func (editor *Editor) SetInputCapture(captureFunc func(event *tcell.EventKey) *tcell.EventKey) {

MODIFY
ui/login.go
ui/login.go
@@ -2,13 +2,14 @@ package ui
import (
"errors"
+ "os"
+
"github.com/Bios-Marcel/cordless/ui/tviewutil"
"github.com/Bios-Marcel/cordless/util/text"
"github.com/Bios-Marcel/discordgo"
"github.com/Bios-Marcel/tview"
"github.com/atotto/clipboard"
"github.com/gdamore/tcell"
- "os"
)
const splashText = `

MODIFY
ui/privatechats.go
ui/privatechats.go
@@ -117,8 +117,12 @@ func (privateList *PrivateChatList) addChannel(channel *discordgo.Channel) {
newNode := createPrivateChannelNode(channel)
if !readstate.HasBeenRead(channel, channel.LastMessageID) {
privateList.privateChannelStates[newNode] = unread
+ if vtxxx {
+ newNode.SetAttributes(tcell.AttrBlink)
+ } else {
newNode.SetColor(config.GetTheme().AttentionColor)
}
+ }
privateList.chatsNode.AddChild(newNode)
}
@@ -210,7 +214,11 @@ func (privateList *PrivateChatList) MarkChannelAsUnread(channel *discordgo.Chann
referenceChannelID, ok := node.GetReference().(string)
if ok && referenceChannelID == channel.ID {
privateList.privateChannelStates[node] = unread
+ if vtxxx {
+ node.SetAttributes(tcell.AttrBlink)
+ } else {
node.SetColor(config.GetTheme().AttentionColor)
+ }
break
}
}
@@ -223,8 +231,12 @@ func (privateList *PrivateChatList) MarkChannelAsRead(channelID string) {
if ok && referenceChannelID == channelID {
if privateList.privateChannelStates[node] != loaded {
privateList.privateChannelStates[node] = read
+ if vtxxx {
+ node.SetAttributes(tcell.AttrNone)
+ } else {
node.SetColor(config.GetTheme().PrimaryTextColor)
}
+ }
break
}
}
@@ -266,7 +278,11 @@ func (privateList *PrivateChatList) MarkChannelAsLoaded(channel *discordgo.Chann
for node, state := range privateList.privateChannelStates {
if state == loaded {
privateList.privateChannelStates[node] = read
+ if vtxxx {
+ node.SetAttributes(tcell.AttrNone)
+ } else {
node.SetColor(config.GetTheme().PrimaryTextColor)
+ }
break
}
}
@@ -275,7 +291,11 @@ func (privateList *PrivateChatList) MarkChannelAsLoaded(channel *discordgo.Chann
referenceChannelID, ok := node.GetReference().(string)
if ok && referenceChannelID == channel.ID {
privateList.privateChannelStates[node] = loaded
+ if vtxxx {
+ node.SetAttributes(tcell.AttrUnderline)
+ } else {
node.SetColor(tview.Styles.ContrastBackgroundColor)
+ }
break
}
}

MODIFY
ui/window.go
ui/window.go
@@ -1049,13 +1049,22 @@ func NewWindow(doRestart chan bool, app *tview.Application, session *discordgo.S
bottomBar.SetBackgroundColor(config.GetTheme().PrimitiveBackgroundColor)
loggedInAsText := fmt.Sprintf("Logged in as: '%s'", tviewutil.Escape(session.State.User.String()))
- loggedInAs := tview.NewTextView().SetText(loggedInAsText)
+ if vtxxx {
+ // For some reason there's an offset when the tag is applied. I have no idea how to fix this.
+ // Except maybe unify the bottom bar into a single TextView rather than using two in a Flex.
+ loggedInAsText = "[::r]" + loggedInAsText
+ }
+ loggedInAs := tview.NewTextView().SetText(loggedInAsText).SetDynamicColors(true)
loggedInAs.SetTextColor(config.GetTheme().PrimitiveBackgroundColor).SetBackgroundColor(config.GetTheme().PrimaryTextColor)
+
bottomBar.AddItem(loggedInAs, runewidth.StringWidth(loggedInAsText), 0, false)
bottomBar.AddItem(tview.NewBox(), 1, 0, false)
shortcutInfoText := fmt.Sprintf("View / Change shortcuts: %s", shortcuts.EventToString(shortcutsDialogShortcut))
- shortcutInfo := tview.NewTextView().SetText(shortcutInfoText)
+ if vtxxx {
+ shortcutInfoText = "[::r]" + shortcutInfoText
+ }
+ shortcutInfo := tview.NewTextView().SetText(shortcutInfoText).SetDynamicColors(true)
shortcutInfo.SetTextColor(config.GetTheme().PrimitiveBackgroundColor).SetBackgroundColor(config.GetTheme().PrimaryTextColor)
bottomBar.AddItem(shortcutInfo, runewidth.StringWidth(shortcutInfoText), 0, false)
@@ -1282,11 +1291,20 @@ func (window *Window) sendMessage(targetChannelID, message string) {
func (window *Window) updateServerReadStatus(guildID string, guildNode *tview.TreeNode, isSelected bool) {
if isSelected {
+ if vtxxx {
+ guildNode.SetAttributes(tcell.AttrUnderline)
+ } else {
guildNode.SetColor(tview.Styles.ContrastBackgroundColor)
+ }
} else {
if !readstate.HasGuildBeenRead(guildID) {
+ if vtxxx {
+ guildNode.SetAttributes(tcell.AttrBlink)
+ } else {
guildNode.SetColor(config.GetTheme().AttentionColor)
+ }
} else {
+ guildNode.SetAttributes(tcell.AttrNone)
guildNode.SetColor(tview.Styles.PrimaryTextColor)
}
}
@@ -2308,6 +2326,9 @@ func (window *Window) startEditingMessage(message *discordgo.Message) {
window.messageInput.SetText(message.Content)
window.messageInput.SetBorderColor(tcell.ColorYellow)
window.messageInput.SetBorderFocusColor(tcell.ColorYellow)
+ if vtxxx {
+ window.messageInput.SetBorderFocusAttributes(tcell.AttrBlink | tcell.AttrBold)
+ }
window.editingMessageID = &message.ID
window.app.SetFocus(window.messageInput.GetPrimitive())
}
@@ -2322,6 +2343,10 @@ func (window *Window) exitMessageEditModeAndKeepText() {
window.editingMessageID = nil
window.messageInput.SetBorderColor(tview.Styles.BorderColor)
window.messageInput.SetBorderFocusColor(tview.Styles.BorderFocusColor)
+ if vtxxx {
+ window.messageInput.SetBorderFocusAttributes(tcell.AttrBold)
+ window.messageInput.SetBorderAttributes(tcell.AttrNone)
+ }
}
//ShowErrorDialog shows a simple error dialog that has only an Okay button,
@@ -2516,7 +2541,11 @@ func (window *Window) LoadChannel(channel *discordgo.Channel) error {
for _, guildNode := range window.guildList.GetRoot().GetChildren() {
if guildNode.GetReference() == channel.GuildID {
window.guildList.SetCurrentNode(guildNode)
+ if vtxxx {
+ guildNode.SetAttributes(tcell.AttrUnderline)
+ } else {
guildNode.SetColor(tview.Styles.ContrastBackgroundColor)
+ }
window.selectedGuildNode = guildNode
break
}

DEC VT dumb terminals support