You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
582 lines
18 KiB
582 lines
18 KiB
/* 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;
|