Merge pull request #40 from liamg/url-detection

added url detection and clicking
This commit is contained in:
Liam Galvin 2018-10-24 16:30:15 +01:00 committed by GitHub
commit 28735e53db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 6 deletions

View File

@ -64,6 +64,7 @@ Ensure you have your latest graphics card drivers installed before use.
| Config file | ✔ |
| Scrolling | ✔ |
| Mouse interaction | ✔ |
| Clickable URLs | ✔ |
| Sweet render effects | |
## Keyboard Shortcuts

View File

@ -2,6 +2,7 @@ package buffer
import (
"fmt"
"net/url"
"time"
)
@ -47,6 +48,45 @@ func NewBuffer(viewCols uint16, viewLines uint16, attr CellAttributes) *Buffer {
return b
}
func (buffer *Buffer) GetURLAtPosition(col uint16, row uint16) string {
cell := buffer.GetCell(col, row)
if cell == nil || cell.Rune() == 0x00 {
return ""
}
candidate := ""
for i := col; i >= 0; i-- {
cell := buffer.GetCell(i, row)
if cell == nil {
break
}
if isRuneURLSelectionMarker(cell.Rune()) {
break
}
candidate = fmt.Sprintf("%c%s", cell.Rune(), candidate)
}
for i := col + 1; i < buffer.viewWidth; i++ {
cell := buffer.GetCell(i, row)
if cell == nil {
break
}
if isRuneURLSelectionMarker(cell.Rune()) {
break
}
candidate = fmt.Sprintf("%s%c", candidate, cell.Rune())
}
// check if url
_, err := url.ParseRequestURI(candidate)
if err != nil {
return ""
}
return candidate
}
func (buffer *Buffer) SelectWordAtPosition(col uint16, row uint16) {
cell := buffer.GetCell(col, row)
@ -62,7 +102,7 @@ func (buffer *Buffer) SelectWordAtPosition(col uint16, row uint16) {
if cell == nil {
break
}
if isRuneSelectionMarker(cell.Rune()) {
if isRuneWordSelectionMarker(cell.Rune()) {
break
}
start = i
@ -73,7 +113,7 @@ func (buffer *Buffer) SelectWordAtPosition(col uint16, row uint16) {
if cell == nil {
break
}
if isRuneSelectionMarker(cell.Rune()) {
if isRuneWordSelectionMarker(cell.Rune()) {
break
}
end = i
@ -92,7 +132,7 @@ func (buffer *Buffer) SelectWordAtPosition(col uint16, row uint16) {
}
// bounds for word selection
func isRuneSelectionMarker(r rune) bool {
func isRuneWordSelectionMarker(r rune) bool {
switch r {
case ',', ' ', ':', ';', 0, '\'', '"', '[', ']', '(', ')', '{', '}':
return true
@ -101,6 +141,15 @@ func isRuneSelectionMarker(r rune) bool {
return false
}
func isRuneURLSelectionMarker(r rune) bool {
switch r {
case ' ', 0, '\'', '"', '{', '}':
return true
}
return false
}
func (buffer *Buffer) GetSelectedText() string {
if buffer.selectionStart == nil || buffer.selectionEnd == nil {
return ""

View File

@ -3,6 +3,8 @@ package gui
import (
"fmt"
"math"
"os/exec"
"runtime"
"github.com/go-gl/glfw/v3.2/glfw"
"github.com/liamg/aminal/terminal"
@ -10,12 +12,34 @@ import (
func (gui *GUI) mouseMoveCallback(w *glfw.Window, xpos float64, ypos float64) {
px, py := w.GetCursorPos()
x := uint16(math.Floor((px - float64(gui.renderer.areaX)) / float64(gui.renderer.CellWidth())))
y := uint16(math.Floor((py - float64(gui.renderer.areaY)) / float64(gui.renderer.CellHeight())))
if gui.mouseDown {
px, py := w.GetCursorPos()
x := uint16(math.Floor((px - float64(gui.renderer.areaX)) / float64(gui.renderer.CellWidth())))
y := uint16(math.Floor((py - float64(gui.renderer.areaY)) / float64(gui.renderer.CellHeight())))
gui.terminal.ActiveBuffer().EndSelection(x, y, false)
}
if url := gui.terminal.ActiveBuffer().GetURLAtPosition(x, y); url != "" {
w.SetCursor(glfw.CreateStandardCursor(glfw.HandCursor))
} else {
w.SetCursor(glfw.CreateStandardCursor(glfw.ArrowCursor))
}
}
func (gui *GUI) launchTarget(target string) {
cmd := "xdg-open"
switch runtime.GOOS {
case "darwin":
cmd = "open"
case "windows":
cmd = "start"
}
if err := exec.Command(cmd, target).Run(); err != nil {
gui.logger.Errorf("Failed to launch external command %s: %s", cmd, err)
}
}
func (gui *GUI) mouseButtonCallback(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
@ -33,6 +57,9 @@ func (gui *GUI) mouseButtonCallback(w *glfw.Window, button glfw.MouseButton, act
} else if action == glfw.Release {
gui.mouseDown = false
gui.terminal.ActiveBuffer().EndSelection(x, y, true)
if url := gui.terminal.ActiveBuffer().GetURLAtPosition(x, y); url != "" {
go gui.launchTarget(url)
}
}
// https://www.xfree86.org/4.8.0/ctlseqs.html