File indexing completed on 2024-04-21 03:57:48

0001 /*
0002     SPDX-FileCopyrightText: 2003-2005 Anders Lund <anders@alweb.dk>
0003     SPDX-FileCopyrightText: 2001-2010 Christoph Cullmann <cullmann@kde.org>
0004     SPDX-FileCopyrightText: 2001 Charles Samuels <charles@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #ifndef KATE_SED_CMD_H
0010 #define KATE_SED_CMD_H
0011 
0012 #include "kateregexpsearch.h"
0013 #include <KTextEditor/Command>
0014 
0015 #include <QStringList>
0016 
0017 namespace KTextEditor
0018 {
0019 class DocumentPrivate;
0020 class ViewPrivate;
0021 }
0022 
0023 /**
0024  * The KateCommands namespace collects subclasses of KTextEditor::Command
0025  * for specific use in kate.
0026  */
0027 namespace KateCommands
0028 {
0029 /**
0030  * Support vim/sed style search and replace
0031  * @author Charles Samuels <charles@kde.org>
0032  **/
0033 class SedReplace : public KTextEditor::Command
0034 {
0035     static SedReplace *m_instance;
0036 
0037 protected:
0038     SedReplace()
0039         : KTextEditor::Command({QStringLiteral("s"), QStringLiteral("%s"), QStringLiteral("$s")})
0040     {
0041     }
0042 
0043 public:
0044     ~SedReplace() override
0045     {
0046         m_instance = nullptr;
0047     }
0048 
0049     /**
0050      * Execute command. Valid command strings are:
0051      *   -  s/search/replace/  find @c search, replace it with @c replace
0052      *                         on this line
0053      *   -  \%s/search/replace/ do the same to the whole file
0054      *   -  s/search/replace/i do the search and replace case insensitively
0055      *   -  $s/search/replace/ do the search are replacement to the
0056      *                         selection only
0057      *
0058      * @note   $s/// is currently unsupported
0059      * @param view view to use for execution
0060      * @param cmd cmd string
0061      * @param errorMsg error to return if no success
0062      * @return success
0063      */
0064     bool exec(class KTextEditor::View *view, const QString &cmd, QString &errorMsg, const KTextEditor::Range &r) override;
0065 
0066     bool supportsRange(const QString &) override
0067     {
0068         return true;
0069     }
0070 
0071     /** This command does not have help. @see KTextEditor::Command::help */
0072     bool help(class KTextEditor::View *, const QString &, QString &) override
0073     {
0074         return false;
0075     }
0076 
0077     static SedReplace *self()
0078     {
0079         if (m_instance == nullptr) {
0080             m_instance = new SedReplace();
0081         }
0082         return m_instance;
0083     }
0084 
0085     /**
0086      * Parses @c sedReplaceString to see if it is a valid sed replace expression (e.g. "s/find/replace/gi").
0087      * If it is, returns true and sets @c delimiter to the delimiter used in the expression;
0088      *  @c destFindBeginPos and @c destFindEndPos to the positions in * @c sedReplaceString of the
0089      * begin and end of the "find" term; and @c destReplaceBeginPos and @c destReplaceEndPos to the begin
0090      * and end positions of the "replace" term.
0091      */
0092     static bool
0093     parse(const QString &sedReplaceString, QString &destDelim, int &destFindBeginPos, int &destFindEndPos, int &destReplaceBeginPos, int &destReplaceEndPos);
0094 
0095     class InteractiveSedReplacer
0096     {
0097     public:
0098         InteractiveSedReplacer(KTextEditor::DocumentPrivate *doc,
0099                                const QString &findPattern,
0100                                const QString &replacePattern,
0101                                bool caseSensitive,
0102                                bool onlyOnePerLine,
0103                                int startLine,
0104                                int endLine);
0105         /**
0106          * Will return invalid Range if there are no further matches.
0107          */
0108         KTextEditor::Range currentMatch();
0109         void skipCurrentMatch();
0110         void replaceCurrentMatch();
0111         void replaceAllRemaining();
0112         QString currentMatchReplacementConfirmationMessage();
0113         QString finalStatusReportMessage() const;
0114 
0115     private:
0116         const QString m_findPattern;
0117         const QString m_replacePattern;
0118         bool m_onlyOnePerLine;
0119         int m_endLine;
0120         KTextEditor::DocumentPrivate *m_doc;
0121         KateRegExpSearch m_regExpSearch;
0122         Qt::CaseSensitivity m_caseSensitive;
0123 
0124         int m_numReplacementsDone;
0125         int m_numLinesTouched;
0126         int m_lastChangedLineNum;
0127 
0128         KTextEditor::Cursor m_currentSearchPos;
0129         const QList<KTextEditor::Range> fullCurrentMatch();
0130         QString replacementTextForCurrentMatch();
0131     };
0132 
0133 protected:
0134     virtual bool interactiveSedReplace(KTextEditor::ViewPrivate *kateView, std::shared_ptr<InteractiveSedReplacer> interactiveSedReplace);
0135 };
0136 
0137 } // namespace KateCommands
0138 #endif