summaryrefslogtreecommitdiffstats
path: root/kate/textfilter/plugin_katetextfilter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kate/textfilter/plugin_katetextfilter.cpp')
-rw-r--r--kate/textfilter/plugin_katetextfilter.cpp336
1 files changed, 336 insertions, 0 deletions
diff --git a/kate/textfilter/plugin_katetextfilter.cpp b/kate/textfilter/plugin_katetextfilter.cpp
new file mode 100644
index 0000000..b5cd1ac
--- /dev/null
+++ b/kate/textfilter/plugin_katetextfilter.cpp
@@ -0,0 +1,336 @@
+/***************************************************************************
+ plugin_katetextfilter.cpp - description
+ -------------------
+ begin : FRE Feb 23 2001
+ copyright : (C) 2001 by Joseph Wenninger
+ email : jowenn@bigfoot.com
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "plugin_katetextfilter.h"
+#include "plugin_katetextfilter.moc"
+
+#include <kaction.h>
+#include <kinstance.h>
+#include <klineeditdlg.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <cassert>
+#include <kdebug.h>
+#include <qstring.h>
+#include <ktexteditor/editinterfaceext.h>
+#include <kapplication.h>
+#include <kcompletion.h>
+#include <klineedit.h>
+#define POP_(x) kdDebug(13000) << #x " = " << flush << x << endl
+
+#include <kgenericfactory.h>
+
+K_EXPORT_COMPONENT_FACTORY( katetextfilterplugin, KGenericFactory<PluginKateTextFilter>( "katetextfilter" ) )
+
+class PluginView : public KXMLGUIClient
+{
+ friend class PluginKateTextFilter;
+
+ public:
+ Kate::MainWindow *win;
+};
+
+PluginKateTextFilter::PluginKateTextFilter( QObject* parent, const char* name, const QStringList& )
+ : Kate::Plugin ( (Kate::Application *)parent, name ),
+ Kate::Command(),
+ m_pFilterShellProcess (NULL)
+{
+ Kate::Document::registerCommand( this );
+}
+
+PluginKateTextFilter::~PluginKateTextFilter()
+{
+ delete m_pFilterShellProcess;
+ Kate::Document::unregisterCommand( this );
+}
+
+void PluginKateTextFilter::addView(Kate::MainWindow *win)
+{
+ // TODO: doesn't this have to be deleted?
+ PluginView *view = new PluginView ();
+
+ (void) new KAction ( i18n("Filter Te&xt..."), /*"edit_filter",*/ CTRL + Key_Backslash, this,
+ SLOT( slotEditFilter() ), view->actionCollection(), "edit_filter" );
+
+ view->setInstance (new KInstance("kate"));
+ view->setXMLFile( "plugins/katetextfilter/ui.rc" );
+ win->guiFactory()->addClient (view);
+ view->win = win;
+
+ m_views.append (view);
+}
+
+void PluginKateTextFilter::removeView(Kate::MainWindow *win)
+{
+ for (uint z=0; z < m_views.count(); z++)
+ if (m_views.at(z)->win == win)
+ {
+ PluginView *view = m_views.at(z);
+ m_views.remove (view);
+ win->guiFactory()->removeClient (view);
+ delete view;
+ }
+}
+
+ void
+splitString (QString q, char c, QStringList &list) // PCP
+{
+
+// screw the OnceAndOnlyOnce Principle!
+
+ int pos;
+ QString item;
+
+ while ( (pos = q.find(c)) >= 0)
+ {
+ item = q.left(pos);
+ list.append(item);
+ q.remove(0,pos+1);
+ }
+ list.append(q);
+}
+
+
+ static void // PCP
+slipInNewText (Kate::View & view, QString pre, QString marked, QString post, bool reselect)
+{
+
+ uint preDeleteLine = 0, preDeleteCol = 0;
+ view.cursorPosition (&preDeleteLine, &preDeleteCol);
+
+ if (marked.length() > 0)
+ view.keyDelete ();
+ uint line = 0, col = 0;
+ view.cursorPosition (&line, &col);
+ view.insertText (pre + marked + post);
+
+ // all this muck to leave the cursor exactly where the user
+ // put it...
+
+ // Someday we will can all this (unless if it already
+ // is canned and I didn't find it...)
+
+ // The second part of the if disrespects the display bugs
+ // when we try to reselect. TODO: fix those bugs, and we can
+ // un-break this if...
+
+ // TODO: fix OnceAndOnlyOnce between this module and plugin_katehtmltools.cpp
+
+ if (reselect && preDeleteLine == line && -1 == marked.find ('\n'))
+ if (preDeleteLine == line && preDeleteCol == col)
+ {
+ view.setCursorPosition (line, col + pre.length () + marked.length () - 1);
+
+ for (int x (marked.length()); x--;)
+ view.shiftCursorLeft ();
+ }
+ else
+ {
+ view.setCursorPosition (line, col += pre.length ());
+
+ for (int x (marked.length()); x--;)
+ view.shiftCursorRight ();
+ }
+
+}
+
+
+ static QString // PCP
+KatePrompt
+ (
+ const QString & strTitle,
+ const QString & strPrompt,
+ QWidget * that,
+ QStringList *completionList
+ )
+{
+ // TODO: Make this a "memory edit" field with a combo box
+ // containing prior entries
+
+ KLineEditDlg dlg(strPrompt, QString::null, that);
+ dlg.setCaption(strTitle);
+ KCompletion *comple=dlg.lineEdit()->completionObject();
+ comple->setItems(*completionList);
+ if (dlg.exec()) {
+ if (!dlg.text().isEmpty()) {
+ comple->addItem(dlg.text());
+ (*completionList)=comple->items();
+ }
+ return dlg.text();
+ }
+ else
+ return "";
+}
+
+
+ void
+PluginKateTextFilter::slotFilterReceivedStdout (KProcess * pProcess, char * got, int len)
+{
+
+ assert (pProcess == m_pFilterShellProcess);
+
+ if (got && len)
+ {
+
+ // TODO: got a better idea?
+
+// while (len--) m_strFilterOutput += *got++;
+ m_strFilterOutput += QString::fromLocal8Bit( got, len );
+// POP_(m_strFilterOutput);
+ }
+
+}
+
+
+ void
+PluginKateTextFilter::slotFilterReceivedStderr (KProcess * pProcess, char * got, int len)
+ {
+ slotFilterReceivedStdout (pProcess, got, len);
+ }
+
+
+ void
+PluginKateTextFilter::slotFilterProcessExited (KProcess * pProcess)
+{
+
+ assert (pProcess == m_pFilterShellProcess);
+ Kate::View * kv (application()->activeMainWindow()->viewManager()->activeView());
+ if (!kv) return;
+ KTextEditor::EditInterfaceExt *ext=KTextEditor::editInterfaceExt(kv->getDoc());
+ if (ext) ext->editBegin();
+ QString marked = kv->getDoc()->selection ();
+ if (marked.length() > 0)
+ kv -> keyDelete ();
+ kv -> insertText (m_strFilterOutput);
+ if (ext) ext->editEnd();
+// slipInNewText (*kv, "", m_strFilterOutput, "", false);
+ m_strFilterOutput = "";
+
+}
+
+
+ static void // PCP
+slipInFilter (KShellProcess & shell, Kate::View & view, QString command)
+{
+ QString marked = view.getDoc()->selection ();
+ if( marked.isEmpty())
+ return;
+// POP_(command.latin1 ());
+ shell.clearArguments ();
+ shell << command;
+
+ shell.start (KProcess::NotifyOnExit, KProcess::All);
+ shell.writeStdin (marked.local8Bit (), marked.length ());
+ // TODO: Put up a modal dialog to defend the text from further
+ // keystrokes while the command is out. With a cancel button...
+
+}
+
+
+ void
+PluginKateTextFilter::slotFilterCloseStdin (KProcess * pProcess)
+ {
+ assert (pProcess == m_pFilterShellProcess);
+ pProcess -> closeStdin ();
+ }
+
+
+ void
+PluginKateTextFilter::slotEditFilter () // PCP
+{
+ if (!kapp->authorize("shell_access")) {
+ KMessageBox::sorry(0,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 (!application()->activeMainWindow())
+ return;
+
+ Kate::View * kv (application()->activeMainWindow()->viewManager()->activeView());
+ if (!kv) return;
+
+ QString text ( KatePrompt ( i18n("Filter"),
+ i18n("Enter command to pipe selected text through:"),
+ (QWidget*) kv,
+ &completionList
+ ) );
+
+ if ( !text.isEmpty () )
+ runFilter( kv, text );
+}
+
+void PluginKateTextFilter::runFilter( Kate::View *kv, const QString &filter )
+{
+ m_strFilterOutput = "";
+
+ if (!m_pFilterShellProcess)
+ {
+ m_pFilterShellProcess = new KShellProcess;
+
+ connect ( m_pFilterShellProcess, SIGNAL(wroteStdin(KProcess *)),
+ this, SLOT(slotFilterCloseStdin (KProcess *)));
+
+ connect ( m_pFilterShellProcess, SIGNAL(receivedStdout(KProcess*,char*,int)),
+ this, SLOT(slotFilterReceivedStdout(KProcess*,char*,int)) );
+
+ connect ( m_pFilterShellProcess, SIGNAL(receivedStderr(KProcess*,char*,int)),
+ this, SLOT(slotFilterReceivedStderr(KProcess*,char*,int)) );
+
+ connect ( m_pFilterShellProcess, SIGNAL(processExited(KProcess*)),
+ this, SLOT(slotFilterProcessExited(KProcess*) ) ) ;
+ }
+
+ slipInFilter (*m_pFilterShellProcess, *kv, filter);
+}
+
+//BEGIN Kate::Command methods
+QStringList PluginKateTextFilter::cmds()
+{
+ return QStringList("textfilter");
+}
+
+bool PluginKateTextFilter::help( Kate::View *, const QString&, QString &msg )
+{
+ msg = i18n(
+ "<qt><p>Usage: <code>textfilter COMMAND</code></p>"
+ "<p>Replace the selection with the output of the specified shell command.</p></qt>");
+ return true;
+}
+
+bool PluginKateTextFilter::exec( Kate::View *v, const QString &cmd, QString &msg )
+{
+ if (! v->getDoc()->hasSelection() )
+ {
+ msg = i18n("You need to have a selection to use textfilter");
+ return false;
+ }
+
+ QString filter = cmd.section( " ", 1 ).stripWhiteSpace();
+
+ if ( filter.isEmpty() )
+ {
+ msg = i18n("Usage: textfilter COMMAND");
+ return false;
+ }
+
+ runFilter( v, filter );
+ return true;
+}
+//END
+// kate: space-indent on; indent-width 2; replace-tabs on; mixed-indent off;