15 Commits
14 changed files with 564 additions and 78 deletions
+2 -2
View File
@@ -8,7 +8,7 @@ GO ?= $(shell which go)
build:
mkdir -p build
cd src/; $(GO) build -ldflags "-w" -o ../build/typer
cd src/; $(GO) build -ldflags "-w -X 'main.sysconfdir=$(SYSCONFDIR)'" -o ../build/typer
install: build/typer
# Create directories
@@ -24,4 +24,4 @@ uninstall:
clean:
rm -r build/
.PHONY: build
.PHONY: build
+6 -2
View File
@@ -6,6 +6,10 @@
| ![Example of the Typer's default style](media/default-style.png) | ![Example of the Typer's classic style](media/classic-style.png) |
### Installation
#### From a package manager:
| Distribution | Package name |
|:----------------------:|:---------------------|
| Arch Linux/Artix Linux | `typer` from the AUR |
#### From source:
- Download `go` from your package manager or from the go website
- Downlaod `which` from your package manager
@@ -16,5 +20,5 @@ make
```
- Run the following command **with superuser privileges** to install Typer to your system
```shell
make install SYSCONFDIR=/etc
```
make install
```
+1
View File
@@ -5,5 +5,6 @@ selected_style_fallback: "default-fallback" # Style for 8-color capable terminal
# Other
show_top_menu: true
show_line_index: true
extend_line_index: false # Extend line index to the bottom of the screen
buffer_info_message: "File: %f Cursor: (%x, %y, %p) Chars: %c"
tab_indentation: 4 # Length of tab characters
+14 -2
View File
@@ -2,6 +2,9 @@ keybindings:
- keybinding: "Ctrl-Q"
cursor_modes: ["buffer"]
command: "quit"
- keybinding: "Ctrl-X"
cursor_modes: ["buffer"]
command: "cut"
- keybinding: "Ctrl-C"
cursor_modes: ["buffer"]
command: "copy"
@@ -14,9 +17,15 @@ keybindings:
- keybinding: "Ctrl-O"
cursor_modes: ["buffer"]
command: "open"
- keybinding: "Ctrl-R"
- keybinding: "Ctrl-L"
cursor_modes: ["buffer"]
command: "reload"
- keybinding: "Ctrl-F"
cursor_modes: [ "buffer" ]
command: "find"
- keybinding: "Ctrl-R"
cursor_modes: [ "buffer" ]
command: "replace"
- keybinding: "PgUp"
cursor_modes: ["buffer"]
command: "prev-buffer"
@@ -37,4 +46,7 @@ keybindings:
command: "menu-edit"
- keybinding: "F3"
cursor_modes: ["buffer","dropdown"]
command: "menu-buffers"
command: "menu-buffers"
- keybinding: "Ctrl-E"
cursor_modes: ["buffer"]
command: "execute"
+186 -1
View File
@@ -98,6 +98,16 @@ func (buffer *Buffer) Load() error {
return nil
}
// Replace tilde with home directory
if strings.HasPrefix(buffer.filename, "~/") {
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
buffer.filename = filepath.Join(homedir, buffer.filename[2:])
}
content, err := os.ReadFile(buffer.filename)
if err != nil {
return err
@@ -113,8 +123,18 @@ func (buffer *Buffer) Save() error {
return nil
}
// Replace tilde with home directory
if strings.HasPrefix(buffer.filename, "~/") {
homedir, err := os.UserHomeDir()
if err != nil {
return err
}
buffer.filename = filepath.Join(homedir, buffer.filename[2:])
}
// Append new line character at end of buffer contents if not present
if buffer.Contents[len(buffer.Contents)-1] != '\n' {
if buffer.Contents == "" || buffer.Contents[len(buffer.Contents)-1] != '\n' {
buffer.Contents += "\n"
}
@@ -164,6 +184,171 @@ func (buffer *Buffer) GetSelectedText() string {
}
}
func (buffer *Buffer) CutText(window *Window) (string, int) {
if buffer.Selection == nil {
// Copy line
copiedText := ""
startOfLine := window.CurrentBuffer.CursorPos
endOfLine := window.CurrentBuffer.CursorPos
// Add current letter to copied text
if buffer.CursorPos < len(buffer.Contents) {
copiedText = string(buffer.Contents[buffer.CursorPos])
}
// Find end of line
for i := buffer.CursorPos + 1; i < len(buffer.Contents); i++ {
currentLetter := buffer.Contents[i]
endOfLine++
copiedText += string(currentLetter)
if currentLetter == '\n' {
break
}
}
// Find start of line
for i := buffer.CursorPos - 1; i >= 0; i-- {
currentLetter := buffer.Contents[i]
if currentLetter != '\n' {
startOfLine--
copiedText = string(currentLetter) + copiedText
} else {
break
}
}
// Remove line from buffer contents
buffer.Contents = buffer.Contents[:startOfLine] + buffer.Contents[endOfLine+1:]
return copiedText, 0
} else {
// Copy selection
copiedText := buffer.GetSelectedText()
// Remove selected text
edge1, edge2 := buffer.GetSelectionEdges()
if edge2 == len(buffer.Contents) {
edge2 = len(buffer.Contents) - 1
}
buffer.Contents = buffer.Contents[:edge1] + buffer.Contents[edge2+1:]
window.SetCursorPos(edge1)
buffer.Selection = nil
return copiedText, 1
}
}
func (buffer *Buffer) CopyText() (string, int) {
if buffer.Selection == nil {
// Copy line
copiedText := ""
// Add current letter to copied text
if buffer.CursorPos < len(buffer.Contents) {
copiedText = string(buffer.Contents[buffer.CursorPos])
}
// Find end of line
for i := buffer.CursorPos + 1; i < len(buffer.Contents); i++ {
currentLetter := buffer.Contents[i]
copiedText += string(currentLetter)
if currentLetter == '\n' {
break
}
}
// Find start of line
for i := buffer.CursorPos - 1; i >= 0; i-- {
currentLetter := buffer.Contents[i]
if currentLetter != '\n' {
copiedText = string(currentLetter) + copiedText
} else {
break
}
}
return copiedText, 0
} else {
// Copy selection
return buffer.GetSelectedText(), 1
}
}
func (buffer *Buffer) PasteText(window *Window, text string) {
str := buffer.Contents
// Remove selected text
if buffer.Selection != nil {
edge1, edge2 := buffer.GetSelectionEdges()
if edge2 == len(buffer.Contents) {
edge2 = len(buffer.Contents) - 1
}
str = str[:edge1] + str[edge2+1:]
buffer.Contents = str
window.SetCursorPos(edge1)
buffer.Selection = nil
}
index := buffer.CursorPos
if index == len(str) {
str += text
} else {
str = str[:index] + text + str[index:]
}
buffer.Contents = str
window.SetCursorPos(buffer.CursorPos + len(text))
}
func (buffer *Buffer) FindSubstring(substring string, afterPos int) int {
// Return no match if afterPos is larger than the buffer contents size
if afterPos >= len(buffer.Contents) {
return -1
}
index := strings.Index(buffer.Contents[afterPos+1:], substring)
if index != -1 {
index += afterPos + 1
}
return index
}
func (buffer *Buffer) FindAndReplaceSubstring(substring, replacement string, afterPos int) int {
index := buffer.FindSubstring(substring, afterPos)
// Return if substring isn't found
if index == -1 {
return -1
}
// Replace substring with replacement string
buffer.Contents = buffer.Contents[:index] + replacement + buffer.Contents[index+len(substring):]
return index
}
func (buffer *Buffer) FindAndReplaceAll(substring, replacement string) int {
replacements := 0
index := 0
for index != -1 {
index = buffer.FindAndReplaceSubstring(substring, replacement, index)
if index != -1 {
replacements++
}
if index == 0 {
index++
}
}
return replacements
}
func GetOpenFileBuffer(filename string) *Buffer {
// Replace tilde with home directory
if filename != "~" && strings.HasPrefix(filename, "~/") {
+264 -15
View File
@@ -18,17 +18,37 @@ var commands = make(map[string]*Command)
func initCommands() {
// Setup commands
cutCmd := Command{
cmd: "cut",
run: func(window *Window, args ...string) {
// Cut text from buffer
copiedText, copyingMethod := window.CurrentBuffer.CutText(window)
// Put cut text to clipboard
window.Clipboard = copiedText
// Send appropriate message and remove text depending on copying method
if copyingMethod == 0 {
PrintMessage(window, "Copied line to clipboard.")
} else {
PrintMessage(window, "Copied selection to clipboard.")
}
},
}
copyCmd := Command{
cmd: "copy",
run: func(window *Window, args ...string) {
if window.CurrentBuffer.Selection == nil {
// Copy line
_, line := window.GetCursorPos2D()
window.Clipboard = strings.SplitAfter(window.CurrentBuffer.Contents, "\n")[line]
// Copy text from buffer
copiedText, copyingMethod := window.CurrentBuffer.CopyText()
// Put copied text to clipboard
window.Clipboard = copiedText
// Send appropriate message depending on copying method
if copyingMethod == 0 {
PrintMessage(window, "Copied line to clipboard.")
} else {
// Copy selection
window.Clipboard = window.CurrentBuffer.GetSelectedText()
PrintMessage(window, "Copied selection to clipboard.")
}
},
@@ -37,16 +57,10 @@ func initCommands() {
pasteCmd := Command{
cmd: "paste",
run: func(window *Window, args ...string) {
str := window.CurrentBuffer.Contents
index := window.CurrentBuffer.CursorPos
if index == len(str) {
str += window.Clipboard
} else {
str = str[:index] + window.Clipboard + str[index:]
if window.Clipboard != "" {
window.CurrentBuffer.PasteText(window, window.Clipboard)
PrintMessage(window, "Pasted text to buffer.")
}
window.CurrentBuffer.Contents = str
window.SetCursorPos(window.CurrentBuffer.CursorPos + len(window.Clipboard))
},
}
@@ -133,6 +147,132 @@ func initCommands() {
},
}
findCmd := Command{
cmd: "find",
run: func(window *Window, args ...string) {
if len(args) >= 1 {
input := args[0]
if input == "" {
return
}
pos := window.CurrentBuffer.FindSubstring(input, window.CurrentBuffer.CursorPos)
if pos >= 0 {
window.SetCursorPos(pos)
PrintMessage(window, "Match found.")
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", input))
}
return
}
inputChannel := RequestInput(window, "Substring to search for:", "")
go func() {
input := <-inputChannel
if input == "" {
return
}
pos := window.CurrentBuffer.FindSubstring(input, window.CurrentBuffer.CursorPos)
if pos >= 0 {
window.SetCursorPos(pos)
PrintMessage(window, "Match found.")
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", input))
}
}()
},
}
replaceCmd := Command{
cmd: "replace",
run: func(window *Window, args ...string) {
if len(args) >= 2 {
findStr := args[0]
replaceStr := args[1]
if findStr == "" {
return
}
pos := window.CurrentBuffer.FindAndReplaceSubstring(findStr, replaceStr, window.CurrentBuffer.CursorPos)
if pos >= 0 {
window.SetCursorPos(pos)
PrintMessage(window, "Match replaced successfully.")
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
}
return
}
go func() {
inputChannel := RequestInput(window, "Substring to search for:", "")
findStr := <-inputChannel
if findStr == "" {
return
}
inputChannel = RequestInput(window, "String to replace with:", "")
replaceStr := <-inputChannel
pos := window.CurrentBuffer.FindAndReplaceSubstring(findStr, replaceStr, window.CurrentBuffer.CursorPos)
if pos >= 0 {
window.SetCursorPos(pos)
PrintMessage(window, "Match replaced successfully.")
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
}
}()
},
}
replaceAllCmd := Command{
cmd: "replace-all",
run: func(window *Window, args ...string) {
if len(args) >= 2 {
findStr := args[0]
replaceStr := args[1]
if findStr == "" {
return
}
replacements := window.CurrentBuffer.FindAndReplaceAll(findStr, replaceStr)
if replacements > 0 {
window.SetCursorPos(window.CurrentBuffer.CursorPos)
PrintMessage(window, fmt.Sprintf("Replaced all %d matches successfully.", replacements))
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
}
return
}
go func() {
inputChannel := RequestInput(window, "Substring to search for:", "")
findStr := <-inputChannel
if findStr == "" {
return
}
inputChannel = RequestInput(window, "String to replace with:", "")
replaceStr := <-inputChannel
replacements := window.CurrentBuffer.FindAndReplaceAll(findStr, replaceStr)
if replacements > 0 {
window.SetCursorPos(window.CurrentBuffer.CursorPos)
PrintMessage(window, fmt.Sprintf("Replaced all %d matches successfully.", replacements))
} else {
PrintMessage(window, fmt.Sprintf("'%s' not found in buffer!", findStr))
}
}()
},
}
prevBufferCmd := Command{
cmd: "prev-buffer",
run: func(window *Window, args ...string) {
@@ -206,6 +346,66 @@ func initCommands() {
},
}
toggleTopBar := Command{
cmd: "toggle-top-bar",
run: func(window *Window, args ...string) {
window.ShowTopMenu = !window.ShowTopMenu
},
}
toggleLineIndex := Command{
cmd: "toggle-line-index",
run: func(window *Window, args ...string) {
window.ShowLineIndex = !window.ShowLineIndex
},
}
setStyleCmd := Command{
cmd: "set-style",
run: func(window *Window, args ...string) {
if len(args) >= 1 {
input := args[0]
if input == "" {
return
}
if _, ok := AvailableStyles[input]; !ok {
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
return
}
if ok := SetCurrentStyle(window.screen, input); ok {
PrintMessage(window, fmt.Sprintf("Setting style to '%s'", input))
} else {
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
}
return
}
inputChannel := RequestInput(window, "Style to switch to:", "")
go func() {
input := <-inputChannel
if input == "" {
return
}
if _, ok := AvailableStyles[input]; !ok {
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
return
}
if ok := SetCurrentStyle(window.screen, input); ok {
PrintMessage(window, fmt.Sprintf("Setting style to '%s'", input))
} else {
PrintMessage(window, fmt.Sprintf("Could not set style to '%s'", input))
}
}()
},
}
menuFileCmd := Command{
cmd: "menu-file",
run: func(window *Window, args ...string) {
@@ -250,20 +450,69 @@ func initCommands() {
},
}
executeCmd := Command{
cmd: "execute",
run: func(window *Window, args ...string) {
inputChannel := RequestInput(window, "Run:", "")
go func() {
input := strings.TrimSpace(<-inputChannel)
if input == "" {
return
}
var arguments []string
builder := &strings.Builder{}
quoted := false
for _, r := range input {
if r == '"' {
quoted = !quoted
} else if !quoted && r == ' ' {
arguments = append(arguments, builder.String())
builder.Reset()
} else {
builder.WriteRune(r)
}
}
if builder.Len() > 0 {
arguments = append(arguments, builder.String())
}
window.CursorMode = CursorModeBuffer
if len(arguments) == 1 {
RunCommand(window, arguments[0])
} else {
RunCommand(window, arguments[0], arguments[1:]...)
}
}()
},
}
// Register commands
commands["cut"] = &cutCmd
commands["copy"] = &copyCmd
commands["paste"] = &pasteCmd
commands["save"] = &saveCmd
commands["open"] = &openCmd
commands["reload"] = &reloadCmd
commands["find"] = &findCmd
commands["replace"] = &replaceCmd
commands["replace-all"] = &replaceAllCmd
commands["prev-buffer"] = &prevBufferCmd
commands["next-buffer"] = &nextBufferCmd
commands["new-buffer"] = &newBufferCmd
commands["close-buffer"] = &closeBufferCmd
commands["toggle-top-bar"] = &toggleTopBar
commands["toggle-line-index"] = &toggleLineIndex
commands["set-style"] = &setStyleCmd
commands["menu-file"] = &menuFileCmd
commands["menu-edit"] = &menuEditCmd
commands["menu-buffers"] = &menuBuffersCmd
commands["quit"] = &quitCmd
commands["execute"] = &executeCmd
}
func RunCommand(window *Window, cmd string, args ...string) bool {
+4 -2
View File
@@ -12,6 +12,7 @@ type TyperConfig struct {
FallbackStyle string `yaml:"fallback_style,omitempty"`
ShowTopMenu bool `yaml:"show_top_menu,omitempty"`
ShowLineIndex bool `yaml:"show_line_index,omitempty"`
ExtendLineIndex bool `yaml:"extend_line_index,omitempty"`
BufferInfoMessage string `yaml:"buffer_info_message,omitempty"`
TabIndentation int `yaml:"tab_indentation,omitempty"`
}
@@ -24,6 +25,7 @@ func readConfig() {
FallbackStyle: "default-fallback",
ShowTopMenu: true,
ShowLineIndex: true,
ExtendLineIndex: false,
BufferInfoMessage: "File: %f Cursor: (%x, %y, %p) Chars: %c",
TabIndentation: 4,
}
@@ -42,8 +44,8 @@ func readConfig() {
if err != nil {
log.Fatalf("Could not unmarshal config.yml: %s", err)
}
} else if _, err := os.Stat("/etc/typer/config.yml"); err == nil {
reader, err := os.Open("/etc/typer/config.yml")
} else if _, err := os.Stat(path.Join(sysconfdir, "typer/config.yml")); err == nil {
reader, err := os.Open(path.Join(sysconfdir, "typer/config.yml"))
if err != nil {
log.Fatalf("Could not read config.yml: %s", err)
}
+1 -1
View File
@@ -18,7 +18,7 @@ func RequestInput(window *Window, text string, defaultInput string) chan string
request := &TyperInputRequest{
Text: text,
input: defaultInput,
cursorPos: 0,
cursorPos: len(defaultInput),
inputChannel: make(chan string),
}
+2 -2
View File
@@ -40,8 +40,8 @@ func readKeybindings() {
if err != nil {
log.Fatalf("Could not unmarshal keybindings.yml: %s", err)
}
} else if _, err := os.Stat("/etc/typer/keybindings.yml"); err == nil {
reader, err := os.Open("/etc/typer/keybindings.yml")
} else if _, err := os.Stat(path.Join(sysconfdir, "typer/keybindings.yml")); err == nil {
reader, err := os.Open(path.Join(sysconfdir, "typer/keybindings.yml"))
if err != nil {
log.Fatalf("Could not read keybindings.yml: %s", err)
}
+16 -9
View File
@@ -12,16 +12,22 @@ func drawLineIndex(window *Window) {
lineIndexStyle := tcell.StyleDefault.Background(CurrentStyle.LineIndexBg).Foreground(CurrentStyle.LineIndexFg)
_, sizeY := screen.Size()
y := 0
if window.ShowTopMenu {
y = 1
}
lineIndexSize := getLineIndexSize(window)
for lineIndex := 1 + buffer.OffsetY; lineIndex <= strings.Count(buffer.Contents, "\n")+1 && lineIndex < sizeY+buffer.OffsetY; lineIndex++ {
_, bufferY1, _, bufferY2 := window.GetTextAreaDimensions()
lineIndex := 1 + buffer.OffsetY
for y := bufferY1; y <= bufferY2; y++ {
if lineIndex > strings.Count(buffer.Contents, "\n")+1 {
if Config.ExtendLineIndex {
for x := 0; x < lineIndexSize; x++ {
screen.SetContent(x, y, ' ', nil, lineIndexStyle)
}
continue
} else {
break
}
}
for x := 0; x < lineIndexSize; x++ {
screen.SetContent(x, y, ' ', nil, lineIndexStyle)
@@ -30,7 +36,8 @@ func drawLineIndex(window *Window) {
text := strconv.Itoa(lineIndex)
drawText(screen, lineIndexSize-len(text)-1, y, lineIndexSize, y, lineIndexStyle, text)
y++
lineIndex++
}
}
+6 -1
View File
@@ -5,6 +5,8 @@ import (
"os"
)
var sysconfdir = "/etc/"
func main() {
// Read config
readConfig()
@@ -38,8 +40,11 @@ func main() {
}
}
for window.screen != nil {
for !window.closed {
window.Draw()
window.ProcessEvents()
}
window.screen.Fini()
window.screen = nil
}
+32 -28
View File
@@ -46,8 +46,29 @@ type typerStyleYaml struct {
Colors map[string]string `yaml:"colors"`
}
var FallbackStyle = TyperStyle{
Name: "fallback",
Description: "Fallback style",
StyleType: "8-color",
BufferAreaBg: tcell.ColorBlack,
BufferAreaFg: tcell.ColorWhite,
BufferAreaSel: tcell.ColorNavy,
TopMenuBg: tcell.ColorWhite,
TopMenuFg: tcell.ColorBlack,
DropdownBg: tcell.ColorWhite,
DropdownFg: tcell.ColorBlack,
DropdownSel: tcell.ColorNavy,
LineIndexBg: tcell.ColorWhite,
LineIndexFg: tcell.ColorBlack,
MessageBarBg: tcell.ColorWhite,
MessageBarFg: tcell.ColorBlack,
InputBarBg: tcell.ColorWhite,
InputBarFg: tcell.ColorBlack,
}
var AvailableStyles = make(map[string]TyperStyle)
var CurrentStyle TyperStyle
var CurrentStyle = FallbackStyle
func readStyles() {
homeDir, err := os.UserHomeDir()
@@ -73,14 +94,14 @@ func readStyles() {
}
}
}
if stat, err := os.Stat("/etc/typer/styles/"); err == nil && stat.IsDir() {
entries, err := os.ReadDir("/etc/typer/styles/")
if stat, err := os.Stat(path.Join(sysconfdir, "typer/styles/")); err == nil && stat.IsDir() {
entries, err := os.ReadDir(path.Join(sysconfdir, "typer/styles/"))
if err != nil {
log.Fatalf("Could not read user style directory: %s", err)
}
for _, entry := range entries {
entryPath := path.Join("/etc/typer/styles/", entry.Name())
entryPath := path.Join(path.Join(sysconfdir, "typer/styles/"), entry.Name())
style, err := readStyleYamlFile(entryPath)
if err != nil {
log.Fatalf("Could not read style file (%s): %s", entryPath, err)
@@ -145,7 +166,7 @@ func readStyleYamlFile(filepath string) (TyperStyle, error) {
return style, nil
}
func SetCurrentStyle(screen tcell.Screen) {
func SetCurrentStyle(screen tcell.Screen, styleName string) bool {
availableTypes := make([]string, 1)
availableTypes[0] = "8-color"
if screen.Colors() >= 16 {
@@ -158,30 +179,13 @@ func SetCurrentStyle(screen tcell.Screen) {
availableTypes = append(availableTypes, "true-color")
}
if style, ok := AvailableStyles[Config.SelectedStyle]; ok && slices.Index(availableTypes, style.StyleType) != -1 {
if style, ok := AvailableStyles[styleName]; ok && slices.Index(availableTypes, style.StyleType) != -1 {
CurrentStyle = style
} else if style, ok := AvailableStyles[Config.FallbackStyle]; ok {
CurrentStyle = style
} else {
CurrentStyle = TyperStyle{
Name: "fallback",
Description: "Fallback style",
StyleType: "8-color",
BufferAreaBg: tcell.ColorBlack,
BufferAreaFg: tcell.ColorWhite,
BufferAreaSel: tcell.ColorNavy,
TopMenuBg: tcell.ColorWhite,
TopMenuFg: tcell.ColorBlack,
DropdownBg: tcell.ColorWhite,
DropdownFg: tcell.ColorBlack,
DropdownSel: tcell.ColorNavy,
LineIndexBg: tcell.ColorWhite,
LineIndexFg: tcell.ColorBlack,
MessageBarBg: tcell.ColorWhite,
MessageBarFg: tcell.ColorBlack,
InputBarBg: tcell.ColorWhite,
InputBarFg: tcell.ColorBlack,
}
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
screen.Sync()
return true
}
return false
}
+7 -3
View File
@@ -56,11 +56,13 @@ func initTopMenu() {
y++
}
d := CreateDropdownMenu([]string{"Copy", "Paste"}, 0, y, 0, func(i int) {
d := CreateDropdownMenu([]string{"Cut", "Copy", "Paste"}, 0, y, 0, func(i int) {
switch i {
case 0:
RunCommand(window, "copy")
RunCommand(window, "cut")
case 1:
RunCommand(window, "copy")
case 2:
RunCommand(window, "paste")
}
ClearDropdowns()
@@ -123,7 +125,9 @@ func drawTopMenu(window *Window) {
// Draw buffer info
bufferInfoMsg := getBufferInfoMsg(window)
drawText(screen, sizeX-len(bufferInfoMsg)-1, 0, sizeX-1, 0, topMenuStyle, bufferInfoMsg)
if sizeX-len(bufferInfoMsg)-1 > currentX+2 {
drawText(screen, sizeX-len(bufferInfoMsg)-1, 0, sizeX-1, 0, topMenuStyle, bufferInfoMsg)
}
}
func getBufferInfoMsg(window *Window) string {
+23 -10
View File
@@ -36,6 +36,8 @@ type Window struct {
CurrentBuffer *Buffer
screen tcell.Screen
closed bool
}
var mouseHeld = false
@@ -70,16 +72,22 @@ func CreateWindow() (*Window, error) {
log.Fatalf("Failed to initialize screen: %s", err)
}
// Set screen style
SetCurrentStyle(screen)
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
// Enable mouse
screen.EnableMouse()
// Set window screen field
window.screen = screen
// Try to set screen style to selected one
if ok := SetCurrentStyle(screen, Config.SelectedStyle); !ok {
// Try to set screen style to selected fallback one
if ok := SetCurrentStyle(screen, Config.FallbackStyle); !ok {
// Use hard-coded fallback style
screen.SetStyle(tcell.StyleDefault.Foreground(CurrentStyle.BufferAreaFg).Background(CurrentStyle.BufferAreaBg))
PrintMessage(&window, "Could not set style either to selected one nor to fallback one!")
}
}
// Initialize top menu
initTopMenu()
@@ -126,7 +134,9 @@ func (window *Window) Draw() {
// Update screen
window.screen.Show()
}
func (window *Window) ProcessEvents() {
// Poll event
ev := window.screen.PollEvent()
@@ -136,13 +146,13 @@ func (window *Window) Draw() {
window.screen.Sync()
window.SyncBufferOffset()
case *tcell.EventMouse:
window.mouseInput(ev)
window.handleMouseInput(ev)
case *tcell.EventKey:
window.input(ev)
window.handleKeyInput(ev)
}
}
func (window *Window) input(ev *tcell.EventKey) {
func (window *Window) handleKeyInput(ev *tcell.EventKey) {
if ev.Key() == tcell.KeyRight { // Navigation Keys
if window.CursorMode == CursorModeBuffer {
// Get original cursor position
@@ -515,7 +525,7 @@ func (window *Window) input(ev *tcell.EventKey) {
}
}
func (window *Window) mouseInput(ev *tcell.EventMouse) {
func (window *Window) handleMouseInput(ev *tcell.EventMouse) {
mouseX, mouseY := ev.Position()
// Left click was pressed
@@ -635,8 +645,11 @@ func (window *Window) mouseInput(ev *tcell.EventMouse) {
}
func (window *Window) Close() {
window.screen.Fini()
window.screen = nil
window.closed = true
err := window.screen.PostEvent(tcell.NewEventInterrupt(nil))
if err != nil {
return
}
}
func (window *Window) GetTextAreaDimensions() (int, int, int, int) {