forked from qt-creator/qt-creator
Lua: Change TextDocument to TextEditor
Since there may be many editors editing a single TextDocument it is more useful to start at the TextEditor level. Change-Id: Ic1c4ea76f22ab0d0741edd6f6ecc24d6befa17e6 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -16,7 +16,7 @@ add_qtc_plugin(Lua
|
||||
bindings/messagemanager.cpp
|
||||
bindings/qtcprocess.cpp
|
||||
bindings/settings.cpp
|
||||
bindings/textdocument.cpp
|
||||
bindings/texteditor.cpp
|
||||
bindings/utils.cpp
|
||||
luaengine.cpp
|
||||
luaengine.h
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "../luaengine.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <texteditor/textdocument.h>
|
||||
|
||||
#include "sol/sol.hpp"
|
||||
|
||||
namespace Lua::Internal {
|
||||
|
||||
class TextDocumentRegistry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static TextDocumentRegistry *instance()
|
||||
{
|
||||
static TextDocumentRegistry *instance = new TextDocumentRegistry();
|
||||
return instance;
|
||||
}
|
||||
|
||||
TextDocumentRegistry()
|
||||
{
|
||||
connect(
|
||||
Core::EditorManager::instance(),
|
||||
&Core::EditorManager::documentOpened,
|
||||
this,
|
||||
&TextDocumentRegistry::onDocumentOpened);
|
||||
|
||||
connect(
|
||||
Core::EditorManager::instance(),
|
||||
&Core::EditorManager::documentClosed,
|
||||
this,
|
||||
&TextDocumentRegistry::onDocumentClosed);
|
||||
|
||||
connect(
|
||||
Core::EditorManager::instance(),
|
||||
&Core::EditorManager::currentEditorChanged,
|
||||
this,
|
||||
[this](Core::IEditor *editor) {
|
||||
if (!editor) {
|
||||
emit currentDocumentChanged(nullptr);
|
||||
return;
|
||||
}
|
||||
auto document = editor->document();
|
||||
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
|
||||
if (textDocument) {
|
||||
emit currentDocumentChanged(textDocument);
|
||||
return;
|
||||
}
|
||||
emit currentDocumentChanged(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
void onDocumentOpened(Core::IDocument *document)
|
||||
{
|
||||
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
|
||||
if (!textDocument)
|
||||
return;
|
||||
|
||||
connect(
|
||||
textDocument,
|
||||
&TextEditor::TextDocument::contentsChangedWithPosition,
|
||||
this,
|
||||
[this, textDocument](int position, int charsRemoved, int charsAdded) {
|
||||
emit documentContentsChanged(textDocument, position, charsRemoved, charsAdded);
|
||||
});
|
||||
|
||||
emit documentOpened(textDocument);
|
||||
}
|
||||
|
||||
void onDocumentClosed(Core::IDocument *document)
|
||||
{
|
||||
auto textDocument = qobject_cast<TextEditor::TextDocument *>(document);
|
||||
if (!textDocument)
|
||||
return;
|
||||
|
||||
document->disconnect(this);
|
||||
emit documentClosed(textDocument);
|
||||
}
|
||||
|
||||
signals:
|
||||
void documentOpened(TextEditor::TextDocument *document);
|
||||
void currentDocumentChanged(TextEditor::TextDocument *document);
|
||||
void documentClosed(TextEditor::TextDocument *document);
|
||||
void documentContentsChanged(
|
||||
TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded);
|
||||
};
|
||||
|
||||
void addTextDocumentsModule()
|
||||
{
|
||||
TextDocumentRegistry::instance();
|
||||
|
||||
LuaEngine::registerProvider("TextDocument", [](sol::state_view lua) -> sol::object {
|
||||
sol::table documents = lua.create_table();
|
||||
|
||||
documents.new_usertype<TextEditor::TextDocument>(
|
||||
"TextDocument",
|
||||
sol::no_constructor,
|
||||
"file",
|
||||
&TextEditor::TextDocument::filePath,
|
||||
"lineAndColumn",
|
||||
[](TextEditor::TextDocument *document,
|
||||
int position) -> std::optional<std::pair<int, int>> {
|
||||
QTextBlock block = document->document()->findBlock(position);
|
||||
if (!block.isValid())
|
||||
return std::nullopt;
|
||||
|
||||
int column = position - block.position();
|
||||
|
||||
return std::make_pair(block.blockNumber() + 1, column + 1);
|
||||
});
|
||||
|
||||
return documents;
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.opened", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextDocumentRegistry::instance(),
|
||||
&TextDocumentRegistry::documentOpened,
|
||||
guard,
|
||||
[func](TextEditor::TextDocument *document) {
|
||||
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.closed", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextDocumentRegistry::instance(),
|
||||
&TextDocumentRegistry::documentClosed,
|
||||
guard,
|
||||
[func](TextEditor::TextDocument *document) {
|
||||
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextDocumentRegistry::instance(),
|
||||
&TextDocumentRegistry::documentContentsChanged,
|
||||
guard,
|
||||
[func](TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded) {
|
||||
Utils::expected_str<void> res
|
||||
= LuaEngine::void_safe_call(func, document, position, charsRemoved, charsAdded);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.currentChanged", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextDocumentRegistry::instance(),
|
||||
&TextDocumentRegistry::currentDocumentChanged,
|
||||
guard,
|
||||
[func](TextEditor::TextDocument *document) {
|
||||
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, document);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Lua::Internal
|
||||
|
||||
#include "textdocument.moc"
|
||||
190
src/plugins/lua/bindings/texteditor.cpp
Normal file
190
src/plugins/lua/bindings/texteditor.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
// Copyright (C) 2024 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
#include "../luaengine.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
|
||||
#include <texteditor/textdocument.h>
|
||||
#include <texteditor/texteditor.h>
|
||||
|
||||
#include "sol/sol.hpp"
|
||||
|
||||
namespace Lua::Internal {
|
||||
|
||||
class TextEditorRegistry : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static TextEditorRegistry *instance()
|
||||
{
|
||||
static TextEditorRegistry *instance = new TextEditorRegistry();
|
||||
return instance;
|
||||
}
|
||||
|
||||
TextEditorRegistry()
|
||||
{
|
||||
connect(
|
||||
Core::EditorManager::instance(),
|
||||
&Core::EditorManager::currentEditorChanged,
|
||||
this,
|
||||
[this](Core::IEditor *editor) {
|
||||
if (!editor) {
|
||||
emit currentEditorChanged(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentTextEditor) {
|
||||
m_currentTextEditor->disconnect(this);
|
||||
m_currentTextEditor->editorWidget()->disconnect(this);
|
||||
m_currentTextEditor->document()->disconnect(this);
|
||||
m_currentTextEditor = nullptr;
|
||||
}
|
||||
|
||||
m_currentTextEditor = qobject_cast<TextEditor::BaseTextEditor *>(editor);
|
||||
|
||||
if (m_currentTextEditor) {
|
||||
if (!connectTextEditor(m_currentTextEditor))
|
||||
m_currentTextEditor = nullptr;
|
||||
}
|
||||
|
||||
emit currentEditorChanged(m_currentTextEditor);
|
||||
});
|
||||
}
|
||||
|
||||
bool connectTextEditor(TextEditor::BaseTextEditor *editor)
|
||||
{
|
||||
auto textEditorWidget = editor->editorWidget();
|
||||
if (!textEditorWidget)
|
||||
return false;
|
||||
|
||||
TextEditor::TextDocument *textDocument = editor->textDocument();
|
||||
if (!textDocument)
|
||||
return false;
|
||||
|
||||
connect(
|
||||
textEditorWidget,
|
||||
&TextEditor::TextEditorWidget::cursorPositionChanged,
|
||||
this,
|
||||
[editor, textEditorWidget, this]() {
|
||||
emit currentCursorChanged(editor, textEditorWidget->multiTextCursor());
|
||||
});
|
||||
|
||||
connect(
|
||||
textDocument,
|
||||
&TextEditor::TextDocument::contentsChangedWithPosition,
|
||||
this,
|
||||
[this, textDocument](int position, int charsRemoved, int charsAdded) {
|
||||
emit documentContentsChanged(textDocument, position, charsRemoved, charsAdded);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
signals:
|
||||
void currentEditorChanged(TextEditor::BaseTextEditor *editor);
|
||||
void documentContentsChanged(
|
||||
TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded);
|
||||
|
||||
void currentCursorChanged(TextEditor::BaseTextEditor *editor, Utils::MultiTextCursor cursor);
|
||||
|
||||
protected:
|
||||
QPointer<TextEditor::BaseTextEditor> m_currentTextEditor = nullptr;
|
||||
};
|
||||
|
||||
void addTextEditorModule()
|
||||
{
|
||||
TextEditorRegistry::instance();
|
||||
|
||||
LuaEngine::registerProvider("TextDocument", [](sol::state_view lua) -> sol::object {
|
||||
sol::table documents = lua.create_table();
|
||||
|
||||
documents.new_usertype<Utils::MultiTextCursor>(
|
||||
"MultiTextCursor",
|
||||
sol::no_constructor,
|
||||
"mainCursor",
|
||||
&Utils::MultiTextCursor::mainCursor,
|
||||
"cursors",
|
||||
&Utils::MultiTextCursor::cursors);
|
||||
|
||||
documents.new_usertype<QTextCursor>(
|
||||
"TextCursor",
|
||||
sol::no_constructor,
|
||||
"position",
|
||||
&QTextCursor::position,
|
||||
"blockNumber",
|
||||
&QTextCursor::blockNumber,
|
||||
"columnNumber",
|
||||
&QTextCursor::columnNumber);
|
||||
|
||||
documents.new_usertype<TextEditor::BaseTextEditor>(
|
||||
"TextEditor",
|
||||
sol::no_constructor,
|
||||
"document",
|
||||
&TextEditor::BaseTextEditor::textDocument,
|
||||
"cursor",
|
||||
[](TextEditor::BaseTextEditor *textEditor) {
|
||||
return textEditor->editorWidget()->multiTextCursor();
|
||||
});
|
||||
|
||||
documents.new_usertype<TextEditor::TextDocument>(
|
||||
"TextDocument",
|
||||
sol::no_constructor,
|
||||
"file",
|
||||
&TextEditor::TextDocument::filePath,
|
||||
"blockAndColumn",
|
||||
[](TextEditor::TextDocument *document,
|
||||
int position) -> std::optional<std::pair<int, int>> {
|
||||
QTextBlock block = document->document()->findBlock(position);
|
||||
if (!block.isValid())
|
||||
return std::nullopt;
|
||||
|
||||
int column = position - block.position();
|
||||
|
||||
return std::make_pair(block.blockNumber() + 1, column + 1);
|
||||
},
|
||||
"blockCount",
|
||||
[](TextEditor::TextDocument *document) { return document->document()->blockCount(); });
|
||||
|
||||
return documents;
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.currentChanged", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextEditorRegistry::instance(),
|
||||
&TextEditorRegistry::currentEditorChanged,
|
||||
guard,
|
||||
[func](TextEditor::BaseTextEditor *editor) {
|
||||
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, editor);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.contentsChanged", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextEditorRegistry::instance(),
|
||||
&TextEditorRegistry::documentContentsChanged,
|
||||
guard,
|
||||
[func](TextEditor::TextDocument *document, int position, int charsRemoved, int charsAdded) {
|
||||
Utils::expected_str<void> res
|
||||
= LuaEngine::void_safe_call(func, document, position, charsRemoved, charsAdded);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
|
||||
LuaEngine::registerHook("editors.text.cursorChanged", [](sol::function func, QObject *guard) {
|
||||
QObject::connect(
|
||||
TextEditorRegistry::instance(),
|
||||
&TextEditorRegistry::currentCursorChanged,
|
||||
guard,
|
||||
[func](TextEditor::BaseTextEditor *editor, const Utils::MultiTextCursor &cursor) {
|
||||
Utils::expected_str<void> res = LuaEngine::void_safe_call(func, editor, cursor);
|
||||
QTC_CHECK_EXPECTED(res);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Lua::Internal
|
||||
|
||||
#include "texteditor.moc"
|
||||
@@ -45,7 +45,7 @@ void addMessageManagerModule();
|
||||
void addProcessModule();
|
||||
void addQtModule();
|
||||
void addSettingsModule();
|
||||
void addTextDocumentsModule();
|
||||
void addTextEditorModule();
|
||||
void addUtilsModule();
|
||||
|
||||
class LuaJsExtension : public QObject
|
||||
@@ -261,7 +261,7 @@ public:
|
||||
addProcessModule();
|
||||
addQtModule();
|
||||
addSettingsModule();
|
||||
addTextDocumentsModule();
|
||||
addTextEditorModule();
|
||||
addUtilsModule();
|
||||
|
||||
Core::JsExpander::registerGlobalObject("Lua", [] { return new LuaJsExtension(); });
|
||||
|
||||
@@ -40,10 +40,9 @@ QtcPluginDependency = {}
|
||||
EditorHooks = {}
|
||||
|
||||
---@class TextEditorHooks
|
||||
---@field opened? function function(Documents.TextDocument)
|
||||
---@field closed? function function(Documents.TextDocument)
|
||||
---@field currentChanged? function function(Documents.TextDocument)
|
||||
---@field contentsChanged? function function(document: Documents.TextDocument, position: integer, charsRemoved: integer, charsAdded: integer)
|
||||
---@field currentChanged? function function(editor: TextEditor)
|
||||
---@field contentsChanged? function function(document: TextDocument, position: integer, charsRemoved: integer, charsAdded: integer)
|
||||
---@field cursorChanged? function function(editor: TextEditor, cursor: MultiTextCursor)
|
||||
|
||||
---@class Hooks
|
||||
---@field editors? EditorHooks
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
---@meta TextDocument
|
||||
|
||||
---@class TextDocument
|
||||
local TextDocument = {}
|
||||
|
||||
---Returns the file path of the document.
|
||||
---@return FilePath filePath The file path of the document.
|
||||
function TextDocument:file() end
|
||||
|
||||
---Returns the line and column of the given position.
|
||||
---@param position integer The position to convert.
|
||||
---@return integer line The line of the position.
|
||||
---@return integer column The column of the position.
|
||||
function TextDocument:lineAndColumn(position) end
|
||||
|
||||
return TextDocument
|
||||
42
src/plugins/lua/meta/texteditor.lua
Normal file
42
src/plugins/lua/meta/texteditor.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
---@meta TextEditor
|
||||
|
||||
---@class TextCursor
|
||||
---@field position integer The position of the cursor.
|
||||
---@field blockNumber integer The block (line) number of the cursor.
|
||||
---@field columnNumber integer The column number of the cursor.
|
||||
local TextCursor = {}
|
||||
|
||||
---@class MultiTextCursor
|
||||
---@field mainCursor TextCursor The main cursor.
|
||||
---@field cursors TextCursor[] The cursors.
|
||||
local MultiTextCursor = {}
|
||||
|
||||
---@class TextDocument
|
||||
local TextDocument = {}
|
||||
|
||||
---Returns the file path of the document.
|
||||
---@return FilePath filePath The file path of the document.
|
||||
function TextDocument:file() end
|
||||
|
||||
---Returns the block (line) and column for the given position.
|
||||
---@param position integer The position to convert.
|
||||
---@return integer block The block (line) of the position.
|
||||
---@return integer column The column of the position.
|
||||
function TextDocument:blockAndColumn(position) end
|
||||
|
||||
---Returns the number of blocks (lines) in the document.
|
||||
---@return integer blockCount The number of blocks in the document.
|
||||
function TextDocument:blockCount() end
|
||||
|
||||
---@class TextEditor
|
||||
local TextEditor = {}
|
||||
|
||||
---Returns the document of the editor.
|
||||
---@return TextDocument document The document of the editor.
|
||||
function TextEditor:document() end
|
||||
|
||||
---Returns the cursor of the editor.
|
||||
---@return MultiTextCursor cursor The cursor of the editor.
|
||||
function TextEditor:cursor() end
|
||||
|
||||
return TextDocument
|
||||
Reference in New Issue
Block a user