[rkward-cvs] SF.net SVN: rkward:[3535] trunk/rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Thu May 5 16:04:37 UTC 2011
Revision: 3535
http://rkward.svn.sourceforge.net/rkward/?rev=3535&view=rev
Author: tfry
Date: 2011-05-05 16:04:37 +0000 (Thu, 05 May 2011)
Log Message:
-----------
Add function rk.print.code() to print _highlighted_ R code to the output window.
Note: Much of the implementation details is stolen from the katepart export plugin (LGPL v2)
Modified Paths:
--------------
trunk/rkward/ChangeLog
trunk/rkward/rkward/rbackend/rinterface.cpp
trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
trunk/rkward/rkward/rbackend/rpackages/rkward/man/rk.results.Rd
trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp
trunk/rkward/rkward/windows/rkcommandeditorwindow.h
Modified: trunk/rkward/ChangeLog
===================================================================
--- trunk/rkward/ChangeLog 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/ChangeLog 2011-05-05 16:04:37 UTC (rev 3535)
@@ -1,3 +1,4 @@
+- Added function rk.print.code() to write highlighted R code to the output window # TODO: Next, implement the 'carbon copy' feature
- Box plot plugin gains support for grouped outcome data
- Fixed: Pressing Ctrl+C would not reset syntactically incomplete commands in the R console
- Crosstabs N to 1 plugin gains options to compute proportions and margins (thanks to Andrés Necochea)
Modified: trunk/rkward/rkward/rbackend/rinterface.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rinterface.cpp 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/rkward/rbackend/rinterface.cpp 2011-05-05 16:04:37 UTC (rev 3535)
@@ -624,6 +624,8 @@
} else {
RK_ASSERT (false);
}
+ } else if (call == "highlightRCode") {
+ issueCommand (".rk.set.reply (" + RObject::rQuote (RKCommandHighlighter::commandToHTML (calllist.value (1))) + ")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
} else if (call == "getWorkspaceUrl") {
KUrl url = RObjectList::getObjectList ()->getWorkspaceURL ();
if (!url.isEmpty ()) issueCommand (".rk.set.reply (" + RObject::rQuote (url.url ()) + ")", RCommand::App | RCommand::Sync, QString::null, 0, 0, in_chain);
Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/R/public.R 2011-05-05 16:04:37 UTC (rev 3535)
@@ -193,6 +193,10 @@
}
}
+"rk.print.code" <- function(code) {
+ .rk.cat.output (.rk.do.call ("highlightRCode", as.character (code)))
+}
+
"rk.header" <- function (title, parameters=list (), level=1) {
sink (rk.get.output.html.file(), append=TRUE)
on.exit (sink ())
Modified: trunk/rkward/rkward/rbackend/rpackages/rkward/man/rk.results.Rd
===================================================================
--- trunk/rkward/rkward/rbackend/rpackages/rkward/man/rk.results.Rd 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/rkward/rbackend/rpackages/rkward/man/rk.results.Rd 2011-05-05 16:04:37 UTC (rev 3535)
@@ -1,5 +1,6 @@
\name{rk.results}
\alias{rk.print}
+\alias{rk.print.code}
\alias{rk.print.literal}
\alias{rk.header}
\alias{rk.results}
@@ -14,6 +15,7 @@
\usage{
rk.print(x, ...)
rk.print.literal(x)
+rk.print.code(code)
rk.header(title, parameters = list(), level = 1)
rk.results(x, titles = NULL)
rk.describe.alternative(x)
@@ -21,6 +23,7 @@
\arguments{
\item{x}{any R object to be printed/exported. A suitable list in case of \code{rk.describe.alternative}.}
+\item{code}{a character vector (single string) of R code}
\item{title}{a string, used as a header for the html output}
\item{level}{an integer, header level. For example, \code{level=2} creates the header with \code{<h2></h>} tag.}
\item{parameters}{a list, preferably named, giving a list of "parameters" to be printed to the output}
@@ -32,8 +35,10 @@
\code{rk.print.literal} prints/exports the given object using a \code{paste(x, collapse="\n")} construct to the output (html) file.
-\code{rk.header} prints a html header, possibly with parameters, to the output file. See example.
+\code{rk.print.code} applies syntax highlighting to the given code string, and writes it to the output (html) file.
+\code{rk.header} prints a header / caption, possibly with parameters, to the output file. See example.
+
\code{rk.results} is similar to \code{rk.print} but prints in a more tabulated fashion. This has been implemented only for certain types of \code{x}: tables, lists (or data.frames), and vectors. See example.
\code{rk.describe.alternatives} describes the alternative (H1) hypothesis of a \code{htest}. This is similar to \code{stats:::print.htext} and makes sense only when \code{x$alternatives} exists.
@@ -61,6 +66,7 @@
nm <- rk.get.description (x1,x2)
result <- t.test (x1, x2, alternative="less")
+rk.print.code ("result <- t.test (x1, x2, alternative=\"less\")")
rk.header (result$method,
parameters=list ("Comparing", paste (nm[1], "against", nm[2]),
Modified: trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp
===================================================================
--- trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/rkward/windows/rkcommandeditorwindow.cpp 2011-05-05 16:04:37 UTC (rev 3535)
@@ -80,6 +80,13 @@
#define GET_HELP_URL 1
#define NUM_BLOCK_RECORDS 6
+/** set syntax highlighting-mode to R syntax. Outside of class, in order to allow use from the on demand code highlighter */
+void setRHighlighting (KTextEditor::Document *doc) {
+ RK_TRACE (COMMANDEDITOR);
+
+ if (!doc->setHighlightingMode("R Script")) RK_DO (qDebug ("R syntax highlighting defintion not found!"), COMMANDEDITOR, DL_ERROR);
+}
+
RKCommandEditorWindow::RKCommandEditorWindow (QWidget *parent, bool use_r_highlighting) : RKMDIWindow (parent, RKMDIWindow::CommandEditorWindow) {
RK_TRACE (COMMANDEDITOR);
@@ -128,7 +135,7 @@
cc_iface = 0;
hinter = 0;
if (use_r_highlighting) {
- setRHighlighting ();
+ setRHighlighting (m_doc);
cc_iface = qobject_cast<KTextEditor::CodeCompletionInterface*> (m_view);
if (cc_iface) {
cc_iface->setAutomaticInvocationEnabled (true);
@@ -324,14 +331,6 @@
QWidget::closeEvent (e);
}
-// KDE4 TODO: inline
-void RKCommandEditorWindow::setRHighlighting () {
- RK_TRACE (COMMANDEDITOR);
-
- // set syntax-highlighting for R
- if (!m_doc->setHighlightingMode("R Script")) RK_DO (qDebug ("R syntax highlighting defintion not found!"), COMMANDEDITOR, DL_ERROR);
-}
-
void RKCommandEditorWindow::copy () {
RK_TRACE (COMMANDEDITOR);
@@ -350,7 +349,7 @@
// encoding must be set *before* loading the file
if (!encoding.isEmpty ()) m_doc->setEncoding (encoding);
if (m_doc->openUrl (url)){
- if (use_r_highlighting) setRHighlighting ();
+ if (use_r_highlighting) setRHighlighting (m_doc);
setReadOnly (read_only);
updateCaption ();
@@ -1034,4 +1033,130 @@
return QVariant ();
}
+
+
+// static
+KTextEditor::Document* RKCommandHighlighter::_doc = 0;
+KTextEditor::Document* RKCommandHighlighter::getDoc () {
+ if (_doc) return _doc;
+
+ RK_TRACE (COMMANDEDITOR);
+ KTextEditor::Editor* editor = KTextEditor::editor("katepart");
+ RK_ASSERT (editor);
+
+ _doc = editor->createDocument (RKWardMainWindow::getMain ());
+// NOTE: In KDE 4.4.5, a (dummy) view is needed to access highlighting attributes. According to a katepart error message, this will be fixed, eventually.
+// TODO: check whether this is fixed in some later version of KDE
+ QWidget* view = _doc->createView (0);
+ view->hide ();
+ RK_ASSERT (_doc);
+ setRHighlighting (_doc);
+ return _doc;
+}
+
+#if KDE_IS_VERSION(4,4,0)
+# include <ktexteditor/highlightinterface.h>
+#include <QTextDocument>
+
+//////////
+// NOTE: Most of the exporting code is copied from the katepart HTML exporter plugin more or less verbatim! (Source license: LGPL v2)
+//////////
+QString exportText(const QString& text, const KTextEditor::Attribute::Ptr& attrib, const KTextEditor::Attribute::Ptr& m_defaultAttribute) {
+ if ( !attrib || !attrib->hasAnyProperty() || attrib == m_defaultAttribute ) {
+ return (Qt::escape(text));
+ }
+
+ QString ret;
+ if ( attrib->fontBold() ) {
+ ret.append ("<b>");
+ }
+ if ( attrib->fontItalic() ) {
+ ret.append ("<i>");
+ }
+
+ bool writeForeground = attrib->hasProperty(QTextCharFormat::ForegroundBrush)
+ && (!m_defaultAttribute || attrib->foreground().color() != m_defaultAttribute->foreground().color());
+ bool writeBackground = attrib->hasProperty(QTextCharFormat::BackgroundBrush)
+ && (!m_defaultAttribute || attrib->background().color() != m_defaultAttribute->background().color());
+
+ if ( writeForeground || writeBackground ) {
+ ret.append (QString("<span style='%1%2'>")
+ .arg(writeForeground ? QString(QLatin1String("color:") + attrib->foreground().color().name() + QLatin1Char(';')) : QString())
+ .arg(writeBackground ? QString(QLatin1String("background:") + attrib->background().color().name() + QLatin1Char(';')) : QString()));
+ }
+
+ ret.append (Qt::escape(text));
+
+ if ( writeBackground || writeForeground ) {
+ ret.append ("</span>");
+ }
+ if ( attrib->fontItalic() ) {
+ ret.append ("</i>");
+ }
+ if ( attrib->fontBold() ) {
+ ret.append ("</b>");
+ }
+
+ return ret;
+}
+
+QString RKCommandHighlighter::commandToHTML (const QString r_command) {
+ KTextEditor::Document* doc = getDoc ();
+ KTextEditor::HighlightInterface *iface = qobject_cast<KTextEditor::HighlightInterface*> (_doc);
+ RK_ASSERT (iface);
+ if (!iface) return (QString ("<pre>") + r_command + "</pre>");
+
+ doc->setText (r_command);
+ setRHighlighting (doc);
+ QString ret;
+ KTextEditor::Attribute::Ptr m_defaultAttribute = iface->defaultStyle(KTextEditor::HighlightInterface::dsNormal);
+ if ( !m_defaultAttribute ) {
+ ret = "<pre>";
+ } else {
+ ret = QString("<pre style='%1%2%3%4'>")
+ .arg(m_defaultAttribute->fontBold() ? "font-weight:bold;" : "")
+ .arg(m_defaultAttribute->fontItalic() ? "text-style:italic;" : "")
+ .arg("color:" + m_defaultAttribute->foreground().color().name() + ';');
+// .arg("background-color:" + m_defaultAttribute->background().color().name() + ';');
+ }
+
+ const KTextEditor::Attribute::Ptr noAttrib(0);
+
+ for (int i = 0; i < doc->lines (); ++i)
+ {
+ const QString &line = doc->line(i);
+
+ QList<KTextEditor::HighlightInterface::AttributeBlock> attribs = iface->lineAttributes(i);
+
+ int lineStart = 0;
+ int remainingChars = line.length();
+ int handledUntil = lineStart;
+
+ foreach ( const KTextEditor::HighlightInterface::AttributeBlock& block, attribs ) {
+ int start = qMax(block.start, lineStart);
+ if ( start > handledUntil ) {
+ ret += exportText( line.mid( handledUntil, start - handledUntil ), noAttrib, m_defaultAttribute );
+ }
+ int length = qMin(block.length, remainingChars);
+ ret += exportText( line.mid( start, length ), block.attribute, m_defaultAttribute);
+ handledUntil = start + length;
+ }
+
+ if ( handledUntil < lineStart + remainingChars ) {
+ ret += exportText( line.mid( handledUntil, remainingChars ), noAttrib, m_defaultAttribute );
+ }
+
+ if (i < (doc->lines () - 1)) ret.append ("\n");
+ }
+ ret.append ("</pre>\n");
+
+ return ret;
+}
+
+#else // KDE < 4.4: No Highlighting Interface
+QString RKCommandHighlighter::commandToHTML (const QString r_command) {
+ return (QString ("<pre>") + r_command + "</pre>");
+}
+#endif
+
#include "rkcommandeditorwindow.moc"
Modified: trunk/rkward/rkward/windows/rkcommandeditorwindow.h
===================================================================
--- trunk/rkward/rkward/windows/rkcommandeditorwindow.h 2011-04-27 18:23:48 UTC (rev 3534)
+++ trunk/rkward/rkward/windows/rkcommandeditorwindow.h 2011-05-05 16:04:37 UTC (rev 3535)
@@ -251,8 +251,6 @@
RKCodeCompletionModel *completion_model;
QTimer *completion_timer;
-/** set syntax highlighting-mode to R syntax */
- void setRHighlighting ();
void initializeActions (KActionCollection* ac);
@@ -293,4 +291,13 @@
KUrl delete_on_close;
};
+/** Simple class to provide HTML highlighting for arbitrary R code. */
+class RKCommandHighlighter {
+public:
+ static QString commandToHTML (const QString r_command);
+private:
+ static KTextEditor::Document* getDoc ();
+ static KTextEditor::Document* _doc;
+};
+
#endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the rkward-tracker
mailing list