Compare commits

...

3 Commits

5 changed files with 267 additions and 3 deletions

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

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"

View File

@ -184,6 +184,62 @@ 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
@ -248,6 +304,51 @@ func (buffer *Buffer) PasteText(window *Window, text string) {
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, "~/") {

View File

@ -18,6 +18,24 @@ 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) {
@ -129,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) {
@ -348,11 +492,15 @@ func initCommands() {
}
// 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

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()