Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Utilities
Kate
Commits
e86e3838
Commit
e86e3838
authored
Jan 21, 2022
by
Waqar Ahmed
Browse files
Add Before/After save triggers
parent
9a599a94
Changes
8
Hide whitespace changes
Inline
Side-by-side
addons/externaltools/externaltoolsplugin.cpp
View file @
e86e3838
...
...
@@ -235,14 +235,14 @@ QVector<KateExternalTool> KateExternalToolsPlugin::defaultTools() const
return
m_defaultTools
;
}
void
KateExternalToolsPlugin
::
runTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executing
On
Save
)
KateToolRunner
*
KateExternalToolsPlugin
::
run
nerFor
Tool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSave
Trigger
)
{
// expand the macros in command if any,
// and construct a command with an absolute path
auto
mw
=
view
->
mainWindow
();
// save documents if requested
if
(
!
executing
On
Save
)
{
if
(
!
executingSave
Trigger
)
{
if
(
tool
.
saveMode
==
KateExternalTool
::
SaveMode
::
CurrentDocument
)
{
// only save if modified, to avoid unnecessary recompiles
if
(
view
->
document
()
->
isModified
())
{
...
...
@@ -286,13 +286,25 @@ void KateExternalToolsPlugin::runTool(const KateExternalTool &tool, KTextEditor:
// Allocate runner on heap such that it lives as long as the child
// process is running and does not block the main thread.
auto
runner
=
new
KateToolRunner
(
std
::
move
(
copy
),
view
,
this
);
return
new
KateToolRunner
(
std
::
move
(
copy
),
view
,
this
);
}
void
KateExternalToolsPlugin
::
runTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSaveTrigger
)
{
auto
runner
=
runnerForTool
(
tool
,
view
,
executingSaveTrigger
);
// use QueuedConnection, since handleToolFinished deletes the runner
connect
(
runner
,
&
KateToolRunner
::
toolFinished
,
this
,
&
KateExternalToolsPlugin
::
handleToolFinished
,
Qt
::
QueuedConnection
);
runner
->
run
();
}
void
KateExternalToolsPlugin
::
blockingRunTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSaveTrigger
)
{
auto
runner
=
runnerForTool
(
tool
,
view
,
executingSaveTrigger
);
connect
(
runner
,
&
KateToolRunner
::
toolFinished
,
this
,
&
KateExternalToolsPlugin
::
handleToolFinished
);
runner
->
run
();
runner
->
waitForFinished
();
}
void
KateExternalToolsPlugin
::
handleToolFinished
(
KateToolRunner
*
runner
,
int
exitCode
,
bool
crashed
)
{
auto
view
=
runner
->
view
();
...
...
addons/externaltools/externaltoolsplugin.h
View file @
e86e3838
...
...
@@ -91,7 +91,13 @@ public:
/**
* Executes the tool based on the view as current document.
*/
void
runTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingOnSave
=
false
);
void
runTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSaveTrigger
=
false
);
/**
* Executes the tool based on the view as current document.
* same as @ref runTool but waits for the tool to finish before returning
*/
void
blockingRunTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSaveTrigger
=
false
);
Q_SIGNALS:
/**
...
...
@@ -134,6 +140,7 @@ public:
private:
void
migrateConfig
();
KateToolRunner
*
runnerForTool
(
const
KateExternalTool
&
tool
,
KTextEditor
::
View
*
view
,
bool
executingSaveTrigger
);
KSharedConfigPtr
m_config
;
QVector
<
KateExternalTool
>
m_defaultTools
;
...
...
addons/externaltools/kateexternaltool.cpp
View file @
e86e3838
...
...
@@ -92,6 +92,34 @@ KateExternalTool::OutputMode toOutputMode(const QString &mode)
}
return
KateExternalTool
::
OutputMode
::
Ignore
;
}
KateExternalTool
::
Trigger
toTrigger
(
const
QString
&
trigger
)
{
if
(
trigger
==
QStringLiteral
(
"None"
))
{
return
KateExternalTool
::
Trigger
::
None
;
}
if
(
trigger
==
QStringLiteral
(
"BeforeSave"
))
{
return
KateExternalTool
::
Trigger
::
BeforeSave
;
}
if
(
trigger
==
QStringLiteral
(
"AfterSave"
))
{
return
KateExternalTool
::
Trigger
::
AfterSave
;
}
return
KateExternalTool
::
Trigger
::
None
;
}
QString
toString
(
KateExternalTool
::
Trigger
trigger
)
{
if
(
trigger
==
KateExternalTool
::
Trigger
::
None
)
{
return
QStringLiteral
(
"None"
);
}
if
(
trigger
==
KateExternalTool
::
Trigger
::
BeforeSave
)
{
return
QStringLiteral
(
"BeforeSave"
);
}
if
(
trigger
==
KateExternalTool
::
Trigger
::
AfterSave
)
{
return
QStringLiteral
(
"AfterSave"
);
}
return
QStringLiteral
(
"None"
);
}
}
bool
KateExternalTool
::
checkExec
()
const
...
...
@@ -119,7 +147,7 @@ void KateExternalTool::load(const KConfigGroup &cg)
saveMode
=
toSaveMode
(
cg
.
readEntry
(
"save"
,
"None"
));
reload
=
cg
.
readEntry
(
"reload"
,
false
);
outputMode
=
toOutputMode
(
cg
.
readEntry
(
"output"
,
"Ignore"
));
execOnSave
=
cg
.
readEntry
(
"execOnSave"
,
false
);
trigger
=
toTrigger
(
cg
.
readEntry
(
"trigger"
,
"None"
)
);
hasexec
=
checkExec
();
}
...
...
@@ -149,10 +177,10 @@ void KateExternalTool::save(KConfigGroup &cg) const
writeEntryMaybe
(
cg
,
"cmdname"
,
cmdname
);
writeEntryMaybe
(
cg
,
"save"
,
toString
(
saveMode
));
writeEntryMaybe
(
cg
,
"output"
,
toString
(
outputMode
));
writeEntryMaybe
(
cg
,
"trigger"
,
toString
(
trigger
));
// a logical value is never empty
cg
.
writeEntry
(
"reload"
,
reload
);
cg
.
writeEntry
(
"execOnSave"
,
execOnSave
);
}
QString
KateExternalTool
::
translatedName
()
const
...
...
@@ -170,7 +198,7 @@ bool operator==(const KateExternalTool &lhs, const KateExternalTool &rhs)
return
lhs
.
category
==
rhs
.
category
&&
lhs
.
name
==
rhs
.
name
&&
lhs
.
icon
==
rhs
.
icon
&&
lhs
.
executable
==
rhs
.
executable
&&
lhs
.
arguments
==
rhs
.
arguments
&&
lhs
.
input
==
rhs
.
input
&&
lhs
.
workingDir
==
rhs
.
workingDir
&&
lhs
.
mimetypes
==
rhs
.
mimetypes
&&
lhs
.
actionName
==
rhs
.
actionName
&&
lhs
.
cmdname
==
rhs
.
cmdname
&&
lhs
.
saveMode
==
rhs
.
saveMode
&&
lhs
.
reload
==
rhs
.
reload
&&
lhs
.
outputMode
==
rhs
.
outputMode
&&
lhs
.
execOnSave
==
rhs
.
execOnSave
;
&&
lhs
.
trigger
==
rhs
.
trigger
;
}
// kate: space-indent on; indent-width 4; replace-tabs on;
addons/externaltools/kateexternaltool.h
View file @
e86e3838
...
...
@@ -45,6 +45,15 @@ public:
DisplayInPane
};
enum
class
Trigger
{
//! No trigger
None
,
//! Run the tool before saving
BeforeSave
,
//! Run the tool after saving
AfterSave
,
};
public:
/// The category used in the menu to categorize the tool.
QString
category
;
...
...
@@ -73,8 +82,8 @@ public:
bool
reload
=
false
;
/// Defines where to redirect the tool's output
OutputMode
outputMode
=
OutputMode
::
Ignore
;
///
Wheth
er to
execute tool on document save
bool
execOnSave
=
fals
e
;
///
Trigg
er to
run tool
Trigger
trigger
=
Trigger
::
Non
e
;
public:
/// This is set when loading the Tool from disk.
...
...
addons/externaltools/kateexternaltoolsconfigwidget.cpp
View file @
e86e3838
...
...
@@ -13,6 +13,7 @@
#include
<KTextEditor/Document>
#include
<KTextEditor/Editor>
#include
<KTextEditor/View>
#include
<ktexteditor_version.h>
#include
<KConfig>
#include
<KConfigGroup>
...
...
@@ -24,6 +25,7 @@
#include
<KXmlGuiWindow>
#include
<QBitmap>
#include
<QComboBox>
#include
<QListView>
#include
<QMenu>
#include
<QMessageBox>
#include
<QRegularExpression>
...
...
@@ -140,6 +142,13 @@ KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool *t
ui
.
setupUi
(
this
);
ui
.
btnIcon
->
setIconSize
(
KIconLoader
::
SizeSmall
);
#if KTEXTEDITOR_VERSION < QT_VERSION_CHECK(5, 90, 0)
{
auto
v
=
qobject_cast
<
QListView
*>
(
ui
.
cmbTrigger
->
view
());
v
->
setRowHidden
(
1
,
true
);
}
#endif
connect
(
ui
.
buttonBox
,
&
QDialogButtonBox
::
accepted
,
this
,
&
KateExternalToolServiceEditor
::
slotOKClicked
);
connect
(
ui
.
buttonBox
,
&
QDialogButtonBox
::
rejected
,
this
,
&
QDialog
::
reject
);
connect
(
ui
.
btnMimeType
,
&
QToolButton
::
clicked
,
this
,
&
KateExternalToolServiceEditor
::
showMTDlg
);
...
...
@@ -156,11 +165,11 @@ KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool *t
ui
.
edtWorkingDir
->
setText
(
m_tool
->
workingDir
);
ui
.
edtWorkingDir
->
setMode
(
KFile
::
Directory
|
KFile
::
ExistingOnly
|
KFile
::
LocalOnly
);
ui
.
edtMimeType
->
setText
(
m_tool
->
mimetypes
.
join
(
QStringLiteral
(
"; "
)));
ui
.
edtMimeType
->
setReadOnly
(
true
);
ui
.
cmbSave
->
setCurrentIndex
(
static_cast
<
int
>
(
m_tool
->
saveMode
));
ui
.
chkReload
->
setChecked
(
m_tool
->
reload
);
ui
.
cmbOutput
->
setCurrentIndex
(
static_cast
<
int
>
(
m_tool
->
outputMode
));
ui
.
edtCommand
->
setText
(
m_tool
->
cmdname
);
ui
.
cmbTrigger
->
setCurrentIndex
((
int
)
m_tool
->
trigger
);
static
const
QRegularExpressionValidator
cmdLineValidator
(
QRegularExpression
(
QStringLiteral
(
"[
\\
w-]*"
)));
ui
.
edtCommand
->
setValidator
(
&
cmdLineValidator
);
...
...
@@ -181,7 +190,7 @@ KateExternalToolServiceEditor::KateExternalToolServiceEditor(KateExternalTool *t
ui
.
chkReload
->
setChecked
(
t
.
reload
);
ui
.
cmbOutput
->
setCurrentIndex
(
static_cast
<
int
>
(
t
.
outputMode
));
ui
.
edtCommand
->
setText
(
t
.
cmdname
);
ui
.
c
hkExecSave
->
setChecked
(
t
.
execOnSave
);
ui
.
c
mbTrigger
->
setCurrentIndex
(
static_cast
<
int
>
(
t
.
trigger
)
);
});
}
...
...
@@ -196,9 +205,9 @@ void KateExternalToolServiceEditor::slotOKClicked()
return
;
}
const
bool
execOnSave
=
ui
.
chkExecSave
->
isChecked
()
;
if
(
execOnSave
&&
ui
.
edtMimeType
->
text
().
isEmpty
())
{
QMessageBox
::
information
(
this
,
i18n
(
"External Tool"
),
i18n
(
"With '
Execute On Save
' enabled, at least one mimetype needs to be specified."
));
const
bool
hasTrigger
=
ui
.
cmbTrigger
->
currentIndex
()
!=
(
int
)
KateExternalTool
::
Trigger
::
None
;
if
(
hasTrigger
&&
ui
.
edtMimeType
->
text
().
isEmpty
())
{
QMessageBox
::
information
(
this
,
i18n
(
"External Tool"
),
i18n
(
"With '
Trigger
' enabled, at least one mimetype needs to be specified."
));
return
;
}
...
...
@@ -355,7 +364,7 @@ bool KateExternalToolsConfigWidget::editTool(KateExternalTool *tool)
tool
->
reload
=
editor
.
ui
.
chkReload
->
isChecked
();
tool
->
outputMode
=
static_cast
<
KateExternalTool
::
OutputMode
>
(
editor
.
ui
.
cmbOutput
->
currentIndex
());
tool
->
cmdname
=
editor
.
ui
.
edtCommand
->
text
().
trimmed
();
tool
->
execOnSave
=
editor
.
ui
.
chkExecSave
->
isChecked
(
);
tool
->
trigger
=
static_cast
<
KateExternalTool
::
Trigger
>
(
editor
.
ui
.
cmbTrigger
->
currentIndex
()
);
tool
->
executable
=
editor
.
ui
.
edtExecutable
->
text
().
trimmed
();
tool
->
hasexec
=
tool
->
checkExec
();
...
...
addons/externaltools/kateexternaltoolsview.cpp
View file @
e86e3838
...
...
@@ -9,7 +9,9 @@
#include
"kateexternaltool.h"
#include
"ui_toolview.h"
#include
<KTextEditor/Application>
#include
<KTextEditor/Document>
#include
<KTextEditor/Editor>
#include
<KTextEditor/MainWindow>
#include
<KTextEditor/View>
...
...
@@ -22,6 +24,7 @@
#include
<KXMLGUIFactory>
#include
<QMenu>
#include
<QStandardPaths>
#include
<ktexteditor_version.h>
#include
<QFontDatabase>
#include
<QKeyEvent>
...
...
@@ -270,20 +273,54 @@ void KateExternalToolsPluginView::handleEsc(QEvent *event)
void
KateExternalToolsPluginView
::
slotViewChanged
(
KTextEditor
::
View
*
v
)
{
if
(
m_currentView
)
{
disconnect
(
m_currentView
->
document
(),
&
KTextEditor
::
Document
::
documentSavedOrUploaded
,
this
,
&
KateExternalToolsPluginView
::
documentSaved
);
disconnect
(
m_currentView
->
document
(),
&
KTextEditor
::
Document
::
documentSavedOrUploaded
,
this
,
&
KateExternalToolsPluginView
::
onDocumentSaved
);
#if KTEXTEDITOR_VERSION >= QT_VERSION_CHECK(5, 90, 0)
disconnect
(
m_currentView
->
document
(),
&
KTextEditor
::
Document
::
aboutToSave
,
this
,
&
KateExternalToolsPluginView
::
onDocumentAboutToSave
);
#endif
}
m_currentView
=
v
;
connect
(
v
->
document
(),
&
KTextEditor
::
Document
::
documentSavedOrUploaded
,
this
,
&
KateExternalToolsPluginView
::
documentSaved
,
Qt
::
UniqueConnection
);
connect
(
v
->
document
(),
&
KTextEditor
::
Document
::
documentSavedOrUploaded
,
this
,
&
KateExternalToolsPluginView
::
onDocumentSaved
,
Qt
::
UniqueConnection
);
#if KTEXTEDITOR_VERSION >= QT_VERSION_CHECK(5, 90, 0)
connect
(
v
->
document
(),
&
KTextEditor
::
Document
::
aboutToSave
,
this
,
&
KateExternalToolsPluginView
::
onDocumentAboutToSave
,
Qt
::
UniqueConnection
);
#endif
}
void
KateExternalToolsPluginView
::
d
ocumentSaved
(
KTextEditor
::
Document
*
doc
)
void
KateExternalToolsPluginView
::
onD
ocumentSaved
(
KTextEditor
::
Document
*
doc
)
{
// We only want to run this in the current active mainwindow
if
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
!=
m_mainWindow
)
{
return
;
}
const
auto
tools
=
m_plugin
->
tools
();
for
(
KateExternalTool
*
tool
:
tools
)
{
const
bool
hasSaveTrigger
=
tool
->
trigger
==
KateExternalTool
::
Trigger
::
AfterSave
;
if
(
hasSaveTrigger
&&
tool
->
matchesMimetype
(
doc
->
mimeType
()))
{
m_plugin
->
runTool
(
*
tool
,
m_currentView
,
/*exec save trigger=*/
true
);
}
}
}
void
KateExternalToolsPluginView
::
onDocumentAboutToSave
(
KTextEditor
::
Document
*
doc
)
{
// We only want to run this in the current active mainwindow
if
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
!=
m_mainWindow
)
{
return
;
}
#if KTEXTEDITOR_VERSION >= QT_VERSION_CHECK(5, 90, 0)
const
auto
tools
=
m_plugin
->
tools
();
for
(
KateExternalTool
*
tool
:
tools
)
{
if
(
tool
->
execOnSave
&&
tool
->
matchesMimetype
(
doc
->
mimeType
()))
{
m_plugin
->
runTool
(
*
tool
,
m_currentView
,
tool
->
execOnSave
);
const
bool
hasSaveTrigger
=
tool
->
trigger
==
KateExternalTool
::
Trigger
::
BeforeSave
;
if
(
hasSaveTrigger
&&
tool
->
matchesMimetype
(
doc
->
mimeType
()))
{
m_plugin
->
blockingRunTool
(
*
tool
,
m_currentView
,
/*exec save trigger=*/
true
);
}
}
#else
Q_UNUSED
(
doc
)
#endif
}
// END KateExternalToolsPluginView
...
...
addons/externaltools/kateexternaltoolsview.h
View file @
e86e3838
...
...
@@ -140,7 +140,8 @@ public Q_SLOTS:
private
Q_SLOTS
:
void
slotViewChanged
(
KTextEditor
::
View
*
v
);
void
documentSaved
(
KTextEditor
::
Document
*
doc
);
void
onDocumentSaved
(
KTextEditor
::
Document
*
doc
);
void
onDocumentAboutToSave
(
KTextEditor
::
Document
*
doc
);
Q_SIGNALS:
/**
...
...
addons/externaltools/tooldialog.ui
View file @
e86e3838
...
...
@@ -7,7 +7,7 @@
<x>
0
</x>
<y>
0
</y>
<width>
470
</width>
<height>
5
34
</height>
<height>
5
59
</height>
</rect>
</property>
<property
name=
"windowTitle"
>
...
...
@@ -51,6 +51,13 @@
</property>
</widget>
</item>
<item
row=
"1"
column=
"1"
>
<widget
class=
"KUrlRequester"
name=
"edtExecutable"
>
<property
name=
"placeholderText"
>
<string>
Application or interpreter
</string>
</property>
</widget>
</item>
<item
row=
"2"
column=
"0"
>
<widget
class=
"QLabel"
name=
"lblArgs"
>
<property
name=
"text"
>
...
...
@@ -95,6 +102,13 @@
</property>
</widget>
</item>
<item
row=
"4"
column=
"1"
>
<widget
class=
"KUrlRequester"
name=
"edtWorkingDir"
>
<property
name=
"placeholderText"
>
<string>
Uses current document path if empty
</string>
</property>
</widget>
</item>
<item
row=
"5"
column=
"0"
>
<widget
class=
"QLabel"
name=
"lblMimeType"
>
<property
name=
"text"
>
...
...
@@ -162,7 +176,33 @@
</item>
</widget>
</item>
<item
row=
"7"
column=
"0"
>
<widget
class=
"QLabel"
name=
"label_2"
>
<property
name=
"text"
>
<string>
Trigger
</string>
</property>
</widget>
</item>
<item
row=
"7"
column=
"1"
>
<widget
class=
"QComboBox"
name=
"cmbTrigger"
>
<item>
<property
name=
"text"
>
<string>
None
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
Before Save
</string>
</property>
</item>
<item>
<property
name=
"text"
>
<string>
After Save
</string>
</property>
</item>
</widget>
</item>
<item
row=
"8"
column=
"1"
>
<widget
class=
"QCheckBox"
name=
"chkReload"
>
<property
name=
"text"
>
<string>
Reload current document after execution
</string>
...
...
@@ -250,27 +290,6 @@
</property>
</widget>
</item>
<item
row=
"1"
column=
"1"
>
<widget
class=
"KUrlRequester"
name=
"edtExecutable"
>
<property
name=
"placeholderText"
>
<string>
Application or interpreter
</string>
</property>
</widget>
</item>
<item
row=
"4"
column=
"1"
>
<widget
class=
"KUrlRequester"
name=
"edtWorkingDir"
>
<property
name=
"placeholderText"
>
<string>
Uses current document path if empty
</string>
</property>
</widget>
</item>
<item
row=
"8"
column=
"1"
>
<widget
class=
"QCheckBox"
name=
"chkExecSave"
>
<property
name=
"text"
>
<string>
Execute on save
</string>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment