KTextEditor

katetemplatehandler.h
1 /*
2  SPDX-FileCopyrightText: 2004, 2010 Joseph Wenninger <[email protected]>
3  SPDX-FileCopyrightText: 2009 Milian Wolff <[email protected]>
4  SPDX-FileCopyrightText: 2014 Sven Brauch <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef _KATE_TEMPLATE_HANDLER_H_
10 #define _KATE_TEMPLATE_HANDLER_H_
11 
12 #include <QMap>
13 #include <QObject>
14 #include <QPointer>
15 #include <QString>
16 #include <QVector>
17 
18 #include <katescript.h>
19 #include <ktexteditor/cursor.h>
20 
21 class KateUndoManager;
22 
23 namespace KTextEditor
24 {
25 class DocumentPrivate;
26 class ViewPrivate;
27 class MovingCursor;
28 class MovingRange;
29 class View;
30 }
31 
32 /**
33  * \brief Inserts a template and offers advanced snippet features, like navigation and mirroring.
34  *
35  * For each template inserted a new KateTemplateHandler will be created.
36  *
37  * The handler has the following features:
38  *
39  * \li It inserts the template string into the document at the requested position.
40  * \li When the template contains at least one variable, the cursor will be placed
41  * at the start of the first variable and its range gets selected.
42  * \li When more than one variable exists,TAB and SHIFT TAB can be used to navigate
43  * to the next/previous variable.
44  * \li When a variable occurs more than once in the template, edits to any of the
45  * occurrences will be mirroed to the other ones.
46  * \li When ESC is pressed, the template handler closes.
47  * \li When ALT + RETURN is pressed and a \c ${cursor} variable
48  * exists in the template,the cursor will be placed there. Else the cursor will
49  * be placed at the end of the template.
50  *
51  * \author Milian Wolff <[email protected]>
52  */
53 
55 {
56  Q_OBJECT
57 
58 public:
59  /**
60  * Setup the template handler, insert the template string.
61  *
62  * NOTE: The handler deletes itself when required, you do not need to
63  * keep track of it.
64  */
65  KateTemplateHandler(KTextEditor::ViewPrivate *view,
66  KTextEditor::Cursor position,
67  const QString &templateString,
68  const QString &script,
69  KateUndoManager *undoManager);
70 
71  ~KateTemplateHandler() override;
72 
73 protected:
74  /**
75  * \brief Provide keyboard interaction for the template handler.
76  *
77  * The event filter handles the following shortcuts:
78  *
79  * TAB: jump to next editable (i.e. not mirrored) range.
80  * NOTE: this prevents indenting via TAB.
81  * SHIFT + TAB: jump to previous editable (i.e. not mirrored) range.
82  * NOTE: this prevents un-indenting via SHIFT + TAB.
83  * ESC: terminate template handler (only when no completion is active).
84  * ALT + RETURN: accept template and jump to the end-cursor.
85  * if %{cursor} was given in the template, that will be the
86  * end-cursor.
87  * else just jump to the end of the inserted text.
88  */
89  bool eventFilter(QObject *object, QEvent *event) override;
90 
91 private:
92  /**
93  * Inserts the @p text template at @p position and performs
94  * all necessary initializations, such as populating default values
95  * and placing the cursor.
96  */
97  void initializeTemplate();
98 
99  /**
100  * Parse @p templateText and populate m_fields.
101  */
102  void parseFields(const QString &templateText);
103 
104  /**
105  * Set necessary attributes (esp. background colour) on all moving
106  * ranges for the fields in m_fields.
107  */
108  void setupFieldRanges();
109 
110  /**
111  * Evaluate default values for all fields in m_fields and
112  * store them in the fields. This updates the @property defaultValue property
113  * of the TemplateField instances in m_fields from the raw, user-entered
114  * default value to its evaluated equivalent (e.g. "func()" -> result of function call)
115  *
116  * @sa TemplateField
117  */
118  void setupDefaultValues();
119 
120  /**
121  * Install an event filter on the filter proxy of \p view for
122  * navigation between the ranges and terminating the KateTemplateHandler.
123  *
124  * \see eventFilter()
125  */
126  void setupEventHandler(KTextEditor::View *view);
127 
128  /**
129  * Jumps to the previous editable range. If there is none, wrap and jump to the first range.
130  *
131  * \see jumpToNextRange()
132  */
133  void jumpToPreviousRange();
134 
135  /**
136  * Jumps to the next editable range. If there is none, wrap and jump to the last range.
137  *
138  * \see jumpToPreviousRange()
139  */
140  void jumpToNextRange();
141 
142  /**
143  * Helper function for jumpTo{Next,Previous}
144  * if initial is set to true, assumes the cursor is before the snippet
145  * and selects the first field
146  */
147  void jump(int by, bool initial = false);
148 
149  /**
150  * Jumps to the final cursor position. This is either \p m_finalCursorPosition, or
151  * if that is not set, the end of \p m_templateRange.
152  */
153  void jumpToFinalCursorPosition();
154 
155  /**
156  * Go through all template fields and decide if their moving ranges expand
157  * when edited at the corners. Expansion is turned off if two fields are
158  * directly adjacent to avoid overlaps when characters are inserted between
159  * them.
160  */
161  void updateRangeBehaviours();
162 
163  /**
164  * Sort all template fields in m_fields by tab order, which means,
165  * by range; except for ${cursor} which is always sorted last.
166  */
167  void sortFields();
168 
169 private Q_SLOTS:
170  /**
171  * Saves the range of the inserted template. This is required since
172  * tabs could get expanded on insert. While we are at it, we can
173  * use it to auto-indent the code after insert.
174  */
175  void slotTemplateInserted(KTextEditor::Document *document, KTextEditor::Range range);
176 
177  /**
178  * Install event filter on new views.
179  */
180  void slotViewCreated(KTextEditor::Document *document, KTextEditor::View *view);
181 
182  /**
183  * Update content of all dependent fields, i.e. mirror or script fields.
184  */
185  void updateDependentFields(KTextEditor::Document *document, KTextEditor::Range oldRange);
186 
187 public:
188  KTextEditor::ViewPrivate *view() const;
189  KTextEditor::DocumentPrivate *doc() const;
190 
191 private:
192  /// The view we operate on
193  KTextEditor::ViewPrivate *m_view;
194  /// The undo manager associated with our document
195  KateUndoManager *const m_undoManager;
196 
197  // Describes a single template field, e.g. ${foo}.
198  struct TemplateField {
199  // up-to-date range for the field
201  // contents of the field, i.e. identifier or function to call
202  QString identifier;
203  // default value, if applicable; else empty
204  QString defaultValue;
205  enum Kind {
206  Invalid, // not an actual field
207  Editable, // normal, user-editable field (green by default) [non-dependent field]
208  Mirror, // field mirroring contents of another field [dependent field]
209  FunctionCall, // field containing the up-to-date result of a function call [dependent field]
210  FinalCursorPosition // field marking the final cursor position
211  };
212  Kind kind = Invalid;
213  // true if this field was edited by the user before
214  bool touched = false;
215  bool operator==(const TemplateField &other) const
216  {
217  return range == other.range;
218  }
219  };
220  // List of all template fields in the inserted snippet. @see sortFields()
221  QVector<TemplateField> m_fields;
222 
223  // Get the template field which contains @p range.
224  const TemplateField fieldForRange(KTextEditor::Range range) const;
225 
226  /// Construct a map of master fields and their current value, for use in scripts.
227  KateScript::FieldMap fieldMap() const;
228 
229  /// A range that occupies the whole range of the inserted template.
230  /// When the an edit happens outside it, the template handler gets closed.
231  QSharedPointer<KTextEditor::MovingRange> m_wholeTemplateRange;
232 
233  /// Set to true when currently updating dependent fields, to prevent recursion.
234  bool m_internalEdit;
235 
236  /// template script (i.e. javascript stuff), which can be used by the current template
237  KateScript m_templateScript;
238 };
239 
240 #endif
Q_OBJECTQ_OBJECT
Q_SLOTSQ_SLOTS
bool eventFilter(QObject *object, QEvent *event) override
Provide keyboard interaction for the template handler.
An object representing a section of text, from one Cursor to another.
virtual bool event(QEvent *e)
The Cursor represents a position in a Document.
Definition: cursor.h:71
KateUndoManager implements a document's history.
A text widget with KXMLGUIClient that represents a Document.
Definition: view.h:146
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
Definition: katetextblock.h:22
Inserts a template and offers advanced snippet features, like navigation and mirroring.
KateTemplateHandler(KTextEditor::ViewPrivate *view, KTextEditor::Cursor position, const QString &templateString, const QString &script, KateUndoManager *undoManager)
Setup the template handler, insert the template string.
KateScript objects represent a script that can be executed and inspected.
Definition: katescript.h:106
A KParts derived class representing a text document.
Definition: document.h:185
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:50:22 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.