Merge branch 'add-scrollbar' of https://github.com/liamg/aminal into add-scrollbar

This commit is contained in:
nikitar020 2019-03-07 22:01:11 +07:00
commit 283a648fcb
11 changed files with 96 additions and 34 deletions

View File

@ -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 &bull;</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 &bull;</a> %s</li>%n ' --reverse | while read line; do echo -n "$line "; done)
deploy:
- provider: releases
skip_cleanup: true

View File

@ -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))
}

View File

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

View File

@ -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"

View File

@ -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)))
}

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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")

View File

@ -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