|
|
|
/***************************************************************************
|
|
|
|
kommanderfunctions.cpp - Text widget core functionality
|
|
|
|
-------------------
|
|
|
|
copyright : (C) 2004 Michal Rudolf <mrudolf@kdewebdwev.org>
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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 <iostream>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
|
|
|
|
#include <dcopclient.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
|
|
|
|
#include "kommanderwidget.h"
|
|
|
|
#include "specials.h"
|
|
|
|
#include "specialinformation.h"
|
|
|
|
#include "expression.h"
|
|
|
|
#include "parser.h"
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalFunction(const TQString& function, const TQStringList& args)
|
|
|
|
{
|
|
|
|
switch (SpecialInformation::function(Group::Kommander, function)) {
|
|
|
|
case Kommander::widgetText:
|
|
|
|
return handleDCOP(DCOP::text);
|
|
|
|
case Kommander::selectedWidgetText:
|
|
|
|
return handleDCOP(DCOP::selection);
|
|
|
|
case Kommander::dcopid:
|
|
|
|
return kapp->dcopClient()->appId();
|
|
|
|
case Kommander::pid:
|
|
|
|
return TQString().setNum(getpid());
|
|
|
|
case Kommander::null:
|
|
|
|
return TQString();
|
|
|
|
case Kommander::comment:
|
|
|
|
return TQString("#");
|
|
|
|
case Kommander::exec:
|
|
|
|
return execCommand(args[0]);
|
|
|
|
case Kommander::dcop:
|
|
|
|
return DCOPQuery(args);
|
|
|
|
case Kommander::parentPid:
|
|
|
|
return global("_PARENTPID").isEmpty() ? TQString().setNum(getppid()) : global("_PARENTPID");
|
|
|
|
case Kommander::env:
|
|
|
|
return TQString(getenv(args[0].latin1()));
|
|
|
|
case Kommander::i18n:
|
|
|
|
return KGlobal::locale()->translate(args[0]);
|
|
|
|
case Kommander::global:
|
|
|
|
return global(args[0]);
|
|
|
|
case Kommander::setGlobal:
|
|
|
|
setGlobal(args[0], args[1]);
|
|
|
|
return TQString();
|
|
|
|
case Kommander::debug:
|
|
|
|
qDebug("%s", args[0].latin1());
|
|
|
|
fflush(stderr);
|
|
|
|
return TQString::null;
|
|
|
|
case Kommander::echo:
|
|
|
|
for (uint i=0; i<args.count(); i++)
|
|
|
|
std::cout << args[i].latin1();
|
|
|
|
fflush(stdout);
|
|
|
|
return TQString::null;
|
|
|
|
case Kommander::readSetting:
|
|
|
|
{
|
|
|
|
TQString fname = fileName();
|
|
|
|
if (!fname.isEmpty())
|
|
|
|
{
|
|
|
|
KConfig cfg("kommanderrc", true);
|
|
|
|
cfg.setGroup(fname);
|
|
|
|
return cfg.readEntry(args[0], args[1]);
|
|
|
|
}
|
|
|
|
return TQString::null;
|
|
|
|
}
|
|
|
|
case Kommander::writeSetting:
|
|
|
|
{
|
|
|
|
TQString fname = fileName();
|
|
|
|
if (!fname.isEmpty())
|
|
|
|
{
|
|
|
|
KConfig cfg("kommanderrc", false);
|
|
|
|
cfg.setGroup(fname);
|
|
|
|
cfg.writeEntry(args[0], args[1]);
|
|
|
|
}
|
|
|
|
return TQString::null;
|
|
|
|
}
|
|
|
|
case Kommander::dialog:
|
|
|
|
if (args.count() > 1)
|
|
|
|
return runDialog(args[0], args[1]);
|
|
|
|
else
|
|
|
|
return runDialog(args[0]);
|
|
|
|
case Kommander::expr:
|
|
|
|
{
|
|
|
|
Expression expr(args[0]);
|
|
|
|
bool ok;
|
|
|
|
TQVariant value = expr.value(&ok);
|
|
|
|
return ok ? value.toString() : TQString();
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalExecBlock(const TQStringList& args, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
int f = s.find("@execEnd", pos);
|
|
|
|
if (f == -1)
|
|
|
|
{
|
|
|
|
printError(i18n("Unterminated @execBegin ... @execEnd block."));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQString shell = args.count() ? args[0] : TQString();
|
|
|
|
int start = pos;
|
|
|
|
pos = f + TQString("@execEnd").length()+1;
|
|
|
|
return execCommand(evalAssociatedText(s.mid(start, f - start)), shell);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalForEachBlock(const TQStringList& args, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
int f = s.find("@end", pos);
|
|
|
|
//FIXME: better detection of block boundaries
|
|
|
|
if (f == -1)
|
|
|
|
{
|
|
|
|
printError(i18n("Unterminated @forEach ... @end block."));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int start = pos;
|
|
|
|
pos = f + TQString("@end").length()+1;
|
|
|
|
TQString var = args[0];
|
|
|
|
TQStringList loop = TQStringList::split("\n", args[1]);
|
|
|
|
TQString output;
|
|
|
|
TQString block = substituteVariable(s.mid(start, f - start), TQString("%1_count").arg(var),
|
|
|
|
TQString::number(loop.count()));
|
|
|
|
TQString varidx = TQString("%1_index").arg(var);
|
|
|
|
for (uint i=0; i<loop.count(); i++)
|
|
|
|
output += evalAssociatedText(substituteVariable(substituteVariable(block, varidx, TQString::number(i+1)),
|
|
|
|
var, loop[i]));
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalForBlock(const TQStringList& args, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
int f = s.find("@end", pos);
|
|
|
|
//FIXME: better detection of block boundaries
|
|
|
|
if (f == -1)
|
|
|
|
{
|
|
|
|
printError(i18n("Unterminated @forEach ... @end block."));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int start = pos;
|
|
|
|
pos = f + TQString("@end").length()+1;
|
|
|
|
TQString block = s.mid(start, f - start);
|
|
|
|
TQString variable = args[0];
|
|
|
|
|
|
|
|
Expression expr;
|
|
|
|
int loopstart = expr.value(args[1]).toInt();
|
|
|
|
int loopend = expr.value(args[2]).toInt();
|
|
|
|
int loopstep = 1;
|
|
|
|
if (args.count() > 3)
|
|
|
|
{
|
|
|
|
loopstep = expr.value(args[3]).toInt();
|
|
|
|
if (!loopstep)
|
|
|
|
loopstep = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString output;
|
|
|
|
for (int i=loopstart; i<=loopend; i+=loopstep)
|
|
|
|
{
|
|
|
|
output += evalAssociatedText(substituteVariable(block, variable, TQString::number(i)));
|
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalIfBlock(const TQStringList& args, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
int f = s.find("@endif", pos);
|
|
|
|
//FIXME: better detection of block boundaries; add error message
|
|
|
|
if (f == -1)
|
|
|
|
{
|
|
|
|
pos = s.length()+1;
|
|
|
|
printError(i18n("Unterminated @if ... @endif block."));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQString block = s.mid(pos, f - pos);
|
|
|
|
pos = f + TQString("@endif").length()+1;
|
|
|
|
Expression expr;
|
|
|
|
if (expr.isTrue(args[0]))
|
|
|
|
return evalAssociatedText(block);
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalSwitchBlock(const TQStringList& args, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
int f = s.find("@end", pos);
|
|
|
|
//FIXME: better detection of block boundaries; add error message
|
|
|
|
if (f == -1)
|
|
|
|
{
|
|
|
|
printError(i18n("Unterminated @switch ... @end block."));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQString block = s.mid(pos, f - pos);
|
|
|
|
pos = f + TQString("@end").length()+1;
|
|
|
|
f = parseBlockBoundary(block, 0, "@case");
|
|
|
|
bool finished = f == -1;
|
|
|
|
while (!finished)
|
|
|
|
{
|
|
|
|
f += 5;
|
|
|
|
int end = parseBlockBoundary(block, f, "@case");
|
|
|
|
if (end == -1)
|
|
|
|
{
|
|
|
|
end = block.length();
|
|
|
|
finished = true;
|
|
|
|
}
|
|
|
|
bool ok;
|
|
|
|
TQString value = parseBrackets(block, f, ok);
|
|
|
|
if (!ok)
|
|
|
|
break;
|
|
|
|
if (value == args[0] || value == "*")
|
|
|
|
return evalAssociatedText(block.mid(f, end-f));
|
|
|
|
f = end;
|
|
|
|
}
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalArrayFunction(const TQString& function, const TQStringList& args)
|
|
|
|
{
|
|
|
|
Parser parser(internalParserData());
|
|
|
|
int fname = SpecialInformation::function(Group::Array, function);
|
|
|
|
TQString array = args[0].startsWith("_") ? args[0] : TQString("_")+ args[0];
|
|
|
|
|
|
|
|
if (fname == Array::setValue)
|
|
|
|
parser.setArray(array, args[1], args[2]);
|
|
|
|
else if (fname == Array::fromString)
|
|
|
|
{
|
|
|
|
TQStringList lines = TQStringList::split("\n", args[1]);
|
|
|
|
for (TQStringList::Iterator it = lines.begin(); it != lines.end(); ++it)
|
|
|
|
{
|
|
|
|
TQString key = (*it).section('\t', 0, 0).stripWhiteSpace();
|
|
|
|
if (!key.isEmpty())
|
|
|
|
parser.setArray(array, key, (*it).section('\t', 1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!parser.isArray(array))
|
|
|
|
return TQString();
|
|
|
|
else switch (fname) {
|
|
|
|
case Array::value:
|
|
|
|
return parser.arrayValue(array, args[1]).toString();
|
|
|
|
case Array::keys:
|
|
|
|
{
|
|
|
|
const TQMap<TQString, ParseNode> map = parser.array(array);
|
|
|
|
TQStringList keys;
|
|
|
|
for (TQMap<TQString, ParseNode>::ConstIterator it = map.begin(); it != map.end(); ++it)
|
|
|
|
keys.append(it.key());
|
|
|
|
return keys.join("\n");
|
|
|
|
}
|
|
|
|
case Array::values:
|
|
|
|
{
|
|
|
|
const TQMap<TQString, ParseNode> map = parser.array(array);
|
|
|
|
TQStringList values;
|
|
|
|
for (TQMap<TQString, ParseNode>::ConstIterator it = map.begin(); it != map.end(); ++it)
|
|
|
|
values.append(it.data().toString());
|
|
|
|
return values.join("\n");
|
|
|
|
}
|
|
|
|
case Array::clear:
|
|
|
|
parser.unsetArray(array);
|
|
|
|
return TQString();
|
|
|
|
case Array::remove:
|
|
|
|
parser.unsetArray(array, args[1]);
|
|
|
|
return TQString();
|
|
|
|
case Array::count:
|
|
|
|
return TQString::number(parser.array(array).count());
|
|
|
|
case Array::toString:
|
|
|
|
{
|
|
|
|
const TQMap<TQString, ParseNode> map = parser.array(array);
|
|
|
|
TQString arraystring;
|
|
|
|
for (TQMap<TQString, ParseNode>::ConstIterator it = map.begin(); it != map.end(); ++it)
|
|
|
|
arraystring += TQString("%1\t%2\n").arg(it.key()).arg(it.data().toString());
|
|
|
|
return arraystring;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString KommanderWidget::evalWidgetFunction(const TQString& identifier, const TQString& s, int& pos)
|
|
|
|
{
|
|
|
|
KommanderWidget* pWidget = parseWidget(identifier);
|
|
|
|
if (!pWidget)
|
|
|
|
{
|
|
|
|
printError(i18n("Unknown widget: @%1.").arg(identifier));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
if (s[pos] == '.')
|
|
|
|
{
|
|
|
|
pos++;
|
|
|
|
bool ok = true;
|
|
|
|
TQString function = parseIdentifier(s, pos);
|
|
|
|
TQStringList args = parseFunction("DCOP", function, s, pos, ok);
|
|
|
|
if (!ok)
|
|
|
|
return TQString();
|
|
|
|
args.prepend(pWidget->widgetName());
|
|
|
|
TQString prototype = SpecialInformation::prototype(Group::DCOP,
|
|
|
|
SpecialInformation::function(Group::DCOP, function));
|
|
|
|
return localDCOPQuery(prototype, args);
|
|
|
|
}
|
|
|
|
else if (pWidget == this)
|
|
|
|
{
|
|
|
|
printError(i18n("Infinite loop: @%1 called inside @%2.").arg(pWidget->widgetName())
|
|
|
|
.arg(pWidget->widgetName()));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
else if (!pWidget->hasAssociatedText())
|
|
|
|
{
|
|
|
|
printError(i18n("Script for @%1 is empty.").arg(pWidget->widgetName()));
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
return pWidget->evalAssociatedText();
|
|
|
|
}
|
|
|
|
|