1 /*
2     SPDX-FileCopyrightText: 2003 Jesse Yurkovich <yurkjes@iit.edu>
3 
4     KateVarIndent class:
5     SPDX-FileCopyrightText: 2004 Anders Lund <anders@alweb.dk>
6 
7     Basic support for config page:
8     SPDX-FileCopyrightText: 2005 Dominik Haumann <dhdev@gmx.de>
9 
10     SPDX-License-Identifier: LGPL-2.0-or-later
11 */
12 
13 #ifndef KATE_AUTO_INDENT_H
14 #define KATE_AUTO_INDENT_H
15 
16 #include "kateconfig.h"
17 
18 #include <QObject>
19 
20 #include <KActionMenu>
21 
22 namespace KTextEditor
23 {
24 class DocumentPrivate;
25 class Cursor;
26 }
27 class KateIndentScript;
28 class KateHighlighting;
29 
30 /**
31  * Provides Auto-Indent functionality for katepart.
32  * This baseclass is a real dummy, does nothing beside remembering the document it belongs too,
33  * only to have the object around
34  */
35 class KateAutoIndent : public QObject
36 {
37     Q_OBJECT
38     /*
39      * Static methods to list indention modes
40      */
41 public:
42     /**
43      * List all possible modes by name, i.e. "C Style", "XML Style", ...
44      * @return list of modes
45      */
46     static QStringList listModes();
47 
48     /**
49      * List all possible names, i.e. "cstyle", "xml", ...
50      * @return list of indenter identifiers
51      */
52     static QStringList listIdentifiers();
53 
54     /**
55      * Return the mode name given the mode
56      * @param mode mode index
57      * @return name for this mode index
58      */
59     static QString modeName(int mode);
60 
61     /**
62      * Return the mode description
63      * @param mode mode index
64      * @return mode index
65      */
66     static QString modeDescription(int mode);
67 
68     /**
69      * Return the syntax highlighting style required to use this mode
70      * @param mode mode index
71      * @return required style, or empty if the mode doesn't require any style
72      */
73     static QString modeRequiredStyle(int mode);
74 
75     /**
76      * Maps name -> index
77      * @param name mode name
78      * @return mode index
79      */
80     static uint modeNumber(const QString &name);
81 
82     /**
83      * count of modes
84      * @return number of existing modes
85      */
86     static int modeCount();
87 
88     /*
89      * Construction + Destruction
90      */
91 public:
92     /**
93      * Constructor, creates dummy indenter "None"
94      * \param doc parent document
95      */
96     explicit KateAutoIndent(KTextEditor::DocumentPrivate *doc);
97 
98     /**
99      * Destructor
100      */
101     ~KateAutoIndent() override;
102 
103     /*
104      * Internal helper for the subclasses and itself
105      */
106 private:
107     /**
108      * Produces a string with the proper indentation characters for its length.
109      *
110      * @param length The length of the indention in characters.
111      * @param align Length of alignment, ignored if less of equal to length
112      * @return A QString representing @p length characters (factoring in tabs and spaces)
113      */
114     QString tabString(int length, int align) const;
115 
116     /**
117      * Set the indent level of the line.
118      * \param line line to change indent for
119      * \param indentDepth set indentation to given number of spaces
120      * \param align if align is higher than indentDepth, the difference
121      * represents a number of spaces to be added after the indent
122      */
123     bool doIndent(int line, int indentDepth, int align = 0);
124 
125     /**
126      * Change the indent of the specified line by the number of levels
127      * specified by change. Positive values will indent more, negative values
128      * will indent less.
129      * \param line line to change indent for
130      * \param change change the indentation by given number of spaces
131      */
132     bool doIndentRelative(int line, int change);
133 
134     /**
135      * Reuse the indent of the previous line
136      * \param line line to change indent for
137      */
138     void keepIndent(int line);
139 
140     /**
141      * Call the indentation script, this is a helper to be used in userTypedChar and indent
142      * \param view the view the user work at
143      * \param position current cursor position, after the inserted char...
144      * \param typedChar the inserted char, indent will just give the script '\n'
145      */
146     void scriptIndent(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor position, QChar typedChar);
147 
148     /**
149      * Return true if the required style for the script is provided by the highlighter.
150      */
151     static bool isStyleProvided(const KateIndentScript *script, const KateHighlighting *highlight);
152 
153 public:
154     /**
155      * Switch indenter
156      * Nop if already set to given mode
157      * Otherwise switch to given indenter or to "None" if no suitable found...
158      * @param name indention mode wanted
159      */
160     void setMode(const QString &name);
161 
162     /**
163      * Check if the current highlighting mode provides the style required by the
164      * current indenter. If not, deactivate the indenter by changing to "normal"
165      * mode.
166      */
167     void checkRequiredStyle();
168 
169     /**
170      * mode name
171      */
modeName()172     const QString &modeName() const
173     {
174         return m_mode;
175     }
176 
177     /**
178      * Update indenter's configuration (indention width, etc.)
179      * Is called in the updateConfig() of the document and after creation of the indenter...
180      */
181     void updateConfig();
182 
183     /**
184      * Function to provide the common indent/unindent/clean indent functionality to the document
185      * This should be generic for all indenters, internally it uses the doIndent function.
186      * This works equal for all indenters, even for "none" or the scripts
187      * \param range range of text to change indent for
188      * \param change level of indents to add or remove, zero will still trigger cleaning of indentation
189      * and removal of extra spaces, if option set
190      * \return \e true on success, otherwise \e false
191      */
192     bool changeIndent(const KTextEditor::Range &range, int change);
193 
194     /**
195      * The document requests the indenter to indent the given range of existing text.
196      * This may happen to indent text pasted or to reindent existing text.
197      * For "none" and "normal" this is a nop, for the scripts, the expression
198      * will be asked for indent level for each line
199      * \param view the view the user work at
200      * \param range the range of text to indent...
201      */
202     void indent(KTextEditor::ViewPrivate *view, const KTextEditor::Range &range);
203 
204     /**
205      * The user typed some char, the indenter can react on this
206      * '\n' will be send as char if the user wraps a line
207      * \param view the view the user work at
208      * \param position current cursor position, after the inserted char...
209      * \param typedChar the inserted char
210      */
211     void userTypedChar(KTextEditor::ViewPrivate *view, const KTextEditor::Cursor position, QChar typedChar);
212 
213 public Q_SLOTS:
214     void reloadScript();
215 
216     /*
217      * needed data
218      */
219 private:
220     KTextEditor::DocumentPrivate *doc; //!< the document the indenter works on
221     int tabWidth; //!< The number of characters simulated for a tab
222     int indentWidth; //!< The number of characters used when tabs are replaced by spaces
223     bool useSpaces; //!< Should we use spaces or tabs to indent
224     bool keepExtra; //!< Keep indentation that is not on indentation boundaries
225     QString m_mode;
226     KateIndentScript *m_script;
227 };
228 
229 /**
230  * This action provides a list of available indenters and gets plugged
231  * into the KTextEditor::ViewPrivate's KActionCollection.
232  */
233 class KateViewIndentationAction : public KActionMenu
234 {
235     Q_OBJECT
236 
237 public:
238     KateViewIndentationAction(KTextEditor::DocumentPrivate *_doc, const QString &text, QObject *parent);
239 
240 private:
241     KTextEditor::DocumentPrivate *doc;
242     QActionGroup *actionGroup;
243 
244 public Q_SLOTS:
245     void slotAboutToShow();
246 
247 private Q_SLOTS:
248     void setMode(QAction *);
249 };
250 
251 #endif
252