mirror of https://github.com/liamg/aminal.git
Merge branch 'add-scrollbar' of https://github.com/liamg/aminal into add-scrollbar
This commit is contained in:
commit
283a648fcb
|
@ -34,7 +34,7 @@ env:
|
|||
global:
|
||||
- secure: "pdRpTOGQSUgbC9tK37voxUYJHMWDPJEmdMhNBsljpP9VnxxbR6JEFwvOQEmUHGlsYv8jma6a17jE60ngVQk8QP12cPh48i2bdbVgym/zTUOKFawCtPAzs8i7evh0di5eZ3uoyc42kG4skc+ePuVHbXC8jDxwaPpMqSHD7QyQc1/6ckI9LLkyWUqhnJJXkVwhmI74Aa1Im6QhywAWFMeTBRRL02cwr6k7VKSYOn6yrtzJRCALFGpZ/n58lPrpDxN7W8o+HRQP89wIDy8FyNeEPdmqGFNfMHDvI3oJRN4dGC4H9EkKf/iGuNJia1Bs+MgaG9kKlMHsI6Fkh5uw9KNTvC1llx43VRQJzm26cn1CpRxxRtF4F8lqkpY4tHjxxCitV+98ddW8jdmQYyx+LeueC5wqlO9g2M5L3oXsGMqZ++mDRDa8oQoQAVUSVtimeO8ODXFuVNR8TlupP0Cthgucil63VUZfAD8EHc2zpRSFxfYByDH53uMEinn20uovL6W42fqgboC43HOnR6aVfSANPsBFDlcpZFa2BY5RkcKyYdaLkucy0DKJ946UDfhOu6FNm0GPHq5HcgWkLojNF0dEFgG6J+SGQGiPjxTlHP/zoe61qMlWu+fYRXQnKWZN5Kk0T1TbAk6pKSE6wRLG8ddxvMg+eVpGLT+gAvQdrrkMFvs="
|
||||
before_deploy:
|
||||
- export CHANGELOG=$(git log $(git describe --abbrev=0 --tags "${TRAVIS_TAG}^")..$TRAVIS_TAG --pretty=format:'<li> <a href="http://github.com/liamg/aminal/commit/%H">view commit •</a> %s</li> ' --reverse | while read line; do echo -n "$line "; done)
|
||||
- export CHANGELOG=$(git log $(git describe --abbrev=0 --tags "${TRAVIS_TAG}^")..$TRAVIS_TAG --pretty=format:'<li> <a href="http://github.com/liamg/aminal/commit/%H">view commit •</a> %s</li>%n ' --reverse | while read line; do echo -n "$line "; done)
|
||||
deploy:
|
||||
- provider: releases
|
||||
skip_cleanup: true
|
||||
|
|
|
@ -10,11 +10,15 @@ import (
|
|||
)
|
||||
|
||||
type SelectionMode int
|
||||
type SelectionRegionMode int
|
||||
|
||||
const (
|
||||
SelectionChar SelectionMode = iota // char-by-char selection
|
||||
SelectionWord SelectionMode = iota // by word selection
|
||||
SelectionLine SelectionMode = iota // whole line selection
|
||||
|
||||
SelectionRegionNormal SelectionRegionMode = iota
|
||||
SelectionRegionRectangular
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
|
@ -160,12 +164,38 @@ func isRuneURLSelectionMarker(r rune) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (buffer *Buffer) GetSelectedText() string {
|
||||
start, end := buffer.getActualSelection()
|
||||
func (buffer *Buffer) getRectangleText(start *Position, end *Position) string {
|
||||
var builder strings.Builder
|
||||
builder.Grow((end.Col - start.Col + 2) * (end.Line - start.Line + 1)) // reserve space to minimize allocations
|
||||
|
||||
for row := start.Line; row <= end.Line; row++ {
|
||||
for col := start.Col; col <= end.Col; col++ {
|
||||
if row < len(buffer.lines) && col < len(buffer.lines[row].cells) {
|
||||
r := buffer.lines[row].cells[col].Rune()
|
||||
if r == 0x00 {
|
||||
r = ' '
|
||||
}
|
||||
builder.WriteRune(r)
|
||||
} else {
|
||||
builder.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
builder.WriteString("\n")
|
||||
}
|
||||
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func (buffer *Buffer) GetSelectedText(selectionRegionMode SelectionRegionMode) string {
|
||||
start, end := buffer.getActualSelection(selectionRegionMode)
|
||||
if start == nil || end == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if selectionRegionMode == SelectionRegionRectangular {
|
||||
return buffer.getRectangleText(start, end)
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
builder.Grow(int(buffer.terminalState.viewWidth) * (end.Line - start.Line + 1)) // reserve space to minimize allocations
|
||||
|
||||
|
@ -258,7 +288,7 @@ func (buffer *Buffer) ClearSelection() {
|
|||
buffer.emitDisplayChange()
|
||||
}
|
||||
|
||||
func (buffer *Buffer) getActualSelection() (*Position, *Position) {
|
||||
func (buffer *Buffer) getActualSelection(selectionRegionMode SelectionRegionMode) (*Position, *Position) {
|
||||
if buffer.selectionStart == nil || buffer.selectionEnd == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -266,7 +296,23 @@ func (buffer *Buffer) getActualSelection() (*Position, *Position) {
|
|||
start := &Position{}
|
||||
end := &Position{}
|
||||
|
||||
if comparePositions(buffer.selectionStart, buffer.selectionEnd) >= 0 {
|
||||
if selectionRegionMode == SelectionRegionRectangular {
|
||||
if buffer.selectionStart.Col > buffer.selectionEnd.Col {
|
||||
start.Col = buffer.selectionEnd.Col
|
||||
end.Col = buffer.selectionStart.Col
|
||||
} else {
|
||||
start.Col = buffer.selectionStart.Col
|
||||
end.Col = buffer.selectionEnd.Col
|
||||
}
|
||||
if buffer.selectionStart.Line > buffer.selectionEnd.Line {
|
||||
start.Line = buffer.selectionEnd.Line
|
||||
end.Line = buffer.selectionStart.Line
|
||||
} else {
|
||||
start.Line = buffer.selectionStart.Line
|
||||
end.Line = buffer.selectionEnd.Line
|
||||
}
|
||||
return start, end
|
||||
} else if comparePositions(buffer.selectionStart, buffer.selectionEnd) >= 0 {
|
||||
start.Col = buffer.selectionStart.Col
|
||||
start.Line = buffer.selectionStart.Line
|
||||
|
||||
|
@ -306,14 +352,18 @@ func (buffer *Buffer) getActualSelection() (*Position, *Position) {
|
|||
return start, end
|
||||
}
|
||||
|
||||
func (buffer *Buffer) InSelection(col uint16, row uint16) bool {
|
||||
start, end := buffer.getActualSelection()
|
||||
func (buffer *Buffer) InSelection(col uint16, row uint16, selectionRegionMode SelectionRegionMode) bool {
|
||||
start, end := buffer.getActualSelection(selectionRegionMode)
|
||||
if start == nil || end == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
rawY := int(buffer.convertViewLineToRawLine(row) - uint64(buffer.terminalState.scrollLinesFromBottom))
|
||||
|
||||
if selectionRegionMode == SelectionRegionRectangular {
|
||||
return rawY >= start.Line && rawY <= end.Line && int(col) >= start.Col && int(col) <= end.Col
|
||||
}
|
||||
|
||||
return (rawY > start.Line || (rawY == start.Line && int(col) >= start.Col)) &&
|
||||
(rawY < end.Line || (rawY == end.Line && int(col) <= end.Col))
|
||||
}
|
||||
|
|
|
@ -659,7 +659,7 @@ func TestSelectingChars(t *testing.T) {
|
|||
b.StartSelection(2, 0, SelectionChar)
|
||||
b.ExtendSelection(4, 1, true)
|
||||
|
||||
assert.Equal(t, "e quick brown\nfox j", b.GetSelectedText())
|
||||
assert.Equal(t, "e quick brown\nfox j", b.GetSelectedText(SelectionRegionNormal))
|
||||
}
|
||||
|
||||
func TestSelectingWordsDown(t *testing.T) {
|
||||
|
@ -668,7 +668,7 @@ func TestSelectingWordsDown(t *testing.T) {
|
|||
b.StartSelection(6, 1, SelectionWord)
|
||||
b.ExtendSelection(5, 2, true)
|
||||
|
||||
assert.Equal(t, "jumps over\nthe lazy", b.GetSelectedText())
|
||||
assert.Equal(t, "jumps over\nthe lazy", b.GetSelectedText(SelectionRegionNormal))
|
||||
}
|
||||
|
||||
func TestSelectingWordsUp(t *testing.T) {
|
||||
|
@ -677,7 +677,7 @@ func TestSelectingWordsUp(t *testing.T) {
|
|||
b.StartSelection(5, 2, SelectionWord)
|
||||
b.ExtendSelection(6, 1, true)
|
||||
|
||||
assert.Equal(t, "jumps over\nthe lazy", b.GetSelectedText())
|
||||
assert.Equal(t, "jumps over\nthe lazy", b.GetSelectedText(SelectionRegionNormal))
|
||||
}
|
||||
|
||||
func TestSelectingLinesDown(t *testing.T) {
|
||||
|
@ -686,7 +686,7 @@ func TestSelectingLinesDown(t *testing.T) {
|
|||
b.StartSelection(6, 1, SelectionLine)
|
||||
b.ExtendSelection(4, 2, true)
|
||||
|
||||
assert.Equal(t, "fox jumps over\nthe lazy dog", b.GetSelectedText())
|
||||
assert.Equal(t, "fox jumps over\nthe lazy dog", b.GetSelectedText(SelectionRegionNormal))
|
||||
}
|
||||
|
||||
func TestSelectingLineUp(t *testing.T) {
|
||||
|
@ -695,7 +695,7 @@ func TestSelectingLineUp(t *testing.T) {
|
|||
b.StartSelection(8, 2, SelectionLine)
|
||||
b.ExtendSelection(3, 1, true)
|
||||
|
||||
assert.Equal(t, "fox jumps over\nthe lazy dog", b.GetSelectedText())
|
||||
assert.Equal(t, "fox jumps over\nthe lazy dog", b.GetSelectedText(SelectionRegionNormal))
|
||||
}
|
||||
|
||||
func TestSelectingAfterText(t *testing.T) {
|
||||
|
@ -704,7 +704,7 @@ func TestSelectingAfterText(t *testing.T) {
|
|||
b.StartSelection(6, 3, SelectionChar)
|
||||
b.ExtendSelection(6, 3, true)
|
||||
|
||||
start, end := b.getActualSelection()
|
||||
start, end := b.getActualSelection(SelectionRegionNormal)
|
||||
|
||||
assert.Equal(t, start.Col, 0)
|
||||
assert.Equal(t, start.Line, 3)
|
||||
|
|
|
@ -8,7 +8,7 @@ if [ -z "$MY_TAG" ] ; then
|
|||
git config --global user.email "travis@travis-ci.org"
|
||||
git config --global user.name "Travis CI"
|
||||
|
||||
NEW_TAG="Nightly-$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)"
|
||||
NEW_TAG="Nightly-$TRAVIS_BRANCH-$(date +%Y-%m-%d)-$(git rev-parse --short HEAD)"
|
||||
git tag -a $NEW_TAG -m "Nightly Build Tag $NEW_TAG"
|
||||
|
||||
echo "New generated nightly build tag: $NEW_TAG"
|
||||
|
|
|
@ -18,7 +18,7 @@ var actionMap = map[config.UserAction]func(gui *GUI){
|
|||
}
|
||||
|
||||
func actionCopy(gui *GUI) {
|
||||
selectedText := gui.terminal.ActiveBuffer().GetSelectedText()
|
||||
selectedText := gui.terminal.ActiveBuffer().GetSelectedText(gui.selectionRegionMode)
|
||||
|
||||
if selectedText != "" {
|
||||
gui.window.SetClipboardString(selectedText)
|
||||
|
@ -37,7 +37,7 @@ func actionToggleDebug(gui *GUI) {
|
|||
}
|
||||
|
||||
func actionSearchSelection(gui *GUI) {
|
||||
keywords := gui.terminal.ActiveBuffer().GetSelectedText()
|
||||
keywords := gui.terminal.ActiveBuffer().GetSelectedText(gui.selectionRegionMode)
|
||||
if keywords != "" && gui.config.SearchURL != "" && strings.Contains(gui.config.SearchURL, "$QUERY") {
|
||||
gui.launchTarget(fmt.Sprintf(strings.Replace(gui.config.SearchURL, "$QUERY", "%s", 1), url.QueryEscape(keywords)))
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ type GUI struct {
|
|||
prevMouseEventHandler mouseEventsHandler
|
||||
|
||||
internalResize bool
|
||||
selectionRegionMode buffer.SelectionRegionMode
|
||||
|
||||
vScrollbar *scrollbar
|
||||
}
|
||||
|
@ -546,7 +547,7 @@ func (gui *GUI) redraw() {
|
|||
cursor = cx == uint(x) && cy == uint(y)
|
||||
}
|
||||
|
||||
if gui.terminal.ActiveBuffer().InSelection(uint16(x), uint16(y)) {
|
||||
if gui.terminal.ActiveBuffer().InSelection(uint16(x), uint16(y), gui.selectionRegionMode) {
|
||||
colour = &gui.config.ColourScheme.Selection
|
||||
} else {
|
||||
colour = nil
|
||||
|
|
13
gui/input.go
13
gui/input.go
|
@ -5,6 +5,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/go-gl/glfw/v3.2/glfw"
|
||||
"github.com/liamg/aminal/buffer"
|
||||
)
|
||||
|
||||
// send typed runes straight through to the pty
|
||||
|
@ -44,8 +45,18 @@ func getModStr(mods glfw.ModifierKey) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
|
||||
func (gui *GUI) updateSelectionMode(mods glfw.ModifierKey) {
|
||||
mode := buffer.SelectionRegionNormal
|
||||
if modsPressed(mods, glfw.ModAlt) {
|
||||
mode = buffer.SelectionRegionRectangular
|
||||
}
|
||||
if gui.selectionRegionMode != mode {
|
||||
gui.selectionRegionMode = mode
|
||||
gui.terminal.SetDirty()
|
||||
}
|
||||
}
|
||||
|
||||
func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
|
||||
if action == glfw.Repeat || action == glfw.Press {
|
||||
|
||||
if gui.overlay != nil {
|
||||
|
|
|
@ -219,7 +219,7 @@ func (gui *GUI) mouseButtonCallback(g *GUI, button glfw.MouseButton, action glfw
|
|||
gui.mouseDown = true
|
||||
|
||||
if gui.terminal.GetMouseMode() != terminal.MouseModeButtonEvent {
|
||||
gui.handleSelectionButtonPress(x, y)
|
||||
gui.handleSelectionButtonPress(x, y, mod)
|
||||
}
|
||||
} else if action == glfw.Release {
|
||||
gui.mouseDown = false
|
||||
|
@ -334,9 +334,10 @@ func (gui *GUI) cursorEnterCallback(g *GUI, entered bool) {
|
|||
// empty, just to conform to the mouseEventsHandler interface
|
||||
}
|
||||
|
||||
func (gui *GUI) handleSelectionButtonPress(x uint16, y uint16) {
|
||||
func (gui *GUI) handleSelectionButtonPress(x uint16, y uint16, mod glfw.ModifierKey) {
|
||||
activeBuffer := gui.terminal.ActiveBuffer()
|
||||
clickCount := gui.updateLeftClickCount(x, y)
|
||||
gui.updateSelectionMode(mod)
|
||||
switch clickCount {
|
||||
case 1:
|
||||
activeBuffer.StartSelection(x, y, buffer.SelectionChar)
|
||||
|
@ -361,7 +362,7 @@ func (gui *GUI) handleSelectionButtonRelease(x uint16, y uint16) {
|
|||
// Do copy to clipboard *or* open URL, but not both.
|
||||
handled := false
|
||||
if gui.config.CopyAndPasteWithMouse {
|
||||
selectedText := activeBuffer.GetSelectedText()
|
||||
selectedText := activeBuffer.GetSelectedText(gui.selectionRegionMode)
|
||||
if selectedText != "" {
|
||||
gui.window.SetClipboardString(selectedText)
|
||||
handled = true
|
||||
|
|
|
@ -146,14 +146,7 @@ func TestScreenFeatures(t *testing.T) {
|
|||
validateScreen("test-screen-features-8.png")
|
||||
validateScreen("test-screen-features-9.png")
|
||||
validateScreen("test-screen-features-10.png")
|
||||
|
||||
// 11th screen test is not passing https://github.com/liamg/aminal/issues/207
|
||||
//g.Screenshot("vttest/test-screen-features-11.png")
|
||||
//compareImages("vttest/test-screen-features-11.png", "vttest/test-screen-features-11.png")
|
||||
|
||||
enter(term)
|
||||
sleep()
|
||||
|
||||
validateScreen("test-screen-features-11.png")
|
||||
validateScreen("test-screen-features-12.png")
|
||||
validateScreen("test-screen-features-13.png")
|
||||
validateScreen("test-screen-features-14.png")
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"fmt"
|
||||
"github.com/MaxRis/w32"
|
||||
)
|
||||
|
||||
|
@ -135,15 +136,20 @@ func (pty *winConPty) Close() error {
|
|||
|
||||
func (pty *winConPty) CreateGuestProcess(imagePath string) (Process, error) {
|
||||
process, err := createPtyChildProcess(imagePath, pty.hcon)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
setupChildConsole(C.DWORD(process.processID), C.STD_OUTPUT_HANDLE, C.ENABLE_PROCESSED_OUTPUT|C.ENABLE_WRAP_AT_EOL_OUTPUT)
|
||||
err = setupChildConsole(C.DWORD(process.processID), C.STD_OUTPUT_HANDLE, C.ENABLE_PROCESSED_OUTPUT|C.ENABLE_WRAP_AT_EOL_OUTPUT)
|
||||
if err != nil {
|
||||
process.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return process, err
|
||||
}
|
||||
|
||||
func setupChildConsole(processID C.DWORD, nStdHandle C.DWORD, mode uint) bool {
|
||||
func setupChildConsole(processID C.DWORD, nStdHandle C.DWORD, mode uint) error {
|
||||
C.FreeConsole()
|
||||
defer C.AttachConsole(^C.DWORD(0)) // attach to parent process console
|
||||
|
||||
|
@ -158,7 +164,7 @@ func setupChildConsole(processID C.DWORD, nStdHandle C.DWORD, mode uint) bool {
|
|||
}
|
||||
lastError := C.GetLastError()
|
||||
if lastError != C.ERROR_GEN_FAILURE || count <= 0 {
|
||||
return false
|
||||
return fmt.Errorf("Was not able to attach to the child prosess' console")
|
||||
}
|
||||
|
||||
time.Sleep(time.Millisecond * time.Duration(waitStepMilliSeconds))
|
||||
|
@ -169,7 +175,7 @@ func setupChildConsole(processID C.DWORD, nStdHandle C.DWORD, mode uint) bool {
|
|||
C.SetConsoleMode(h, C.DWORD(mode))
|
||||
C.FreeConsole()
|
||||
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pty *winConPty) Resize(x, y int) error {
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Loading…
Reference in New Issue