/* * Copyright (C) 2008 Martin Hostettler * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ // manager mini command system #include #include "mcmdmanager.h" MCmdSimpleState::MCmdSimpleState(QString name, QString prompt) { name_ = name; prompt_ = prompt; } MCmdSimpleState::MCmdSimpleState(QString name, QString prompt, int flags) { name_ = name; prompt_ = prompt; flags_ = flags; } MCmdSimpleState::~MCmdSimpleState() { } MCmdManager::MCmdManager(MCmdUiSiteIface* site_) : state_(0), uiSite_(site_) { }; MCmdManager::~MCmdManager() { foreach(MCmdProviderIface *prov, providers_) { prov->mCmdSiteDestroyed(); } } QStringList MCmdManager::parseCommand(const QString command, int pos, int &part, QString &partial, int &start, int &end, char "edAtPos) { QStringList list; QString item; bool escape=false; int quote=0; // "=1, '=2 bool space=true; int partStart = 0; quotedAtPos = 0; for (int i=0; i < command.length(); i++) { if (i == pos) { part = list.size(); partial = item; end = i; start = partStart; if (quote) quotedAtPos = (quote == 1) ? '"' : '\''; } QChar ch = command[i]; if (escape) { escape = false; item += ch; } else if (ch == '\\') { escape = true; } else if (quote != 0) { if ((quote == 1 && ch == '"') || (quote == 2 && ch == '\'')) { quote = 0; } else { item += ch; } } else if (ch == ' ') { partStart = i+1; if (space) { continue; } list << item; item = ""; space = true; continue; } else if (ch == '\'') { quote = 2; } else if (ch == '"') { quote = 1; } else { item += ch; } space = false; } if (command.length() == pos) { part = list.size(); partial = item; end = command.length(); start = partStart; if (quote) quotedAtPos = (quote == 1) ? '"' : '\''; } if (!space) list << item; return list; } QString MCmdManager::serializeCommand(const QStringList &list) { QString retval; bool needspace = false; QRegExp specials("([\"\'\\\\ ])"); foreach(QString item, list) { item.replace(specials, "\\\\1"); if (item == "") item = "\"\""; if (needspace) retval += " "; retval += item; needspace = true; } return retval; } bool MCmdManager::processCommand(QString command) { MCmdStateIface *tmpstate=0; QStringList preset; QStringList items; if (state_->getFlags() & MCMDSTATE_UNPARSED) { items << command; } else { int tmp_1; QString tmp_2; char tmp_3; items = parseCommand(command, -1, tmp_1, tmp_2, tmp_1, tmp_1, tmp_3); } foreach(MCmdProviderIface *prov, providers_) { if (prov->mCmdTryStateTransit(state_, items, tmpstate, preset)) { state_ = tmpstate; if (state_ != 0) { QString prompt = state_->getPrompt(); QString def; if (state_->getFlags() & MCMDSTATE_UNPARSED) { if (preset.size() == 1) { def = preset.at(0); } } else { def = serializeCommand(preset); } uiSite_->mCmdReady(prompt, def); } else { uiSite_->mCmdClose(); } return true; } } tmpstate = state_; bool ret = state_->unhandled(items); state_ = 0; if (state_ == 0) { tmpstate->dispose(); uiSite_->mCmdClose(); } return ret; } bool MCmdManager::open(MCmdStateIface *state, QStringList preset) { if (0 != state_) state_->dispose(); state_ = state; QString prompt = state->getPrompt(); QString def; if (state_->getFlags() & MCMDSTATE_UNPARSED) { if (preset.size() == 1) def = preset.at(0); } else { def = serializeCommand(preset); } uiSite_->mCmdReady(prompt, def); return true; } QStringList MCmdManager::completeCommand(QString &command, int pos, int &start, int &end) { int part; QString query; char quotedAtPos; QStringList all; if (state_->getFlags() & MCMDSTATE_UNPARSED) { all << command; query = command.left(pos); part = -1; } else { all = parseCommand(command, pos, part, query, start, end, quotedAtPos); } QStringList res; foreach(MCmdProviderIface *prov, providers_) { res += prov->mCmdTryCompleteCommand(state_, query, all, part); } res.sort(); QStringList quoted; if ((state_->getFlags() & MCMDSTATE_UNPARSED) == 0) { foreach(QString str, res) { QString trail; if (str.size() > 1 && str.at(str.size()-1) == QChar(0)) { str.chop(1); trail = " "; } str = str.replace("\\", "\\\\"); if (quotedAtPos == 0) { quoted << str.replace(" ", "\\ ").replace("\"", "\\\"").replace("'", "\\'") + trail; } else { quoted << quotedAtPos + str.replace(quotedAtPos, QString("\\") + quotedAtPos) + trail; } } } else { quoted = res; } return quoted; } bool MCmdManager::isActive() { return state_ != 0; } void MCmdManager::registerProvider(MCmdProviderIface *prov) { if (! providers_.contains(prov)) { providers_ += prov; } }