Enter починен: новая строка с сохранением отступа
- TextArea focus:true, handleEnter() с indent +4 для { [ ( : >, extra для }])], _enterHandled флаг, onTextChanged авто-отступ если \n вставлен, Keys.onReturnPressed/onEnterPressed + onPressed Tab/Backspace
- Backspace удаляет 4 пробела как один, Tab 4 пробела / Shift+Tab снятие
This commit is contained in:
@@ -276,6 +276,7 @@ Item {
|
|||||||
|
|
||||||
TextArea {
|
TextArea {
|
||||||
id: textArea
|
id: textArea
|
||||||
|
focus: true
|
||||||
placeholderText: qsTr("Начните писать…")
|
placeholderText: qsTr("Начните писать…")
|
||||||
placeholderTextColor: Theme.textFaint
|
placeholderTextColor: Theme.textFaint
|
||||||
color: Theme.editorText
|
color: Theme.editorText
|
||||||
@@ -342,7 +343,60 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property string _prevText: ""
|
||||||
|
property int _prevCursor: 0
|
||||||
|
property bool _enterHandled: false
|
||||||
onTextChanged: {
|
onTextChanged: {
|
||||||
|
// Авто-отступ при Enter: если был вставлен \n, добавляем indent (если не обработано через Keys)
|
||||||
|
if (_enterHandled) {
|
||||||
|
_enterHandled = false
|
||||||
|
_prevText = text
|
||||||
|
_prevCursor = cursorPosition
|
||||||
|
if (activeFocus && text !== documentManager.contentAt(documentManager.activeIndex)) {
|
||||||
|
editDebounce.restart()
|
||||||
|
}
|
||||||
|
if (viewMode === "live") liveDebounce.restart()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (activeFocus && _prevText.length > 0) {
|
||||||
|
const pos = cursorPosition
|
||||||
|
// Проверяем был ли вставлен один \n
|
||||||
|
if (text.length === _prevText.length + 1 && text[pos-1] === "\n") {
|
||||||
|
// Найдём отступ предыдущей строки
|
||||||
|
let lineStart = _prevText.lastIndexOf("\n", _prevCursor-1) + 1
|
||||||
|
let line = _prevText.substring(lineStart, _prevCursor)
|
||||||
|
let indent = ""
|
||||||
|
const m = line.match(/^(\s+)/)
|
||||||
|
if (m) indent = m[1]
|
||||||
|
const trimmed = line.trimEnd()
|
||||||
|
if (trimmed.endsWith("{") || trimmed.endsWith("[") || trimmed.endsWith("(") || trimmed.endsWith(":") || trimmed.endsWith(">")) {
|
||||||
|
indent += " "
|
||||||
|
}
|
||||||
|
if (indent.length > 0) {
|
||||||
|
// Вставляем indent после \n
|
||||||
|
const before = text.substring(0, pos)
|
||||||
|
const after = text.substring(pos)
|
||||||
|
// Проверяем что indent ещё не вставлен (чтобы не дублировать)
|
||||||
|
if (!after.startsWith(indent.substring(0,4))) {
|
||||||
|
const newText = before + indent + after
|
||||||
|
// Блокируем рекурсию
|
||||||
|
_prevText = newText
|
||||||
|
text = newText
|
||||||
|
cursorPosition = pos + indent.length
|
||||||
|
if (documentManager.activeIndex >=0) documentManager.updateContent(documentManager.activeIndex, text)
|
||||||
|
_prevText = text
|
||||||
|
_prevCursor = cursorPosition
|
||||||
|
if (viewMode === "live") liveDebounce.restart()
|
||||||
|
if (activeFocus && text !== documentManager.contentAt(documentManager.activeIndex)) {
|
||||||
|
editDebounce.restart()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_prevText = text
|
||||||
|
_prevCursor = cursorPosition
|
||||||
if (activeFocus && text !== documentManager.contentAt(documentManager.activeIndex)) {
|
if (activeFocus && text !== documentManager.contentAt(documentManager.activeIndex)) {
|
||||||
editDebounce.restart()
|
editDebounce.restart()
|
||||||
}
|
}
|
||||||
@@ -350,6 +404,7 @@ Item {
|
|||||||
}
|
}
|
||||||
function insertText(t) { insert(cursorPosition, t) }
|
function insertText(t) { insert(cursorPosition, t) }
|
||||||
function handleEnter() {
|
function handleEnter() {
|
||||||
|
_enterHandled = true
|
||||||
const pos = cursorPosition
|
const pos = cursorPosition
|
||||||
let lineStart = text.lastIndexOf("\n", pos-1) + 1
|
let lineStart = text.lastIndexOf("\n", pos-1) + 1
|
||||||
let line = text.substring(lineStart, pos)
|
let line = text.substring(lineStart, pos)
|
||||||
@@ -371,12 +426,19 @@ Item {
|
|||||||
insert(pos, ins)
|
insert(pos, ins)
|
||||||
cursorPosition = pos + 1 + indent.length
|
cursorPosition = pos + 1 + indent.length
|
||||||
if (documentManager.activeIndex >=0) documentManager.updateContent(documentManager.activeIndex, text)
|
if (documentManager.activeIndex >=0) documentManager.updateContent(documentManager.activeIndex, text)
|
||||||
|
// _enterHandled сбросится в onTextChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
// Авто-отступ и скобки
|
// Авто-отступ и скобки
|
||||||
Keys.onReturnPressed: handleEnter()
|
|
||||||
Keys.onEnterPressed: handleEnter()
|
|
||||||
Keys.onPressed: (event) => {
|
Keys.onPressed: (event) => {
|
||||||
|
console.log("Keys.onPressed", event.key, event.text, event.modifiers, "cursor", cursorPosition)
|
||||||
|
// Enter — дублируем обработку здесь на случай если onReturnPressed не сработает
|
||||||
|
if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
|
||||||
|
console.log("Enter via onPressed")
|
||||||
|
event.accepted = true
|
||||||
|
handleEnter()
|
||||||
|
return
|
||||||
|
}
|
||||||
// Tab — 4 пробела, Shift+Tab — снять отступ
|
// Tab — 4 пробела, Shift+Tab — снять отступ
|
||||||
if (event.key === Qt.Key_Tab) {
|
if (event.key === Qt.Key_Tab) {
|
||||||
event.accepted = true
|
event.accepted = true
|
||||||
|
|||||||
Reference in New Issue
Block a user