2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
13 #include <QApplication>
20 #include <QTextCursor>
24 #include <boost/scoped_ptr.hpp>
25 #include <kstandarddirs.h>
30 #include "histlineedit.h"
31 #include "highlighter.h"
32 #include "mastersettings.h"
35 class BackInserterPatternIteratorAdaptor
: public PatternListAdaptorOutputIterator
{
36 std::vector
<Highlighter::Pattern
>& m_vector
;
38 BackInserterPatternIteratorAdaptor(std::vector
<Highlighter::Pattern
>& vector
)
39 : m_vector(vector
) { }
41 virtual void add(const Highlighter::Pattern
& p
) {
42 m_vector
.push_back(p
);
47 ConsoleOutput::ConsoleOutput(QTextEdit
* edit
, bool force_scroll
)
49 m_old_val
= m_edit
->verticalScrollBar()->value();
50 m_scroll_to
= force_scroll
|| (m_edit
->verticalScrollBar()->value()
51 >= m_edit
->verticalScrollBar()->maximum() );
53 QTextCursor cursor
= m_edit
->textCursor();
54 cursor
.movePosition(QTextCursor::End
);
55 m_edit
->setTextCursor(cursor
);
58 ConsoleOutput::~ConsoleOutput() {
60 m_edit
->verticalScrollBar()->setValue(m_edit
->verticalScrollBar()->maximum());
62 m_edit
->verticalScrollBar()->setValue(m_old_val
);
63 //m_edit->ensureCursorVisible();
66 void ConsoleOutput::operator()(const QString
& text
) {
67 m_edit
->insertPlainText(text
);
70 LuaConsoleHighlighter::LuaConsoleHighlighter()
72 KStandardDirs
* dirs
= KGlobal::dirs();
74 QString luaHighlightingLibrary
= dirs
->locate("appdata", "scripts/hllib.lua");
75 std::cout
<< "lua lib: " << luaHighlightingLibrary
<< std::endl
;
76 m_api
.runFile(qPrintable(luaHighlightingLibrary
));
78 QStringList highlighting
= dirs
->findAllResources("appdata", "highlighting/*.lua", KStandardDirs::Recursive
);
79 foreach (QString f
, highlighting
) {
80 std::cout
<< "lua highlighting file: " << f
<< std::endl
;
81 m_api
.runFile(qPrintable(f
));
85 void LuaConsoleHighlighter::setDisplay(QTextEdit
* display
) {
89 LuaConsoleHighlighter::Executor::Executor(QTextEdit
* display
, ConsoleOutput
& output
)
91 , m_output(output
) { }
93 void LuaConsoleHighlighter::Executor::writeChunk(const QString
& text
) {
97 void LuaConsoleHighlighter::Executor::setFormat(const QTextCharFormat
& format
) {
98 m_display
->setCurrentCharFormat(format
);
101 LuaConsoleHighlighter::Executor::~Executor() {
105 void LuaConsoleHighlighter::operator()(const QString
& text
, ConsoleOutput
& output
) {
106 QStringList lines
= text
.split('\n');
108 for (int i
= 0; i
< lines
.size(); i
++) {
109 const QString
& line
= lines
[i
];
110 boost::scoped_ptr
<HLine
> hline(m_api
.highlight(line
));
112 Executor
executor(m_display
, output
);
113 hline
->run(executor
);
114 if (i
< lines
.size() - 1) output("\n");
120 ConsoleHighlighter::ConsoleHighlighter()
122 BackInserterPatternIteratorAdaptor
out(m_patterns
);
123 Highlighter::load(out
);
126 void ConsoleHighlighter::setDisplay(QTextEdit
* display
) {
128 m_basic_format
= m_display
->currentCharFormat();
131 void ConsoleHighlighter::operator()(const QString
& text
, ConsoleOutput
& output
) {
135 m_display
->setCurrentCharFormat(m_basic_format
);
139 int best_offset
= -1;
142 // try each pattern and find the closest matching one
143 for (uint i
= 0; i
< m_patterns
.size(); i
++) {
144 int match_offset
= text
.indexOf(m_patterns
[i
].pattern
, offset
);
145 if (match_offset
>= 0 &&
146 (best_offset
== -1 || match_offset
< best_offset
)) {
147 int length
= m_patterns
[i
].pattern
.matchedLength();
150 best_offset
= match_offset
;
151 best_length
= length
;
157 // output the portion of the text before the matching
159 // std::cout << "outputting plain: " << text.mid(offset, best_offset - offset) << std::endl;
160 // std::cout << "weight = " << m_display->currentCharFormat().fontWeight() << std::endl;
161 output(text
.mid(offset
, best_offset
- offset
));
164 m_display
->setCurrentCharFormat(m_patterns
[best
].format
);
166 // output the matching substring
167 // std::cout << "outputting formatted: " << text.mid(best_offset, best_length) << std::endl;
168 // std::cout << "weight = " << m_display->currentCharFormat().fontWeight() << std::endl;
169 output(text
.mid(best_offset
, best_length
));
171 // restore basic format
172 m_display
->setCurrentCharFormat(m_basic_format
);
173 // std::cout << "restored" << std::endl;
174 // std::cout << "weight = " << m_display->currentCharFormat().fontWeight() << std::endl;
177 offset
= best_offset
+ best_length
;
182 // output the last portion of the text
183 // std::cout << "outputting plain: " << text.mid(offset) << std::endl;
184 output(text
.mid(offset
));
185 // std::cout << "weight = " << m_display->currentCharFormat().fontWeight() << std::endl;
189 QRegExp
Console::promptRegexp("([a-zA-Z0-9]*% )");
191 Console::Console(QWidget
* parent
, const QString
& caption
)
193 setObjectName("console");
196 setWindowTitle(caption
);
198 QBoxLayout
* layout
= new QVBoxLayout(this);
199 QHBoxLayout
* promptLayout
= new QHBoxLayout
;
200 layout
->setMargin(0);
201 layout
->setSpacing(0);
202 promptLayout
->setMargin(0);
203 promptLayout
->setSpacing(0);
205 edit
= new HistLineEdit(this);
206 display
= new QTextEdit(this);
207 prompt
= new QLabel(this);
211 layout
->addWidget(display
);
212 layout
->addLayout(promptLayout
);
214 promptLayout
->addWidget(prompt
);
215 promptLayout
->addWidget(edit
);
217 display
->setFocusProxy(edit
);
218 display
->setReadOnly(true);
219 ////display->setTextFormat(QTextEdit::PlainText);
220 display
->setAcceptRichText(false);
221 display
->setWordWrapMode (QTextOption::NoWrap
);
222 display
->setUndoRedoEnabled (false);
223 Settings s_console
= settings().group("console");
224 if (!s_console
["font"]) {
225 QFont f
= QApplication::font();
226 f
.setFamily("Monospace");
227 s_console
["font"] = f
;
229 display
->setFont(s_console
["font"].value
<QFont
>());
231 display
->setFontWeight(QFont::Normal
);
232 m_highlighter
.setDisplay(display
);
234 connect(edit
, SIGNAL(receivedInput(const QString
&)),
235 this, SLOT(input(const QString
&)));
238 void Console::echo(const QString
& text
) {
239 ConsoleOutput
output(display
, true);
240 display
->setFontWeight(QFont::Bold
);
242 display
->setFontWeight(QFont::Normal
);
245 void Console::input(const QString
& text
) {
246 if (edit
->echoMode() == QLineEdit::Password
) {
247 // edit->setEchoMode(QLineEdit::Normal);
248 echo("(password sent)");
251 // echo inputted text
256 m_notifier
->textNotify(text
);
260 void Console::displayText(QString text
, int offset
) {
261 if (offset
== 0 && promptRegexp
.indexIn(text
) == 0) {
262 prompt
->setText(" " + promptRegexp
.cap(1));
263 offset
+= promptRegexp
.cap(1).length();
266 text
= text
.mid(offset
);
267 text
.replace("\t", " ");
269 QByteArray bytes
= text
.toAscii();
270 if (bytes
.contains("\xff\xfc\x01")) {
271 edit
->setEchoMode(QLineEdit::Normal
);
273 else if (bytes
.contains("\xff\xfb\x01")) {
274 edit
->setEchoMode(QLineEdit::Password
);
277 if (text
[offset
].isPrint()) {
278 ConsoleOutput
output(display
);
279 m_highlighter(text
, output
);
283 void Console::clear() {