summaryrefslogtreecommitdiffstats
path: root/kate/part/kateautoindent.h
diff options
context:
space:
mode:
Diffstat (limited to 'kate/part/kateautoindent.h')
-rw-r--r--kate/part/kateautoindent.h581
1 files changed, 581 insertions, 0 deletions
diff --git a/kate/part/kateautoindent.h b/kate/part/kateautoindent.h
new file mode 100644
index 000000000..76ba14ee6
--- /dev/null
+++ b/kate/part/kateautoindent.h
@@ -0,0 +1,581 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 2003 Jesse Yurkovich <yurkjes@iit.edu>
+ Copyright (C) 2004 >Anders Lund <anders@alweb.dk> (KateVarIndent class)
+ Copyright (C) 2005 Dominik Haumann <dhdev@gmx.de> (basic support for config page)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KATE_AUTO_INDENT_H__
+#define __KATE_AUTO_INDENT_H__
+
+#include <qobject.h>
+
+#include "katecursor.h"
+#include "kateconfig.h"
+#include "katejscript.h"
+class KateDocument;
+
+/**
+ * This widget will be embedded into a modal dialog when clicking
+ * the "Configure..." button in the indentation config page.
+ * To add a config page for an indenter there are several todos:
+ * - Derive a class from this class. This widget will be embedded into
+ * the config dialog.
+ * - Override the slot @p apply(), which is called when the configuration
+ * needs to be saved.
+ * - Override @p KateAutoIndent::configPage() to return an instance of
+ * this dialog.
+ * - Return @p true in @p KateAutoIndent::hasConfigPage() for the
+ * corresponding indenter id.
+ */
+class IndenterConfigPage : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Standard constructor
+ * @param parent parent widget
+ * @param name name
+ */
+ IndenterConfigPage ( QWidget *parent=0, const char *name=0 ) : QWidget(parent, name) {}
+ virtual ~IndenterConfigPage () {}
+
+ public slots:
+ /**
+ * Apply the changes. Save options here, use @p kapp->config() and
+ * group [Kate Indenter MyIndenter].
+ */
+ virtual void apply () = 0;
+};
+
+/**
+ * Provides Auto-Indent functionality for katepart.
+ * This baseclass is a real dummy, does nothing beside remembering the document it belongs too,
+ * only to have the object around
+ */
+class KateAutoIndent : public QObject
+{
+ Q_OBJECT
+
+ /**
+ * Static methods to create and list indention modes
+ */
+ public:
+ /**
+ * Create an indenter
+ * @param doc document for the indenter
+ * @param mode indention mode wanted
+ * @return created autoindention object
+ */
+ static KateAutoIndent *createIndenter (KateDocument *doc, uint mode);
+
+ /**
+ * List all possible modes by name
+ * @return list of modes
+ */
+ static QStringList listModes ();
+
+ /**
+ * Return the mode name given the mode
+ * @param mode mode index
+ * @return name for this mode index
+ */
+ static QString modeName (uint mode);
+
+ /**
+ * Return the mode description
+ * @param mode mode index
+ * @return mode index
+ */
+ static QString modeDescription (uint mode);
+
+ /**
+ * Maps name -> index
+ * @param name mode name
+ * @return mode index
+ */
+ static uint modeNumber (const QString &name);
+
+ /**
+ * Config page support
+ * @param mode mode index
+ * @return true, if the indenter @p mode has a configuration page
+ */
+ static bool hasConfigPage (uint mode);
+
+ /**
+ * Support for a config page.
+ * @return config page or 0 if not available.
+ */
+ static IndenterConfigPage* configPage(QWidget *parent, uint mode);
+
+ public:
+ /**
+ * Constructor
+ * @param doc parent document
+ */
+ KateAutoIndent (KateDocument *doc);
+
+ /**
+ * Virtual Destructor for the baseclass
+ */
+ virtual ~KateAutoIndent ();
+
+ public slots:
+ /**
+ * Update indenter's configuration (indention width, attributes etc.)
+ */
+ virtual void updateConfig () {};
+
+ public:
+ /**
+ * does this indenter support processNewLine
+ * @return can you do it?
+ */
+ virtual bool canProcessNewLine () const { return false; }
+
+ /**
+ * Called every time a newline character is inserted in the document.
+ *
+ * @param cur The position to start processing. Contains the new cursor position after the indention.
+ * @param needContinue Used to determine whether to calculate a continue indent or not.
+ */
+ virtual void processNewline (KateDocCursor &cur, bool needContinue) { Q_UNUSED(cur); Q_UNUSED(needContinue); }
+
+ /**
+ * Called every time a character is inserted into the document.
+ * @param c character inserted
+ */
+ virtual void processChar (QChar c) { Q_UNUSED(c); }
+
+ /**
+ * Aligns/indents the given line to the proper indent position.
+ */
+ virtual void processLine (KateDocCursor &/*line*/) { }
+
+ /**
+ * Processes a section of text, indenting each line in between.
+ */
+ virtual void processSection (const KateDocCursor &/*begin*/, const KateDocCursor &/*end*/) { }
+
+ /**
+ * Set to true if an actual implementation of 'processLine' is present.
+ * This is used to prevent a needless Undo action from being created.
+ */
+ virtual bool canProcessLine() const { return false; }
+
+ /**
+ * Mode index of this mode
+ * @return modeNumber
+ */
+ virtual uint modeNumber () const { return KateDocumentConfig::imNone; };
+
+ protected:
+ KateDocument *doc;
+};
+
+/**
+ * This action provides a list of available indenters and gets plugged
+ * into the KateView's KActionCollection.
+ */
+class KateViewIndentationAction : public KActionMenu
+{
+ Q_OBJECT
+
+ public:
+ KateViewIndentationAction(KateDocument *_doc, const QString& text, QObject* parent = 0, const char* name = 0);
+
+ ~KateViewIndentationAction(){;};
+
+ private:
+ KateDocument* doc;
+
+ public slots:
+ void slotAboutToShow();
+
+ private slots:
+ void setMode (int mode);
+};
+
+/**
+ * Provides Auto-Indent functionality for katepart.
+ */
+class KateNormalIndent : public KateAutoIndent
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor
+ * @param doc parent document
+ */
+ KateNormalIndent (KateDocument *doc);
+
+ /**
+ * Virtual Destructor for the baseclass
+ */
+ virtual ~KateNormalIndent ();
+
+public slots:
+ /**
+ * Update indenter's configuration (indention width, attributes etc.)
+ */
+ virtual void updateConfig ();
+
+public:
+ /**
+ * does this indenter support processNewLine
+ * @return can you do it?
+ */
+ virtual bool canProcessNewLine () const { return true; }
+
+ /**
+ * Called every time a newline character is inserted in the document.
+ *
+ * @param cur The position to start processing. Contains the new cursor position after the indention.
+ * @param needContinue Used to determine whether to calculate a continue indent or not.
+ */
+ virtual void processNewline (KateDocCursor &cur, bool needContinue);
+
+ /**
+ * Called every time a character is inserted into the document.
+ * @param c character inserted
+ */
+ virtual void processChar (QChar c) { Q_UNUSED(c); }
+
+ /**
+ * Aligns/indents the given line to the proper indent position.
+ */
+ virtual void processLine (KateDocCursor &/*line*/) { }
+
+ /**
+ * Processes a section of text, indenting each line in between.
+ */
+ virtual void processSection (const KateDocCursor &/*begin*/, const KateDocCursor &/*end*/) { }
+
+ /**
+ * Set to true if an actual implementation of 'processLine' is present.
+ * This is used to prevent a needless Undo action from being created.
+ */
+ virtual bool canProcessLine() const { return false; }
+
+ /**
+ * Mode index of this mode
+ * @return modeNumber
+ */
+ virtual uint modeNumber () const { return KateDocumentConfig::imNormal; };
+
+protected:
+
+ /**
+ * Determines if the characters open and close are balanced between @p begin and @p end
+ * Fills in @p pos with the column position of first opened character if found.
+ *
+ * @param begin Beginning cursor position.
+ * @param end Ending cursor position where the processing will stop.
+ * @param open The open character.
+ * @param close The closing character which should be matched against @p open.
+ * @param pos Contains the position of the first @p open character in the line.
+ * @return True if @p open and @p close have an equal number of occurances between @p begin and @p end. False otherwise.
+ */
+ bool isBalanced (KateDocCursor &begin, const KateDocCursor &end, QChar open, QChar close, uint &pos) const;
+
+ /**
+ * Skip all whitespace starting at @p cur and ending at @p max. Spans lines if @p newline is set.
+ * @p cur is set to the current position afterwards.
+ *
+ * @param cur The current cursor position to start from.
+ * @param max The furthest cursor position that will be used for processing
+ * @param newline Whether we are allowed to span multiple lines when skipping blanks
+ * @return True if @p cur < @p max after processing. False otherwise.
+ */
+ bool skipBlanks (KateDocCursor &cur, KateDocCursor &max, bool newline) const;
+
+ /**
+ * Measures the indention of the current textline marked by cur
+ * @param cur The cursor position to measure the indent to.
+ * @return The length of the indention in characters.
+ */
+ uint measureIndent (KateDocCursor &cur) const;
+
+ /**
+ * Produces a string with the proper indentation characters for its length.
+ *
+ * @param length The length of the indention in characters.
+ * @return A QString representing @p length characters (factoring in tabs and spaces)
+ */
+ QString tabString(uint length) const;
+
+ uint tabWidth; //!< The number of characters simulated for a tab
+ uint indentWidth; //!< The number of characters used when tabs are replaced by spaces
+
+public:
+ // Attributes that we should skip over or otherwise know about
+ uchar commentAttrib;
+ uchar doxyCommentAttrib;
+ uchar regionAttrib;
+ uchar symbolAttrib;
+ uchar alertAttrib;
+ uchar tagAttrib;
+ uchar wordAttrib;
+ uchar keywordAttrib;
+ uchar normalAttrib;
+ uchar extensionAttrib;
+ uchar preprocessorAttrib;
+ uchar stringAttrib;
+ uchar charAttrib;
+
+protected:
+ bool useSpaces; //!< Should we use spaces or tabs to indent
+ bool mixedIndent; //!< Optimize indent by mixing spaces and tabs, ala emacs
+ bool keepProfile; //!< Always try to honor the leading whitespace of lines already in the file
+};
+
+class KateCSmartIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ KateCSmartIndent (KateDocument *doc);
+ ~KateCSmartIndent ();
+
+ virtual void processNewline (KateDocCursor &cur, bool needContinue);
+ virtual void processChar (QChar c);
+
+ virtual void processLine (KateDocCursor &line);
+ virtual void processSection (const KateDocCursor &begin, const KateDocCursor &end);
+
+ virtual bool canProcessLine() const { return true; }
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imCStyle; };
+
+ private:
+ uint calcIndent (KateDocCursor &begin, bool needContinue);
+ uint calcContinue (KateDocCursor &begin, KateDocCursor &end);
+ uint findOpeningBrace (KateDocCursor &start);
+ uint findOpeningParen (KateDocCursor &start);
+ uint findOpeningComment (KateDocCursor &start);
+ bool firstOpeningBrace (KateDocCursor &start);
+ bool handleDoxygen (KateDocCursor &begin);
+
+ bool allowSemi;
+ bool processingBlock;
+};
+
+class KatePythonIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ KatePythonIndent (KateDocument *doc);
+ ~KatePythonIndent ();
+
+ virtual void processNewline (KateDocCursor &cur, bool needContinue);
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imPythonStyle; };
+
+ private:
+ int calcExtra (int &prevBlock, int &pos, KateDocCursor &end);
+ void traverseString( const QChar &stringChar, KateDocCursor &cur, KateDocCursor &end );
+
+ static QRegExp endWithColon;
+ static QRegExp stopStmt;
+ static QRegExp blockBegin;
+};
+
+class KateXmlIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ KateXmlIndent (KateDocument *doc);
+ ~KateXmlIndent ();
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imXmlStyle; }
+ virtual void processNewline (KateDocCursor &cur, bool needContinue);
+ virtual void processChar (QChar c);
+ virtual void processLine (KateDocCursor &line);
+ virtual bool canProcessLine() const { return true; }
+ virtual void processSection (const KateDocCursor &begin, const KateDocCursor &end);
+
+ private:
+ // sets the indentation of a single line based on previous line
+ // (returns indentation width)
+ uint processLine (uint line);
+
+ // gets information about a line
+ void getLineInfo (uint line, uint &prevIndent, int &numTags,
+ uint &attrCol, bool &unclosedTag);
+
+ // useful regular expressions
+ static const QRegExp startsWithCloseTag;
+ static const QRegExp unclosedDoctype;
+};
+
+class KateCSAndSIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ KateCSAndSIndent (KateDocument *doc);
+ ~KateCSAndSIndent ();
+
+ virtual void processNewline (KateDocCursor &begin, bool needContinue);
+ virtual void processChar (QChar c);
+
+ virtual void processLine (KateDocCursor &line);
+ virtual void processSection (const KateDocCursor &begin, const KateDocCursor &end);
+
+ virtual bool canProcessLine() const { return true; }
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imCSAndS; };
+
+ private:
+ void updateIndentString();
+
+ bool inForStatement( int line );
+ int lastNonCommentChar( const KateDocCursor &line );
+ bool startsWithLabel( int line );
+ bool inStatement( const KateDocCursor &begin );
+ QString continuationIndent( const KateDocCursor &begin );
+
+ QString calcIndent (const KateDocCursor &begin);
+ QString calcIndentAfterKeyword(const KateDocCursor &indentCursor, const KateDocCursor &keywordCursor, int keywordPos, bool blockKeyword);
+ QString calcIndentInBracket(const KateDocCursor &indentCursor, const KateDocCursor &bracketCursor, int bracketPos);
+ QString calcIndentInBrace(const KateDocCursor &indentCursor, const KateDocCursor &braceCursor, int bracePos);
+
+ bool handleDoxygen (KateDocCursor &begin);
+ QString findOpeningCommentIndentation (const KateDocCursor &start);
+
+ QString indentString;
+};
+
+/**
+ * This indenter uses document variables to determine when to add/remove indents.
+ *
+ * It attempts to get the following variables from the document:
+ * - var-indent-indent-after: A rerular expression which will cause a line to
+ * be indented by one unit, if the first non-whitespace-only line above matches.
+ * - var-indent-indent: A regular expression, which will cause a matching line
+ * to be indented by one unit.
+ * - var-indent-unindent: A regular expression which will cause the line to be
+ * unindented by one unit if matching.
+ * - var-indent-triggerchars: a list of characters that should cause the
+ * indentiou to be recalculated immediately when typed.
+ * - var-indent-handle-couples: a list of paren sets to handle. Any combination
+ * of 'parens' 'braces' and 'brackets'. Each set type is handled
+ * the following way: If there are unmatched opening instances on the above line,
+ * one indent unit is added, if there are unmatched closing instances on the
+ * current line, one indent unit is removed.
+ * - var-indent-couple-attribute: When looking for unmatched couple openings/closings,
+ * only characters with this attribute is considered. The value must be the
+ * attribute name from the syntax xml file, for example "Symbol". If it's not
+ * specified, attribute 0 is used (usually 'Normal Text').
+ *
+ * The idea is to provide a somewhat intelligent indentation for perl, php,
+ * bash, scheme and in general formats with humble indentation needs.
+ */
+class KateVarIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Purely for readability, couples we know and love
+ */
+ enum pairs {
+ Parens=1,
+ Braces=2,
+ Brackets=4,
+ AngleBrackets=8
+ };
+
+ KateVarIndent( KateDocument *doc );
+ virtual ~KateVarIndent();
+
+ virtual void processNewline (KateDocCursor &cur, bool needContinue);
+ virtual void processChar (QChar c);
+
+ virtual void processLine (KateDocCursor &line);
+ virtual void processSection (const KateDocCursor &begin, const KateDocCursor &end);
+
+ virtual bool canProcessLine() const { return true; }
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imVarIndent; };
+
+ private slots:
+ void slotVariableChanged(const QString&, const QString&);
+
+ private:
+ /**
+ * Check if coupled characters are in balance within one line.
+ * @param line the line to check
+ * @param open the opening character
+ * @param close the closing character
+ * @param attrib the attribute the characters must have, defaults to
+ * KateAutoIndent::symbolAttrib
+ */
+ int coupleBalance( int line, const QChar &open, const QChar &close ) const;
+
+ /**
+ * @return true if there is a matching opening with the correct attribute
+ * @param end a cursor pointing to the closing character
+ */
+ bool hasRelevantOpening( const KateDocCursor &end ) const;
+
+ class KateVarIndentPrivate *d;
+};
+
+class KateScriptIndent : public KateNormalIndent
+{
+ Q_OBJECT
+
+ public:
+ KateScriptIndent( KateDocument *doc );
+ ~KateScriptIndent();
+
+ virtual void processNewline( KateDocCursor &cur, bool needContinue );
+ virtual void processChar( QChar c );
+
+ virtual void processLine (KateDocCursor &line);
+// virtual void processSection (const KateDocCursor &begin, const KateDocCursor &end);
+
+ virtual bool canProcessLine() const { return true; }
+
+ virtual uint modeNumber () const { return KateDocumentConfig::imScriptIndent; };
+ private:
+ KateIndentScript m_script;
+};
+
+class ScriptIndentConfigPage : public IndenterConfigPage
+{
+ Q_OBJECT
+
+ public:
+ ScriptIndentConfigPage ( QWidget *parent=0, const char *name=0 );
+ virtual ~ScriptIndentConfigPage ();
+
+ public slots:
+ /**
+ * Apply changes.
+ */
+ virtual void apply ();
+};
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;