You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaddons/kate/textfilter/plugin_katetextfilter.cpp

336 lines
9.2 KiB

/***************************************************************************
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 <tdeaction.h>
#include <kinstance.h>
#include <klineeditdlg.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <cassert>
#include <kdebug.h>
#include <tqstring.h>
#include <tdetexteditor/editinterfaceext.h>
#include <tdeapplication.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( TQObject* parent, const char* name, const TQStringList& )
: 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 TDEAction ( i18n("Filter Te&xt..."), /*"edit_filter",*/ CTRL + Key_Backslash, this,
TQT_SLOT( slotEditFilter() ), view->actionCollection(), "edit_filter" );
view->setInstance (new TDEInstance("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 (TQString q, char c, TQStringList &list) // PCP
{
// screw the OnceAndOnlyOnce Principle!
int pos;
TQString 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, TQString pre, TQString marked, TQString 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 TQString // PCP
KatePrompt
(
const TQString & strTitle,
const TQString & strPrompt,
TQWidget * that,
TQStringList *completionList
)
{
// TODO: Make this a "memory edit" field with a combo box
// containing prior entries
KLineEditDlg dlg(strPrompt, TQString(), that);
dlg.setCaption(strTitle);
TDECompletion *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 (TDEProcess * pProcess, char * got, int len)
{
assert (pProcess == m_pFilterShellProcess);
if (got && len)
{
// TODO: got a better idea?
// while (len--) m_strFilterOutput += *got++;
m_strFilterOutput += TQString::fromLocal8Bit( got, len );
// POP_(m_strFilterOutput);
}
}
void
PluginKateTextFilter::slotFilterReceivedStderr (TDEProcess * pProcess, char * got, int len)
{
slotFilterReceivedStdout (pProcess, got, len);
}
void
PluginKateTextFilter::slotFilterProcessExited (TDEProcess * 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();
TQString 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, TQString command)
{
TQString marked = view.getDoc()->selection ();
if( marked.isEmpty())
return;
// POP_(command.latin1 ());
shell.clearArguments ();
shell << command;
shell.start (TDEProcess::NotifyOnExit, TDEProcess::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 (TDEProcess * 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;
TQString text ( KatePrompt ( i18n("Filter"),
i18n("Enter command to pipe selected text through:"),
(TQWidget*) kv,
&completionList
) );
if ( !text.isEmpty () )
runFilter( kv, text );
}
void PluginKateTextFilter::runFilter( Kate::View *kv, const TQString &filter )
{
m_strFilterOutput = "";
if (!m_pFilterShellProcess)
{
m_pFilterShellProcess = new KShellProcess;
connect ( m_pFilterShellProcess, TQT_SIGNAL(wroteStdin(TDEProcess *)),
this, TQT_SLOT(slotFilterCloseStdin (TDEProcess *)));
connect ( m_pFilterShellProcess, TQT_SIGNAL(receivedStdout(TDEProcess*,char*,int)),
this, TQT_SLOT(slotFilterReceivedStdout(TDEProcess*,char*,int)) );
connect ( m_pFilterShellProcess, TQT_SIGNAL(receivedStderr(TDEProcess*,char*,int)),
this, TQT_SLOT(slotFilterReceivedStderr(TDEProcess*,char*,int)) );
connect ( m_pFilterShellProcess, TQT_SIGNAL(processExited(TDEProcess*)),
this, TQT_SLOT(slotFilterProcessExited(TDEProcess*) ) ) ;
}
slipInFilter (*m_pFilterShellProcess, *kv, filter);
}
//BEGIN Kate::Command methods
TQStringList PluginKateTextFilter::cmds()
{
return TQStringList("textfilter");
}
bool PluginKateTextFilter::help( Kate::View *, const TQString&, TQString &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 TQString &cmd, TQString &msg )
{
if (! v->getDoc()->hasSelection() )
{
msg = i18n("You need to have a selection to use textfilter");
return false;
}
TQString filter = cmd.section( " ", 1 ).stripWhiteSpace();
if ( filter.isEmpty() )
{
msg = i18n("Usage: textfilter COMMAND");
return false;
}
runFilter( v, filter );
return true;
}
//END