1 | /* |
2 | SPDX-FileCopyrightText: 2003-2005 Anders Lund <anders@alweb.dk> |
3 | SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org> |
4 | SPDX-FileCopyrightText: 2001 Charles Samuels <charles@kde.org> |
5 | |
6 | SPDX-License-Identifier: LGPL-2.0-or-later |
7 | */ |
8 | |
9 | #ifndef KATE_SED_CMD_H |
10 | #define KATE_SED_CMD_H |
11 | |
12 | #include "kateregexpsearch.h" |
13 | #include <KTextEditor/Command> |
14 | |
15 | #include <QStringList> |
16 | |
17 | namespace KTextEditor |
18 | { |
19 | class DocumentPrivate; |
20 | class ViewPrivate; |
21 | } |
22 | |
23 | /** |
24 | * The KateCommands namespace collects subclasses of KTextEditor::Command |
25 | * for specific use in kate. |
26 | */ |
27 | namespace KateCommands |
28 | { |
29 | /** |
30 | * Support vim/sed style search and replace |
31 | * @author Charles Samuels <charles@kde.org> |
32 | **/ |
33 | class SedReplace : public KTextEditor::Command |
34 | { |
35 | static SedReplace *m_instance; |
36 | |
37 | protected: |
38 | SedReplace() |
39 | : KTextEditor::Command({QStringLiteral("s" ), QStringLiteral("%s" ), QStringLiteral("$s" )}) |
40 | { |
41 | } |
42 | |
43 | public: |
44 | ~SedReplace() override |
45 | { |
46 | m_instance = nullptr; |
47 | } |
48 | |
49 | /** |
50 | * Execute command. Valid command strings are: |
51 | * - s/search/replace/ find @c search, replace it with @c replace |
52 | * on this line |
53 | * - \%s/search/replace/ do the same to the whole file |
54 | * - s/search/replace/i do the search and replace case insensitively |
55 | * - $s/search/replace/ do the search are replacement to the |
56 | * selection only |
57 | * |
58 | * @note $s/// is currently unsupported |
59 | * @param view view to use for execution |
60 | * @param cmd cmd string |
61 | * @param errorMsg error to return if no success |
62 | * @return success |
63 | */ |
64 | bool exec(class KTextEditor::View *view, const QString &cmd, QString &errorMsg, const KTextEditor::Range &r) override; |
65 | |
66 | bool supportsRange(const QString &) override |
67 | { |
68 | return true; |
69 | } |
70 | |
71 | /** This command does not have help. @see KTextEditor::Command::help */ |
72 | bool help(class KTextEditor::View *, const QString &, QString &) override |
73 | { |
74 | return false; |
75 | } |
76 | |
77 | static SedReplace *self() |
78 | { |
79 | if (m_instance == nullptr) { |
80 | m_instance = new SedReplace(); |
81 | } |
82 | return m_instance; |
83 | } |
84 | |
85 | /** |
86 | * Parses @c sedReplaceString to see if it is a valid sed replace expression (e.g. "s/find/replace/gi"). |
87 | * If it is, returns true and sets @c delimiter to the delimiter used in the expression; |
88 | * @c destFindBeginPos and @c destFindEndPos to the positions in * @c sedReplaceString of the |
89 | * begin and end of the "find" term; and @c destReplaceBeginPos and @c destReplaceEndPos to the begin |
90 | * and end positions of the "replace" term. |
91 | */ |
92 | static bool |
93 | parse(const QString &sedReplaceString, QString &destDelim, int &destFindBeginPos, int &destFindEndPos, int &destReplaceBeginPos, int &destReplaceEndPos); |
94 | |
95 | class InteractiveSedReplacer |
96 | { |
97 | public: |
98 | InteractiveSedReplacer(KTextEditor::DocumentPrivate *doc, |
99 | const QString &findPattern, |
100 | const QString &replacePattern, |
101 | bool caseSensitive, |
102 | bool onlyOnePerLine, |
103 | int startLine, |
104 | int endLine); |
105 | /** |
106 | * Will return invalid Range if there are no further matches. |
107 | */ |
108 | KTextEditor::Range currentMatch(); |
109 | void skipCurrentMatch(); |
110 | void replaceCurrentMatch(); |
111 | void replaceAllRemaining(); |
112 | QString currentMatchReplacementConfirmationMessage(); |
113 | QString finalStatusReportMessage() const; |
114 | |
115 | private: |
116 | const QString m_findPattern; |
117 | const QString m_replacePattern; |
118 | bool m_onlyOnePerLine; |
119 | int m_endLine; |
120 | KTextEditor::DocumentPrivate *m_doc; |
121 | KateRegExpSearch m_regExpSearch; |
122 | Qt::CaseSensitivity m_caseSensitive; |
123 | |
124 | int m_numReplacementsDone; |
125 | int m_numLinesTouched; |
126 | int m_lastChangedLineNum; |
127 | |
128 | KTextEditor::Cursor m_currentSearchPos; |
129 | const QList<KTextEditor::Range> fullCurrentMatch(); |
130 | QString replacementTextForCurrentMatch(); |
131 | }; |
132 | |
133 | protected: |
134 | virtual bool interactiveSedReplace(KTextEditor::ViewPrivate *kateView, std::shared_ptr<InteractiveSedReplacer> interactiveSedReplace); |
135 | }; |
136 | |
137 | } // namespace KateCommands |
138 | #endif |
139 | |