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.
tdewebdev/kommander/widget/kommanderfunctions.cpp

350 lines
10 KiB

/***************************************************************************
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 <textstream.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();
case Kommander::echo:
for (uint i=0; i<args.count(); i++)
std::cout << args[i].latin1();
fflush(stdout);
return TQString();
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();
}
case Kommander::writeSetting:
{
TQString fname = fileName();
if (!fname.isEmpty())
{
KConfig cfg("kommanderrc", false);
cfg.setGroup(fname);
cfg.writeEntry(args[0], args[1]);
}
return TQString();
}
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();
}