forked from qt-creator/qt-creator
Lua: Allow creating and running user defined scripts
Change-Id: I227d55105fde53f22885793b4bfae69da90e8fa6 Reviewed-by: Marcus Tillmanns <marcus.tillmanns@qt.io>
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "corejsextensions.h"
|
#include "corejsextensions.h"
|
||||||
|
|
||||||
|
#include "icore.h"
|
||||||
#include "messagemanager.h"
|
#include "messagemanager.h"
|
||||||
|
|
||||||
#include <utils/appinfo.h>
|
#include <utils/appinfo.h>
|
||||||
@@ -35,6 +36,11 @@ QString UtilsJsExtension::qtCreatorIdeVersion() const
|
|||||||
return QCoreApplication::applicationVersion();
|
return QCoreApplication::applicationVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString UtilsJsExtension::qtCreatorSettingsPath() const
|
||||||
|
{
|
||||||
|
return Core::ICore::userResourcePath().toString();
|
||||||
|
}
|
||||||
|
|
||||||
QString UtilsJsExtension::toNativeSeparators(const QString &in) const
|
QString UtilsJsExtension::toNativeSeparators(const QString &in) const
|
||||||
{
|
{
|
||||||
return QDir::toNativeSeparators(in);
|
return QDir::toNativeSeparators(in);
|
||||||
|
@@ -21,6 +21,7 @@ public:
|
|||||||
Q_INVOKABLE QString qtVersion() const;
|
Q_INVOKABLE QString qtVersion() const;
|
||||||
Q_INVOKABLE QString qtCreatorVersion() const;
|
Q_INVOKABLE QString qtCreatorVersion() const;
|
||||||
Q_INVOKABLE QString qtCreatorIdeVersion() const;
|
Q_INVOKABLE QString qtCreatorIdeVersion() const;
|
||||||
|
Q_INVOKABLE QString qtCreatorSettingsPath() const;
|
||||||
|
|
||||||
// File name conversions:
|
// File name conversions:
|
||||||
Q_INVOKABLE QString toNativeSeparators(const QString &in) const;
|
Q_INVOKABLE QString toNativeSeparators(const QString &in) const;
|
||||||
|
@@ -5,6 +5,8 @@
|
|||||||
#include "luapluginspec.h"
|
#include "luapluginspec.h"
|
||||||
#include "luatr.h"
|
#include "luatr.h"
|
||||||
|
|
||||||
|
#include <coreplugin/actionmanager/actionmanager.h>
|
||||||
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
#include <coreplugin/ioutputpane.h>
|
#include <coreplugin/ioutputpane.h>
|
||||||
#include <coreplugin/jsexpander.h>
|
#include <coreplugin/jsexpander.h>
|
||||||
@@ -14,6 +16,7 @@
|
|||||||
#include <extensionsystem/pluginmanager.h>
|
#include <extensionsystem/pluginmanager.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
|
#include <utils/fileutils.h>
|
||||||
#include <utils/layoutbuilder.h>
|
#include <utils/layoutbuilder.h>
|
||||||
#include <utils/macroexpander.h>
|
#include <utils/macroexpander.h>
|
||||||
#include <utils/qtcprocess.h>
|
#include <utils/qtcprocess.h>
|
||||||
@@ -25,6 +28,7 @@
|
|||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QMenu>
|
||||||
#include <QStringListModel>
|
#include <QStringListModel>
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
@@ -34,6 +38,11 @@ using namespace ExtensionSystem;
|
|||||||
|
|
||||||
namespace Lua::Internal {
|
namespace Lua::Internal {
|
||||||
|
|
||||||
|
const char M_SCRIPT[] = "Lua.Script";
|
||||||
|
const char G_SCRIPTS[] = "Lua.Scripts";
|
||||||
|
const char ACTION_SCRIPTS_BASE[] = "Lua.Scripts.";
|
||||||
|
const char ACTION_NEW_SCRIPT[] = "Lua.NewScript";
|
||||||
|
|
||||||
void setupActionModule();
|
void setupActionModule();
|
||||||
void setupCoreModule();
|
void setupCoreModule();
|
||||||
void setupFetchModule();
|
void setupFetchModule();
|
||||||
@@ -270,6 +279,7 @@ class LuaPlugin : public IPlugin
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
LuaPane *m_pane = nullptr;
|
LuaPane *m_pane = nullptr;
|
||||||
|
std::unique_ptr<FilePathWatcher> m_userScriptsWatcher;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LuaPlugin() {}
|
LuaPlugin() {}
|
||||||
@@ -319,6 +329,44 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
m_pane = new LuaPane(this);
|
m_pane = new LuaPane(this);
|
||||||
|
|
||||||
|
//register actions
|
||||||
|
ActionContainer *toolsContainer = ActionManager::actionContainer(Core::Constants::M_TOOLS);
|
||||||
|
|
||||||
|
ActionContainer *scriptContainer = ActionManager::createMenu(M_SCRIPT);
|
||||||
|
|
||||||
|
Command *newScriptCommand = ActionBuilder(this, ACTION_NEW_SCRIPT)
|
||||||
|
.setScriptable(true)
|
||||||
|
.setText(tr("New Script..."))
|
||||||
|
.addToContainer(M_SCRIPT)
|
||||||
|
.addOnTriggered([](){
|
||||||
|
auto command = Core::ActionManager::command(Utils::Id("Wizard.Impl.Q.QCreatorScript"));
|
||||||
|
if (command && command->action())
|
||||||
|
command->action()->trigger();
|
||||||
|
else
|
||||||
|
qWarning("Failed to get wizard command. UI changed?");
|
||||||
|
})
|
||||||
|
.command();
|
||||||
|
|
||||||
|
scriptContainer->addAction(newScriptCommand);
|
||||||
|
scriptContainer->addSeparator();
|
||||||
|
scriptContainer->appendGroup(G_SCRIPTS);
|
||||||
|
|
||||||
|
scriptContainer->menu()->setTitle(Tr::tr("Scripting"));
|
||||||
|
toolsContainer->addMenu(scriptContainer);
|
||||||
|
|
||||||
|
const Utils::FilePath userScriptsPath = Core::ICore::userResourcePath("scripts");
|
||||||
|
userScriptsPath.ensureWritableDir();
|
||||||
|
if (auto watch = userScriptsPath.watch()) {
|
||||||
|
m_userScriptsWatcher.swap(*watch);
|
||||||
|
connect(
|
||||||
|
m_userScriptsWatcher.get(),
|
||||||
|
&FilePathWatcher::pathChanged,
|
||||||
|
this,
|
||||||
|
&LuaPlugin::scanForScripts);
|
||||||
|
}
|
||||||
|
|
||||||
|
scanForScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool delayedInitialize() final
|
bool delayedInitialize() final
|
||||||
@@ -355,6 +403,49 @@ public:
|
|||||||
PluginManager::addPlugins({plugins.begin(), plugins.end()});
|
PluginManager::addPlugins({plugins.begin(), plugins.end()});
|
||||||
PluginManager::loadPluginsAtRuntime(plugins);
|
PluginManager::loadPluginsAtRuntime(plugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scanForScripts()
|
||||||
|
{
|
||||||
|
const FilePath scriptsPath = Core::ICore::userResourcePath("scripts");
|
||||||
|
if (!scriptsPath.exists())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ActionContainer *scriptContainer = ActionManager::actionContainer(M_SCRIPT);
|
||||||
|
|
||||||
|
const FilePaths scripts = scriptsPath.dirEntries(FileFilter({"*.lua"}, QDir::Files));
|
||||||
|
for (const FilePath &script : scripts) {
|
||||||
|
const Id base = Id(ACTION_SCRIPTS_BASE).withSuffix(script.baseName());
|
||||||
|
const Id menuId = base.withSuffix(".Menu");
|
||||||
|
if (!ActionManager::actionContainer(menuId)) {
|
||||||
|
ActionContainer *container = ActionManager::createMenu(menuId);
|
||||||
|
scriptContainer->addMenu(container);
|
||||||
|
auto menu = container->menu();
|
||||||
|
menu->setTitle(script.baseName());
|
||||||
|
ActionBuilder(this, base)
|
||||||
|
.setText(Tr::tr("%1").arg(script.baseName()))
|
||||||
|
.setToolTip(Tr::tr("Run script '%1'").arg(script.toUserOutput()))
|
||||||
|
.addOnTriggered([this, script]() { runScript(script); });
|
||||||
|
connect(menu->addAction(Tr::tr("Run")), &QAction::triggered, this, [this, script]() {
|
||||||
|
runScript(script);
|
||||||
|
});
|
||||||
|
connect(menu->addAction(Tr::tr("Edit")), &QAction::triggered, this, [script]() {
|
||||||
|
Core::EditorManager::openEditor(script);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void runScript(const FilePath &script)
|
||||||
|
{
|
||||||
|
expected_str<QByteArray> content = script.fileContents();
|
||||||
|
if (content) {
|
||||||
|
Lua::runScript(QString::fromUtf8(*content), script.fileName());
|
||||||
|
} else {
|
||||||
|
MessageManager::writeFlashing(Tr::tr("Failed to read script %1: %2")
|
||||||
|
.arg(script.toUserOutput())
|
||||||
|
.arg(content.error()));
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Lua::Internal
|
} // namespace Lua::Internal
|
||||||
|
4
src/plugins/lua/wizards/qcscript/script.lua
Normal file
4
src/plugins/lua/wizards/qcscript/script.lua
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
T = require'TextEditor'
|
||||||
|
editor = T.currentEditor()
|
||||||
|
cursor = editor:cursor()
|
||||||
|
cursor:insertText('-- Hello World!')
|
44
src/plugins/lua/wizards/qcscript/wizard.json
Normal file
44
src/plugins/lua/wizards/qcscript/wizard.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"supportedProjectTypes": [],
|
||||||
|
"id": "Q.QCreatorScript",
|
||||||
|
"category": "R.Lua",
|
||||||
|
"trDescription": "Creates a script that can access Qt Creator internals and be triggered by an action.",
|
||||||
|
"trDisplayName": "Qt Creator Script",
|
||||||
|
"trDisplayCategory": "Lua",
|
||||||
|
"iconText": "ts",
|
||||||
|
"enabled": "%{JS: value('Plugins').indexOf('Lua') >= 0}",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"key": "DefaultSuffix",
|
||||||
|
"value": "%{JS: Util.preferredSuffix('text/x-lua')}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "InitialPath",
|
||||||
|
"value": "%{JS: Util.qtCreatorSettingsPath()}/scripts"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "PathVisible",
|
||||||
|
"value": "false"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"trDisplayName": "Location",
|
||||||
|
"trShortTitle": "Location",
|
||||||
|
"typeId": "File"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"generators": [
|
||||||
|
{
|
||||||
|
"typeId": "File",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"source": "script.lua",
|
||||||
|
"target": "%{JS: Util.fileName(value('TargetPath'), value('DefaultSuffix'))}",
|
||||||
|
"openInEditor": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -9,5 +9,7 @@
|
|||||||
<file>plugin/.luarc.json</file>
|
<file>plugin/.luarc.json</file>
|
||||||
<file>plugin/icon.png</file>
|
<file>plugin/icon.png</file>
|
||||||
<file>plugin/icon@2x.png</file>
|
<file>plugin/icon@2x.png</file>
|
||||||
|
<file>qcscript/script.lua</file>
|
||||||
|
<file>qcscript/wizard.json</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
Reference in New Issue
Block a user