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
dd11e707
Commit
dd11e707
authored
Jul 25, 2022
by
Pablo Rauzy
Committed by
Christoph Cullmann
Aug 14, 2022
Browse files
simplifying things
parent
42171a43
Changes
5
Hide whitespace changes
Inline
Side-by-side
addons/keyboardmacro/CMakeLists.txt
View file @
dd11e707
...
...
@@ -2,12 +2,9 @@ kate_add_plugin(keyboardmacroplugin)
target_compile_definitions
(
keyboardmacroplugin PRIVATE TRANSLATION_DOMAIN=
"katekeyboardmacro"
)
target_link_libraries
(
keyboardmacroplugin PRIVATE KF5::I18n KF5::TextEditor
)
ki18n_wrap_ui
(
keyboardmacroplugin keyboardmacrowidget.ui
)
target_sources
(
keyboardmacroplugin
PRIVATE
plugin_katekeyboardmacro.cpp
plugin.qrc
)
addons/keyboardmacro/keyboardmacroplugin.json
View file @
dd11e707
{
"KPlugin"
:
{
"Description"
:
"Record and r
epla
y keyboard action sequence
s
"
,
"Description"
:
"Record and r
un an
y keyboard action sequence"
,
"Name"
:
"Keyboard Macro"
,
"ServiceTypes"
:
[
"KTextEditor/Plugin"
...
...
addons/keyboardmacro/plugin_katekeyboardmacro.cpp
View file @
dd11e707
/***************************************************************************
plugin_katekeyboardmacro.cpp - description
-------------------
begin : FRE Feb 23 2001
copyright : (C) 2001 by Joseph Wenninger <jowenn@bigfoot.com>
copyright : (C) 2009 Dominik Haumann <dhaumann kde org>
***************************************************************************/
/***************************************************************************
* *
* SPDX-License-Identifier: GPL-2.0-or-later
* *
***************************************************************************/
/*
* SPDX-FileCopyrightText: 2022 Pablo Rauzy <r .at. uzy .dot. me>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
"plugin_katekeyboardmacro.h"
#include
"ui_keyboardmacrowidget.h"
#include
<ktexteditor/editor.h>
#include
<ktexteditor/message.h>
#include
<KLineEdit>
#include
<KLocalizedString>
#include
<KMessageBox>
#include
<QAction>
#include
<QDialog>
#include
<QString>
#include
<KActionCollection>
#include
<KAuthorized>
#include
<KConfigGroup>
#include
<KPluginFactory>
#include
<KSharedConfig>
#include
<KXMLGUIFactory>
...
...
@@ -36,221 +20,142 @@
#include
<QApplication>
#include
<QClipboard>
#include
<iostream>
K_PLUGIN_FACTORY_WITH_JSON
(
KeyboardMacroPluginFactory
,
"keyboardmacroplugin.json"
,
registerPlugin
<
PluginKateKeyboardMacro
>
();)
PluginKateKeyboardMacro
::
PluginKateKeyboardMacro
(
QObject
*
parent
,
const
QList
<
QVariant
>
&
)
:
KTextEditor
::
Plugin
(
parent
)
{
// register command
new
PluginKateKeyboardMacroCommand
(
this
);
// register commands
m_recCommand
=
new
PluginKateKeyboardMacroRecordCommand
(
this
);
m_runCommand
=
new
PluginKateKeyboardMacroRunCommand
(
this
);
}
PluginKateKeyboardMacro
::~
PluginKateKeyboardMacro
()
{
// cleanup the process the right way (TM)
if
(
m_pFilterProcess
)
{
m_pFilterProcess
->
kill
();
m_pFilterProcess
->
waitForFinished
();
delete
m_pFilterProcess
;
}
delete
m_recCommand
;
delete
m_runCommand
;
}
QObject
*
PluginKateKeyboardMacro
::
createView
(
KTextEditor
::
MainWindow
*
mainWindow
)
QObject
*
PluginKateKeyboardMacro
::
createView
(
KTextEditor
::
MainWindow
*
)
{
m_mainWindow
=
mainWindow
;
// create a plugin view
return
new
PluginViewKateKeyboardMacro
(
this
,
mainWindow
);
return
nullptr
;
}
void
PluginKateKeyboardMacro
::
slotFilterReceivedStdout
(
)
bool
PluginKateKeyboardMacro
::
record
(
KTextEditor
::
View
*
)
{
m_strFilterOutput
+=
QString
::
fromLocal8Bit
(
m_pFilterProcess
->
readAllStandardOutput
());
}
void
PluginKateKeyboardMacro
::
slotFilterReceivedStderr
()
{
const
QString
block
=
QString
::
fromLocal8Bit
(
m_pFilterProcess
->
readAllStandardError
());
if
(
mergeOutput
)
{
m_strFilterOutput
+=
block
;
}
else
{
m_stderrOutput
+=
block
;
if
(
m_recording
)
{
// stop recording
std
::
cerr
<<
"stop recording"
<<
std
::
endl
;
m_recording
=
false
;
m_macro
=
QStringLiteral
(
"foobar"
);
return
true
;
// if success
}
std
::
cerr
<<
"start recording"
<<
std
::
endl
;
m_recording
=
true
;
return
true
;
}
void
PluginKateKeyboardMacro
::
slotFilterProcessExited
(
int
,
QProcess
::
ExitStatus
)
bool
PluginKateKeyboardMacro
::
run
(
KTextEditor
::
View
*
view
)
{
KTextEditor
::
View
*
kv
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
->
activeView
());
if
(
!
kv
)
{
return
;
}
// Is there any error output to display?
if
(
!
mergeOutput
&&
!
m_stderrOutput
.
isEmpty
())
{
QPointer
<
KTextEditor
::
Message
>
message
=
new
KTextEditor
::
Message
(
xi18nc
(
"@info"
,
"<title>Result of:</title><nl /><pre><code>$ %1
\n
<nl />%2</code></pre>"
,
m_last_command
,
m_stderrOutput
),
KTextEditor
::
Message
::
Error
);
message
->
setWordWrap
(
true
);
message
->
setAutoHide
(
1000
);
kv
->
document
()
->
postMessage
(
message
);
}
if
(
newDocument
)
{
auto
v
=
m_mainWindow
->
openUrl
(
QUrl
());
if
(
v
&&
v
->
document
())
{
v
->
document
()
->
setText
(
m_strFilterOutput
);
}
return
;
}
if
(
copyResult
)
{
QApplication
::
clipboard
()
->
setText
(
m_strFilterOutput
);
return
;
}
// Do not even try to change the document if no result collected...
if
(
m_strFilterOutput
.
isEmpty
())
{
return
;
if
(
m_recording
)
{
return
false
;
}
KTextEditor
::
Document
::
EditingTransaction
transaction
(
kv
->
document
());
KTextEditor
::
Cursor
start
=
kv
->
cursorPosition
();
if
(
kv
->
selection
())
{
start
=
kv
->
selectionRange
().
start
();
kv
->
removeSelectionText
();
if
(
m_macro
.
isEmpty
())
{
return
false
;
}
kv
->
setCursorPosition
(
start
);
// for block selection
kv
->
insertText
(
m_strFilterOutput
);
view
->
insertText
(
m_macro
);
return
true
;
}
static
void
slipInFilter
(
KProcess
&
proc
,
KTextEditor
::
View
&
view
,
const
QString
&
command
)
bool
PluginKateKeyboardMacro
::
isRecording
(
)
{
QString
inputText
;
return
m_recording
;
}
if
(
view
.
selection
())
{
inputText
=
view
.
selectionText
();
}
else
{
inputText
=
view
.
document
()
->
text
()
;
void
PluginKateKeyboardMacro
::
slotRecord
()
{
if
(
!
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
())
{
return
;
}
proc
.
clearProgram
();
proc
.
setShellCommand
(
command
);
KTextEditor
::
View
*
view
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
->
activeView
());
if
(
!
view
)
{
return
;
}
proc
.
start
();
QByteArray
encoded
=
inputText
.
toLocal8Bit
();
proc
.
write
(
encoded
);
proc
.
closeWriteChannel
();
// TODO: Put up a modal dialog to defend the text from further
// keystrokes while the command is out. With a cancel button...
record
(
view
);
}
void
PluginKateKeyboardMacro
::
slot
EditFilter
()
void
PluginKateKeyboardMacro
::
slot
Run
()
{
if
(
!
KAuthorized
::
authorize
(
QStringLiteral
(
"shell_access"
)))
{
KMessageBox
::
error
(
nullptr
,
i18n
(
"You are not allowed to execute arbitrary external applications. If "
"you want to be able to do this, contact your system administrator."
),
i18n
(
"Access Restrictions"
));
return
;
}
if
(
!
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
())
{
return
;
}
KTextEditor
::
View
*
k
v
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
->
activeView
());
if
(
!
k
v
)
{
KTextEditor
::
View
*
v
iew
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
->
activeView
());
if
(
!
v
iew
)
{
return
;
}
QDialog
dialog
(
KTextEditor
::
Editor
::
instance
()
->
application
()
->
activeMainWindow
()
->
window
());
Ui
::
KeyboardMacroWidget
ui
;
ui
.
setupUi
(
&
dialog
);
ui
.
filterBox
->
setFocus
();
dialog
.
setWindowTitle
(
i18n
(
"Text Filter"
));
KConfigGroup
config
(
KSharedConfig
::
openConfig
(),
"PluginKeyboardMacro"
);
QStringList
items
=
config
.
readEntry
(
"Completion list"
,
QStringList
());
copyResult
=
config
.
readEntry
(
"Copy result"
,
false
);
mergeOutput
=
config
.
readEntry
(
"Merge output"
,
true
);
newDocument
=
config
.
readEntry
(
"New Document"
,
false
);
ui
.
filterBox
->
setMaxCount
(
10
);
ui
.
filterBox
->
setHistoryItems
(
items
,
true
);
ui
.
filterBox
->
setMinimumContentsLength
(
80
);
ui
.
copyResult
->
setChecked
(
copyResult
);
ui
.
mergeOutput
->
setChecked
(
mergeOutput
);
ui
.
newDoc
->
setChecked
(
newDocument
);
if
(
dialog
.
exec
()
==
QDialog
::
Accepted
)
{
copyResult
=
ui
.
copyResult
->
isChecked
();
mergeOutput
=
ui
.
mergeOutput
->
isChecked
();
newDocument
=
ui
.
newDoc
->
isChecked
();
const
QString
filter
=
ui
.
filterBox
->
currentText
();
if
(
!
filter
.
isEmpty
())
{
ui
.
filterBox
->
addToHistory
(
filter
);
config
.
writeEntry
(
"New Document"
,
newDocument
);
config
.
writeEntry
(
"Completion list"
,
ui
.
filterBox
->
historyItems
());
config
.
writeEntry
(
"Copy result"
,
copyResult
);
config
.
writeEntry
(
"Merge output"
,
mergeOutput
);
m_last_command
=
filter
;
runFilter
(
kv
,
filter
);
}
}
run
(
view
);
}
void
PluginKateKeyboardMacro
::
runFilter
(
KTextEditor
::
View
*
kv
,
const
QString
&
filter
)
{
m_strFilterOutput
.
clear
();
m_stderrOutput
.
clear
();
if
(
!
m_pFilterProcess
)
{
m_pFilterProcess
=
new
KProcess
;
// BEGIN commands
connect
(
m_pFilterProcess
,
&
KProcess
::
readyReadStandardOutput
,
this
,
&
PluginKateKeyboardMacro
::
slotFilterReceivedStdout
);
connect
(
m_pFilterProcess
,
&
KProcess
::
readyReadStandardError
,
this
,
&
PluginKateKeyboardMacro
::
slotFilterReceivedStderr
);
PluginKateKeyboardMacroRecordCommand
::
PluginKateKeyboardMacroRecordCommand
(
PluginKateKeyboardMacro
*
plugin
)
:
KTextEditor
::
Command
(
QStringList
()
<<
QStringLiteral
(
"recmac"
),
plugin
)
,
m_plugin
(
plugin
)
{
}
connect
(
m_pFilterProcess
,
static_cast
<
void
(
KProcess
::*
)(
int
,
KProcess
::
ExitStatus
)
>
(
&
KProcess
::
finished
),
this
,
&
PluginKateKeyboardMacro
::
slotFilterProcessExited
);
bool
PluginKateKeyboardMacroRecordCommand
::
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
,
const
KTextEditor
::
Range
&
)
{
if
(
m_plugin
->
isRecording
())
{
// remove from the recording the call to this command…
}
m_pFilterProcess
->
setOutputChannelMode
(
mergeOutput
?
KProcess
::
MergedChannels
:
KProcess
::
SeparateChannels
);
slipInFilter
(
*
m_pFilterProcess
,
*
kv
,
filter
);
bool
success
=
m_plugin
->
record
(
view
);
if
(
!
success
)
{
// display fail in toolview
}
return
true
;
}
// BEGIN Kate::Command methods
bool
PluginKateKeyboardMacroRecordCommand
::
help
(
KTextEditor
::
View
*
,
const
QString
&
,
QString
&
msg
)
{
msg
=
i18n
(
"<qt><p>Usage: <code>recmac</code></p>"
"<p>Start/stop recording a keyboard macro.</p></qt>"
);
return
true
;
}
PluginKateKeyboardMacroCommand
::
PluginKateKeyboardMacroCommand
(
PluginKateKeyboardMacro
*
plugin
)
:
KTextEditor
::
Command
(
QStringList
()
<<
QStringLiteral
(
"
keyboard
mac
ro
"
),
plugin
)
PluginKateKeyboardMacro
Run
Command
::
PluginKateKeyboardMacro
Run
Command
(
PluginKateKeyboardMacro
*
plugin
)
:
KTextEditor
::
Command
(
QStringList
()
<<
QStringLiteral
(
"
run
mac"
),
plugin
)
,
m_plugin
(
plugin
)
{
}
bool
PluginKateKeyboardMacroCommand
::
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
cmd
,
QString
&
msg
,
const
KTextEditor
::
Range
&
)
bool
PluginKateKeyboardMacro
Run
Command
::
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
,
const
KTextEditor
::
Range
&
)
{
QString
filter
=
cmd
.
section
(
QLatin1Char
(
' '
),
1
).
trimmed
();
if
(
filter
.
isEmpty
())
{
msg
=
i18n
(
"Usage: keyboardmacro COMMAND"
);
return
false
;
bool
success
=
m_plugin
->
run
(
view
);
if
(
!
success
)
{
// display fail in toolview
}
m_plugin
->
runFilter
(
view
,
filter
);
return
true
;
}
bool
PluginKateKeyboardMacroCommand
::
help
(
KTextEditor
::
View
*
,
const
QString
&
,
QString
&
msg
)
bool
PluginKateKeyboardMacro
Run
Command
::
help
(
KTextEditor
::
View
*
,
const
QString
&
,
QString
&
msg
)
{
msg
=
i18n
(
"<qt><p>Usage: <code>
keyboardmacro COMMAND
</code></p>"
"<p>R
eplace the selection with the output of the specified shell command
.</p></qt>"
);
"<qt><p>Usage: <code>
runmac
</code></p>"
"<p>R
un recorded keyboard macro
.</p></qt>"
);
return
true
;
}
// END
PluginViewKateKeyboardMacro
::
PluginViewKateKeyboardMacro
(
PluginKateKeyboardMacro
*
plugin
,
KTextEditor
::
MainWindow
*
mainwindow
)
...
...
@@ -261,11 +166,17 @@ PluginViewKateKeyboardMacro::PluginViewKateKeyboardMacro(PluginKateKeyboardMacro
KXMLGUIClient
::
setComponentName
(
QStringLiteral
(
"keyboardmacro"
),
i18n
(
"Keyboard Macro"
));
setXMLFile
(
QStringLiteral
(
"ui.rc"
));
// create our one and only action
QAction
*
a
=
actionCollection
()
->
addAction
(
QStringLiteral
(
"record_macro"
));
a
->
setText
(
i18n
(
"&Record Macro..."
));
actionCollection
()
->
setDefaultShortcut
(
a
,
Qt
::
CTRL
|
Qt
::
ALT
|
Qt
::
Key_R
);
connect
(
a
,
&
QAction
::
triggered
,
plugin
,
&
PluginKateKeyboardMacro
::
slotEditFilter
);
// create record action
QAction
*
rec
=
actionCollection
()
->
addAction
(
QStringLiteral
(
"record_macro"
));
rec
->
setText
(
i18n
(
"&Record Macro..."
));
actionCollection
()
->
setDefaultShortcut
(
rec
,
Qt
::
CTRL
|
Qt
::
SHIFT
|
Qt
::
Key_K
);
connect
(
rec
,
&
QAction
::
triggered
,
plugin
,
&
PluginKateKeyboardMacro
::
slotRecord
);
// create run action
QAction
*
exec
=
actionCollection
()
->
addAction
(
QStringLiteral
(
"run_macro"
));
exec
->
setText
(
i18n
(
"&Run Macro"
));
actionCollection
()
->
setDefaultShortcut
(
exec
,
Qt
::
CTRL
|
Qt
::
ALT
|
Qt
::
Key_K
);
connect
(
exec
,
&
QAction
::
triggered
,
plugin
,
&
PluginKateKeyboardMacro
::
slotRun
);
// register us at the UI
mainwindow
->
guiFactory
()
->
addClient
(
this
);
...
...
addons/keyboardmacro/plugin_katekeyboardmacro.h
View file @
dd11e707
/***************************************************************************
plugin_katekeyboardmacro.h - description
-------------------
begin : FRE Feb 23 2001
copyright : (C) 2001 by Joseph Wenninger
email : jowenn@bigfoot.com
***************************************************************************/
/***************************************************************************
* *
* SPDX-License-Identifier: GPL-2.0-or-later
* *
***************************************************************************/
#ifndef PLUGIN_KATEKEYBOARDMACROS_H
#define PLUGIN_KATEKEYBOARDMACROS_H
/*
* SPDX-FileCopyrightText: 2022 Pablo Rauzy <r .at. uzy .dot. me>
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef PLUGIN_KATEKEYBOARDMACRO_H
#define PLUGIN_KATEKEYBOARDMACRO_H
#include
<KTextEditor/Application>
#include
<KTextEditor/Command>
...
...
@@ -22,8 +13,8 @@
#include
<KTextEditor/Plugin>
#include
<KTextEditor/View>
#include
<KProcess>
#include
<QVariantList>
class
PluginKateKeyboardMacroRecordCommand
;
class
PluginKateKeyboardMacroRunCommand
;
class
PluginKateKeyboardMacro
:
public
KTextEditor
::
Plugin
{
...
...
@@ -37,36 +28,53 @@ public:
~
PluginKateKeyboardMacro
()
override
;
QObject
*
createView
(
KTextEditor
::
MainWindow
*
mainWindow
)
override
;
virtual
QObject
*
createView
(
KTextEditor
::
MainWindow
*
mainWindow
)
override
;
void
runFilter
(
KTextEditor
::
View
*
kv
,
const
QString
&
filter
);
bool
record
(
KTextEditor
::
View
*
view
);
bool
run
(
KTextEditor
::
View
*
view
);
bool
isRecording
();
private:
QString
m_strFilterOutput
;
QString
m_stderrOutput
;
QString
m_last_command
;
KProcess
*
m_pFilterProcess
=
nullptr
;
QStringList
completionList
;
bool
copyResult
=
false
;
bool
mergeOutput
=
false
;
bool
newDocument
=
false
;
KTextEditor
::
MainWindow
*
m_mainWindow
;
bool
m_recording
=
false
;
QString
m_macro
;
PluginKateKeyboardMacroRecordCommand
*
m_recCommand
;
PluginKateKeyboardMacroRunCommand
*
m_runCommand
;
public
Q_SLOTS
:
void
slotEditFilter
();
void
slotFilterReceivedStdout
();
void
slotFilterReceivedStderr
();
void
slotFilterProcessExited
(
int
exitCode
,
QProcess
::
ExitStatus
exitStatus
);
void
slotRecord
();
void
slotRun
();
};
class
PluginKateKeyboardMacroCommand
:
public
KTextEditor
::
Command
/**
* recmac command
*/
class
PluginKateKeyboardMacroRecordCommand
:
public
KTextEditor
::
Command
{
Q_OBJECT
public:
PluginKateKeyboardMacroRecordCommand
(
PluginKateKeyboardMacro
*
plugin
);
// Kate::Command
bool
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
,
const
KTextEditor
::
Range
&
=
KTextEditor
::
Range
::
invalid
())
override
;
bool
help
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
msg
)
override
;
private:
PluginKateKeyboardMacro
*
m_plugin
;
};
/**
* runmac command
*/
class
PluginKateKeyboardMacroRunCommand
:
public
KTextEditor
::
Command
{
Q_OBJECT
public:
PluginKateKeyboardMacroCommand
(
PluginKateKeyboardMacro
*
plugin
);
PluginKateKeyboardMacro
Run
Command
(
PluginKateKeyboardMacro
*
plugin
);
// Kate::Command
bool
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
cmd
,
QString
&
msg
,
const
KTextEditor
::
Range
&
range
=
KTextEditor
::
Range
::
invalid
())
override
;
bool
help
(
KTextEditor
::
View
*
view
,
const
QString
&
cmd
,
QString
&
msg
)
override
;
bool
exec
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
,
const
KTextEditor
::
Range
&
=
KTextEditor
::
Range
::
invalid
())
override
;
bool
help
(
KTextEditor
::
View
*
view
,
const
QString
&
,
QString
&
msg
)
override
;
private:
PluginKateKeyboardMacro
*
m_plugin
;
...
...
addons/keyboardmacro/ui.rc
View file @
dd11e707
...
...
@@ -5,6 +5,7 @@
<Menu
name=
"tools"
>
<text>
&
Tools
</text>
<Action
name=
"record_macro"
group=
"tools_snippets"
/>
<Action
name=
"run_macro"
group=
"tools_snippets"
/>
</Menu>
</MenuBar>
</gui>
...
...
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