forked from qt-creator/qt-creator
Allow not only a colon as a keyword-text divider in todos.
This makes possible to scan such things as doxygen \todo, @todo entries where colons cannot be added after a keyword. Change-Id: I13c757294c94a1f4758e7dc9634a79ea6e91c68f Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
This commit is contained in:
committed by
Eike Ziller
parent
b6b2441e55
commit
9fe784115a
@@ -35,6 +35,7 @@
|
||||
#include "keyword.h"
|
||||
#include "ui_keyworddialog.h"
|
||||
#include "constants.h"
|
||||
#include "lineparser.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
|
||||
@@ -124,7 +125,7 @@ void KeywordDialog::setupColorWidgets(const QColor &color)
|
||||
bool KeywordDialog::canAccept()
|
||||
{
|
||||
if (!isKeywordNameCorrect()) {
|
||||
showError(tr("Keyword cannot be empty, contain spaces or colons."));
|
||||
showError(tr("Keyword cannot be empty, contain spaces, colons, slashes or asterisks."));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -146,7 +147,7 @@ bool KeywordDialog::isKeywordNameCorrect()
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < name.size(); ++i)
|
||||
if (name.at(i).isSpace() || name.at(i) == QLatin1Char(':'))
|
||||
if (LineParser::isKeywordSeparator(name.at(i)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@@ -38,10 +38,6 @@
|
||||
namespace Todo {
|
||||
namespace Internal {
|
||||
|
||||
LineParser::LineParser()
|
||||
{
|
||||
}
|
||||
|
||||
LineParser::LineParser(const KeywordList &keywordList)
|
||||
{
|
||||
setKeywordList(keywordList);
|
||||
@@ -59,6 +55,14 @@ QList<TodoItem> LineParser::parse(const QString &line)
|
||||
return todoItemsFromKeywordEntries(entries);
|
||||
}
|
||||
|
||||
bool LineParser::isKeywordSeparator(const QChar &ch)
|
||||
{
|
||||
return ch.isSpace()
|
||||
|| (ch == QLatin1Char(':'))
|
||||
|| (ch == QLatin1Char('/'))
|
||||
|| (ch == QLatin1Char('*'));
|
||||
}
|
||||
|
||||
LineParser::KeywordEntryCandidates LineParser::findKeywordEntryCandidates(const QString &line)
|
||||
{
|
||||
KeywordEntryCandidates entryCandidates;
|
||||
@@ -66,27 +70,40 @@ LineParser::KeywordEntryCandidates LineParser::findKeywordEntryCandidates(const
|
||||
for (int i = 0; i < m_keywords.count(); ++i) {
|
||||
int searchFrom = -1;
|
||||
forever {
|
||||
const int index = line.lastIndexOf(m_keywords.at(i).name
|
||||
+ QLatin1Char(':'), searchFrom);
|
||||
const int index = line.lastIndexOf(m_keywords.at(i).name, searchFrom);
|
||||
|
||||
if (index == -1)
|
||||
break; // 'forever' loop exit condition
|
||||
|
||||
searchFrom = index - line.length() - 1;
|
||||
|
||||
if (!isFirstCharOfTheWord(index, line))
|
||||
continue;
|
||||
|
||||
entryCandidates.insert(index, i);
|
||||
if (isKeywordAt(index, line, m_keywords.at(i).name))
|
||||
entryCandidates.insert(index, i);
|
||||
}
|
||||
}
|
||||
|
||||
return entryCandidates;
|
||||
}
|
||||
|
||||
bool LineParser::isKeywordAt(int index, const QString &line, const QString &keyword)
|
||||
{
|
||||
if (!isFirstCharOfTheWord(index, line))
|
||||
return false;
|
||||
|
||||
if (!isLastCharOfTheWord(index + keyword.length() - 1, line))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LineParser::isFirstCharOfTheWord(int index, const QString &line)
|
||||
{
|
||||
return (index == 0) || !line.at(index - 1).isLetterOrNumber();
|
||||
return (index == 0) || isKeywordSeparator(line.at(index - 1));
|
||||
}
|
||||
|
||||
bool LineParser::isLastCharOfTheWord(int index, const QString &line)
|
||||
{
|
||||
return (index == line.length() - 1) || isKeywordSeparator(line.at(index + 1));
|
||||
}
|
||||
|
||||
QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
||||
@@ -109,15 +126,15 @@ QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
||||
entry.keywordStart = i.key();
|
||||
entry.keywordIndex = i.value();
|
||||
|
||||
int keywordLength = m_keywords.at(entry.keywordIndex).name.length() + 1; // include colon
|
||||
int keywordLength = m_keywords.at(entry.keywordIndex).name.length();
|
||||
|
||||
int entryTextLength = -1;
|
||||
if (!entries.empty())
|
||||
entryTextLength = entries.last().keywordStart - (entry.keywordStart + keywordLength);
|
||||
|
||||
entry.text = line.mid(entry.keywordStart + keywordLength, entryTextLength).trimmed();
|
||||
entry.text = line.mid(entry.keywordStart + keywordLength, entryTextLength);
|
||||
|
||||
if (entry.text.isEmpty() && !entries.empty())
|
||||
if (trimSeparators(entry.text).isEmpty() && !entries.empty())
|
||||
// Take the text form the previous entry, consider:
|
||||
// '<keyword1>: <keyword2>: <some text>'
|
||||
entry.text = entries.last().text;
|
||||
@@ -128,14 +145,36 @@ QList<LineParser::KeywordEntry> LineParser::keywordEntriesFromCandidates(
|
||||
return entries;
|
||||
}
|
||||
|
||||
QString LineParser::trimSeparators(const QString &string)
|
||||
{
|
||||
QString result = string.trimmed();
|
||||
|
||||
while (startsWithSeparator(result))
|
||||
result = result.right(result.length() - 1);
|
||||
|
||||
while (endsWithSeparator(result))
|
||||
result = result.left(result.length() - 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LineParser::startsWithSeparator(const QString &string)
|
||||
{
|
||||
return !string.isEmpty() && isKeywordSeparator(string.at(0));
|
||||
}
|
||||
|
||||
bool LineParser::endsWithSeparator(const QString &string)
|
||||
{
|
||||
return !string.isEmpty() && isKeywordSeparator(string.at(string.length() - 1));
|
||||
}
|
||||
|
||||
QList<TodoItem> LineParser::todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries)
|
||||
{
|
||||
QList<TodoItem> todoItems;
|
||||
|
||||
foreach (const KeywordEntry &entry, entries) {
|
||||
TodoItem item;
|
||||
item.text = m_keywords.at(entry.keywordIndex).name
|
||||
+ QLatin1String(": ") + entry.text;
|
||||
item.text = m_keywords.at(entry.keywordIndex).name + entry.text;
|
||||
item.color = m_keywords.at(entry.keywordIndex).color;
|
||||
item.iconResource = m_keywords.at(entry.keywordIndex).iconResource;
|
||||
todoItems << item;
|
||||
|
@@ -43,12 +43,14 @@ namespace Internal {
|
||||
class LineParser
|
||||
{
|
||||
public:
|
||||
LineParser();
|
||||
explicit LineParser(const KeywordList &keywordList);
|
||||
|
||||
void setKeywordList(const KeywordList &keywordList);
|
||||
QList<TodoItem> parse(const QString &line);
|
||||
|
||||
// This can also be used from KeywordDialog to avoid code duplication
|
||||
static bool isKeywordSeparator(const QChar &ch);
|
||||
|
||||
private:
|
||||
|
||||
// map key here is keyword start position in the text line
|
||||
@@ -62,8 +64,13 @@ private:
|
||||
};
|
||||
|
||||
KeywordEntryCandidates findKeywordEntryCandidates(const QString &line);
|
||||
bool isKeywordAt(int index, const QString &line, const QString &keyword);
|
||||
bool isFirstCharOfTheWord(int index, const QString &line);
|
||||
bool isLastCharOfTheWord(int index, const QString &line);
|
||||
QList<KeywordEntry> keywordEntriesFromCandidates(const QMap<int, int> &candidates, const QString &line);
|
||||
QString trimSeparators(const QString &string);
|
||||
bool startsWithSeparator(const QString &string);
|
||||
bool endsWithSeparator(const QString &string);
|
||||
QList<TodoItem> todoItemsFromKeywordEntries(const QList<KeywordEntry> &entries);
|
||||
|
||||
KeywordList m_keywords;
|
||||
|
Reference in New Issue
Block a user