gui: B3-click on word expands to file path (acme-style)
RMB on text without selection now expands to the word at cursor using acme's isfilec character set: alphanumeric + . - + / : @ This matches acme behavior for clicking on file paths like foo.go:42
This commit is contained in:
parent
5bf29198ff
commit
b119668965
|
|
@ -250,10 +250,19 @@ Column {
|
||||||
}
|
}
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
// B3: Plumb selection (no context menu)
|
// B3: Plumb selection or word under cursor
|
||||||
|
if (!plumber.available()) {
|
||||||
|
mouse.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
var sel = mainTextEdit.selectedText
|
var sel = mainTextEdit.selectedText
|
||||||
if (sel && sel.trim() !== "" && plumber.available()) {
|
if (sel && sel.trim() !== "") {
|
||||||
plumber.plumb(sel.trim(), sessionCwd())
|
plumber.plumb(sel.trim(), sessionCwd())
|
||||||
|
} else {
|
||||||
|
// No selection - expand word at click position (acme-style)
|
||||||
|
var pos = mainTextEdit.positionAt(mouse.x, mouse.y)
|
||||||
|
var word = wordAtCursor(mainTextEdit, pos)
|
||||||
|
if (word) plumber.plumb(word, sessionCwd())
|
||||||
}
|
}
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
}
|
}
|
||||||
|
|
@ -339,6 +348,33 @@ Column {
|
||||||
return cfg ? (cfg.cwd || "") : ""
|
return cfg ? (cfg.cwd || "") : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand cursor position to surrounding word/path for plumbing
|
||||||
|
// Matches acme's isfilec: alphanumeric + . - + / : @
|
||||||
|
function wordAtCursor(textEdit, cursorPos) {
|
||||||
|
var text = textEdit.getText(0, textEdit.length)
|
||||||
|
if (cursorPos < 0 || cursorPos > text.length) return ""
|
||||||
|
|
||||||
|
// isfilec from acme: alphanumeric + . - + / : @
|
||||||
|
function isfilec(ch) {
|
||||||
|
return /[a-zA-Z0-9.\-+\/:@]/.test(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find start of word (acme also allows isaddrc chars going left)
|
||||||
|
var start = cursorPos
|
||||||
|
while (start > 0 && isfilec(text.charAt(start - 1))) {
|
||||||
|
start--
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find end of word
|
||||||
|
var end = cursorPos
|
||||||
|
while (end < text.length && isfilec(text.charAt(end))) {
|
||||||
|
end++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start === end) return ""
|
||||||
|
return text.substring(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
// Text segment component
|
// Text segment component
|
||||||
Component {
|
Component {
|
||||||
id: textComponent
|
id: textComponent
|
||||||
|
|
@ -396,10 +432,18 @@ Column {
|
||||||
}
|
}
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
// B3: Plumb selection (no context menu)
|
// B3: Plumb selection or word under cursor
|
||||||
|
if (!plumber.available()) {
|
||||||
|
mouse.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
var sel = textEdit.selectedText
|
var sel = textEdit.selectedText
|
||||||
if (sel && sel.trim() !== "" && plumber.available()) {
|
if (sel && sel.trim() !== "") {
|
||||||
plumber.plumb(sel.trim(), sessionCwd())
|
plumber.plumb(sel.trim(), sessionCwd())
|
||||||
|
} else {
|
||||||
|
var pos = textEdit.positionAt(mouse.x, mouse.y)
|
||||||
|
var word = wordAtCursor(textEdit, pos)
|
||||||
|
if (word) plumber.plumb(word, sessionCwd())
|
||||||
}
|
}
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
}
|
}
|
||||||
|
|
@ -505,10 +549,18 @@ Column {
|
||||||
if (sel && sel.trim() !== "") executeText(sel)
|
if (sel && sel.trim() !== "") executeText(sel)
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
// B3: Plumb selection (no context menu)
|
// B3: Plumb selection or word under cursor
|
||||||
|
if (!plumber.available()) {
|
||||||
|
mouse.accepted = true
|
||||||
|
return
|
||||||
|
}
|
||||||
var sel = sourceEdit.selectedText
|
var sel = sourceEdit.selectedText
|
||||||
if (sel && sel.trim() !== "" && plumber.available()) {
|
if (sel && sel.trim() !== "") {
|
||||||
plumber.plumb(sel.trim(), sessionCwd())
|
plumber.plumb(sel.trim(), sessionCwd())
|
||||||
|
} else {
|
||||||
|
var pos = sourceEdit.positionAt(mouse.x, mouse.y)
|
||||||
|
var word = wordAtCursor(sourceEdit, pos)
|
||||||
|
if (word) plumber.plumb(word, sessionCwd())
|
||||||
}
|
}
|
||||||
mouse.accepted = true
|
mouse.accepted = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,26 @@ Item {
|
||||||
return cfg ? (cfg.cwd || "") : ""
|
return cfg ? (cfg.cwd || "") : ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expand cursor position to surrounding word/path for plumbing
|
||||||
|
// Matches acme's isfilec: alphanumeric + . - + / : @
|
||||||
|
function wordAtCursor(textEdit, cursorPos) {
|
||||||
|
var text = textEdit.getText(0, textEdit.length)
|
||||||
|
if (cursorPos < 0 || cursorPos > text.length) return ""
|
||||||
|
|
||||||
|
function isfilec(ch) {
|
||||||
|
return /[a-zA-Z0-9.\-+\/:@]/.test(ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = cursorPos
|
||||||
|
while (start > 0 && isfilec(text.charAt(start - 1))) start--
|
||||||
|
|
||||||
|
var end = cursorPos
|
||||||
|
while (end < text.length && isfilec(text.charAt(end))) end++
|
||||||
|
|
||||||
|
if (start === end) return ""
|
||||||
|
return text.substring(start, end)
|
||||||
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
loadChat()
|
loadChat()
|
||||||
scrollToBottom()
|
scrollToBottom()
|
||||||
|
|
@ -503,10 +523,15 @@ Item {
|
||||||
// No selection - ignore
|
// No selection - ignore
|
||||||
}
|
}
|
||||||
} else if (mouse.button === Qt.RightButton) {
|
} else if (mouse.button === Qt.RightButton) {
|
||||||
// B3: Plumb selection (no context menu)
|
// B3: Plumb selection or word under cursor
|
||||||
|
if (!plumber.available()) return
|
||||||
var sel = promptInput.selectedText
|
var sel = promptInput.selectedText
|
||||||
if (sel && sel.trim() !== "" && plumber.available()) {
|
if (sel && sel.trim() !== "") {
|
||||||
plumber.plumb(sel.trim(), sessionCwd())
|
plumber.plumb(sel.trim(), sessionCwd())
|
||||||
|
} else {
|
||||||
|
var pos = promptInput.positionAt(mouse.x, mouse.y)
|
||||||
|
var word = wordAtCursor(promptInput, pos)
|
||||||
|
if (word) plumber.plumb(word, sessionCwd())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue