diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt --- a/addons/CMakeLists.txt +++ b/addons/CMakeLists.txt @@ -35,6 +35,9 @@ # open header matching to current file ecm_optional_add_subdirectory (openheader) +# open selected text path +ecm_optional_add_subdirectory (openselection) + # debugger plugin, needs windows love, guarded until ported to win32 if (NOT WIN32) ecm_optional_add_subdirectory (gdbplugin) diff --git a/addons/openselection/CMakeLists.txt b/addons/openselection/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/addons/openselection/CMakeLists.txt @@ -0,0 +1,17 @@ +project (kateopenselection) +add_definitions(-DTRANSLATION_DOMAIN=\"kateopenselection\") + +########### next target ############### +set(kateopenselectionplugin_PART_SRCS plugin_kateopenselection.cpp ) + +# resource for ui file and stuff +qt5_add_resources(kateopenselectionplugin_PART_SRCS plugin.qrc) + +add_library(kateopenselectionplugin MODULE ${kateopenselectionplugin_PART_SRCS}) +kcoreaddons_desktop_to_json (kateopenselectionplugin kateopenselectionplugin.desktop) +target_link_libraries(kateopenselectionplugin + KF5::TextEditor + KF5::I18n + KF5::Parts) + +install(TARGETS kateopenselectionplugin DESTINATION ${PLUGIN_INSTALL_DIR}/ktexteditor ) diff --git a/addons/openselection/Messages.sh b/addons/openselection/Messages.sh new file mode 100755 --- /dev/null +++ b/addons/openselection/Messages.sh @@ -0,0 +1,3 @@ +#! /bin/sh +$EXTRACTRC *.rc >> rc.cpp +$XGETTEXT *.cpp -o $podir/kateopenselection.pot diff --git a/addons/openselection/kateopenselectionplugin.desktop b/addons/openselection/kateopenselectionplugin.desktop new file mode 100644 --- /dev/null +++ b/addons/openselection/kateopenselectionplugin.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Type=Service +ServiceTypes=KTextEditor/Plugin +X-KDE-Library=kateopenselectionplugin +Name=Open Selection +Comment=Opens the selected path diff --git a/addons/openselection/plugin.qrc b/addons/openselection/plugin.qrc new file mode 100644 --- /dev/null +++ b/addons/openselection/plugin.qrc @@ -0,0 +1,6 @@ + + + + ui.rc + + diff --git a/addons/openselection/plugin_kateopenselection.h b/addons/openselection/plugin_kateopenselection.h new file mode 100644 --- /dev/null +++ b/addons/openselection/plugin_kateopenselection.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + Copyright (C) 2019 Arnaud Ruiz + + Created from large parts of: + - openheader plugin + Copyright (C) 2001 Joseph Wenninger + Copyright (C) 2009 Erlend Hamberg + - search plugin + Copyright (C) 2011-2013 by Kåre Särs + + 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 PLUGIN_KATEOPENSELECTION_H +#define PLUGIN_KATEOPENSELECTION_H + +#include +#include +#include +#include +#include +#include +#include + +class PluginKateOpenSelection : public KTextEditor::Plugin +{ + Q_OBJECT + + public: + explicit PluginKateOpenSelection( QObject* parent = nullptr, const QList& = QList() ); + ~PluginKateOpenSelection() override; + + QObject *createView (KTextEditor::MainWindow *mainWindow) override; + + public Q_SLOTS: + void slotOpenSelection(); + + private: + bool fileExists(const QUrl &url); +}; + +class PluginViewKateOpenSelection + : public KTextEditor::Command + , public KXMLGUIClient +{ + Q_OBJECT + public: + PluginViewKateOpenSelection(PluginKateOpenSelection* plugin, KTextEditor::MainWindow *mainwindow); + ~PluginViewKateOpenSelection() override; + + bool exec (KTextEditor::View *view, const QString &cmd, QString &msg, const KTextEditor::Range &range = KTextEditor::Range::invalid()) override; + bool help (KTextEditor::View *view, const QString &cmd, QString &msg) override; + + private: + PluginKateOpenSelection* m_plugin; + KTextEditor::MainWindow *m_mainWindow; +}; + +#endif // PLUGIN_KATEOPENSELECTION_H diff --git a/addons/openselection/plugin_kateopenselection.cpp b/addons/openselection/plugin_kateopenselection.cpp new file mode 100644 --- /dev/null +++ b/addons/openselection/plugin_kateopenselection.cpp @@ -0,0 +1,180 @@ +/* This file is part of the KDE project + Copyright (C) 2019 Arnaud Ruiz + + Created from large parts of: + - openheader plugin + Copyright (C) 2001 Joseph Wenninger + Copyright (C) 2009 Erlend Hamberg + - search plugin + Copyright (C) 2011-2013 by Kåre Särs + + 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. +*/ + +#include "plugin_kateopenselection.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +K_PLUGIN_FACTORY_WITH_JSON(KateOpenSelectionFactory,"kateopenselectionplugin.json", registerPlugin();) + + +PluginViewKateOpenSelection::PluginViewKateOpenSelection(PluginKateOpenSelection *plugin, KTextEditor::MainWindow *mainwindow) + : KTextEditor::Command(QStringList() << QStringLiteral("open-selection"), mainwindow), + KXMLGUIClient(), + m_plugin(plugin), + m_mainWindow(mainwindow) +{ + KXMLGUIClient::setComponentName(QStringLiteral("kateopenselectionplugin"), i18n("Open Selection")); + setXMLFile( QStringLiteral("ui.rc") ); + QAction *a = actionCollection()->addAction(QStringLiteral("file_openselection")); + a->setText(i18n("Open selected path")); + actionCollection()->setDefaultShortcut(a, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_O)); + connect(a, &QAction::triggered, plugin, &PluginKateOpenSelection::slotOpenSelection); + mainwindow->guiFactory()->addClient(this); +} + +PluginViewKateOpenSelection::~PluginViewKateOpenSelection() +{ + m_mainWindow->guiFactory()->removeClient(this); +} + +PluginKateOpenSelection::PluginKateOpenSelection( QObject* parent, const QList& ) + : KTextEditor::Plugin(parent) +{ +} + +PluginKateOpenSelection::~PluginKateOpenSelection() +{ +} + +QObject *PluginKateOpenSelection::createView (KTextEditor::MainWindow *mainWindow) +{ + return new PluginViewKateOpenSelection(this,mainWindow); +} + +static bool isValidChar(QChar c) +{ + return !c.isSpace() && c != QLatin1Char('"') && c != QLatin1Char('\''); +} + +void PluginKateOpenSelection::slotOpenSelection() +{ + KTextEditor::Application *application = KTextEditor::Editor::instance()->application(); + if (!application->activeMainWindow()) { + return; + } + + KTextEditor::View* editView = application->activeMainWindow()->activeView(); + if (editView) { + QString selection; + + // Selected text + if (editView->selection()) { + selection = editView->selectionText(); + selection = selection.trimmed(); + } + + // Try to extract path under cursor if no selected text + if (selection.isEmpty()) { + const KTextEditor::Cursor &cursor = editView->cursorPosition(); + const QString line = editView->document()->line(cursor.line()); + const int lineLength = line.size(); + if (lineLength > 0) { + const int col = cursor.column(); + int start = col; + int end = col; + + // Stop at first white space or quote (for path with space, user should select the text) + while (start > 0 && isValidChar(line.at(start - 1))) { + --start; + } + while (end+1 < lineLength && isValidChar(line.at(end + 1))) { + ++end; + } + selection = line.mid(start, end - start + 1); + } + } + + // Relative file path : set relative to current document path + if (QDir::isRelativePath(selection)) { + const QUrl currentUrl = editView->document()->url(); + if (currentUrl.isValid() && !currentUrl.isEmpty()) { + const QDir currentDir(QFileInfo(currentUrl.path()).absolutePath()); + selection = currentDir.absoluteFilePath(selection); + } + } + + // Open the file + if (!selection.isEmpty() && !selection.contains(QLatin1Char('\n'))) { + const QUrl url = QUrl::fromLocalFile(selection); + if (fileExists(url)) { + application->activeMainWindow()->openUrl(url); + } + } + } +} + +bool PluginKateOpenSelection::fileExists(const QUrl &url) +{ + if (url.isLocalFile()) { + return QFile::exists(url.toLocalFile()); + } + KIO::JobFlags flags = KIO::DefaultFlags; + KIO::StatJob *job = KIO::stat(url, flags); + KJobWidgets::setWindow(job, KTextEditor::Editor::instance()->application()->activeMainWindow()->window()); + job->setSide(KIO::StatJob::DestinationSide); + job->exec(); + return !job->error(); +} + +bool PluginViewKateOpenSelection::exec(KTextEditor::View *view, const QString &cmd, QString &msg, const KTextEditor::Range &) +{ + Q_UNUSED(view) + Q_UNUSED(cmd) + Q_UNUSED(msg) + + m_plugin->slotOpenSelection(); + return true; +} + +bool PluginViewKateOpenSelection::help(KTextEditor::View *view, const QString &cmd, QString &msg) +{ + Q_UNUSED(view) + Q_UNUSED(cmd) + + msg = i18n("

open-selection — open the selected path

" + "

usage: open-selection

" + "

This command will open the file under the cursor (path in selection or auto-detection)

"); + + return true; +} + +#include "plugin_kateopenselection.moc" diff --git a/addons/openselection/rc.cpp b/addons/openselection/rc.cpp new file mode 100644 diff --git a/addons/openselection/ui.rc b/addons/openselection/ui.rc new file mode 100644 --- /dev/null +++ b/addons/openselection/ui.rc @@ -0,0 +1,11 @@ + + + + + + &File + + + + + diff --git a/doc/kate/plugins.docbook b/doc/kate/plugins.docbook --- a/doc/kate/plugins.docbook +++ b/doc/kate/plugins.docbook @@ -84,6 +84,10 @@ - Opens the corresponding .h/[.cpp|.c] file +Open Selection +- Opens the selected path + + Project Plugin - Integration with Git and other source control systems @@ -1510,6 +1514,44 @@ + + +Open Selection Plugin + + +Using the Open Selection Plugin + +This command help to open files with path in a file + +For example, if you have a list of path in a file (address file, includes, ...), select or place the cursor in one of them, then trigger the plugin using the shortcut. The plugin will open the file + + + + +Menu Structure + + + + + + +&Ctrl;&Shift;O + +File +Opens the selected path + + +Open the selected path or the path under the cursor. + + + + + + + + + +