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,181 @@
+/* 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::ALT + 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);
+ }
+ }
+
+ if (!selection.isEmpty() && !selection.contains(QLatin1Char('\n'))) {
+
+ // Directory of the active document
+ const QUrl currentUrl = editView->document()->url();
+ QString currentUrlDirectory;
+ if (currentUrl.isValid() && !currentUrl.isEmpty()) {
+ currentUrlDirectory = QFileInfo(currentUrl.path()).absolutePath();
+ }
+
+ // Deduction of the url type, QUrl::AssumeLocalFile to prevent remote file assumption when the local file does not exist
+ const QUrl url = QUrl::fromUserInput(selection, currentUrlDirectory, QUrl::AssumeLocalFile);
+
+ // Open the file if existing
+ if (fileExists(url)) {
+ application->activeMainWindow()->openUrl(url);
+ }
+ }
+ }
+}
+
+bool PluginKateOpenSelection::fileExists(const QUrl &url)
+{
+ if (url.isLocalFile()) {
+ return QFile::exists(url.toLocalFile());
+ }
+ // For http protocol, the file is supposed to exist (KIO::StatJob::SourceSide)
+ KIO::JobFlags flags = KIO::DefaultFlags;
+ KIO::StatJob *job = KIO::stat(url, KIO::StatJob::SourceSide, 0, KIO::DefaultFlags);
+ KJobWidgets::setWindow(job, KTextEditor::Editor::instance()->application()->activeMainWindow()->window());
+ 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("