Repository: spyder-ide/spyder

Issue:
Show current file in file browser
It would be nice to have a menu item to show the current file in the file explorer (move to directory, select file), ideally in the context menu.



Discussion:
Good suggestion.

@naught101 can you elaborate a bit more on how this would work and use cases?

Cheers :-)

@goanpeca: basically, if you have a file open, and click "show current file in file browser", it would change the file browser's displayed directory to the directory containing the file (obviously this would not be available for unsaved files), and then select/highlight the file.

Use-cases are pretty general: it's very useful to be able to explore the directory structure of a file, for example when editing a module that's part of a larger package that uses relative imports - this would make it easier to quicly figure out the required relative import syntax.


Resolving patch:
diff --git a/spyder/widgets/editor.py b/spyder/widgets/editor.py
--- a/spyder/widgets/editor.py
+++ b/spyder/widgets/editor.py
@@ -50,6 +50,7 @@
                                    EOLStatus, ReadWriteStatus)
 from spyder.widgets.tabs import BaseTabs
 from spyder.config.main import CONF
+from spyder.widgets.explorer import show_in_external_file_explorer
 
 DEBUG_EDITOR = DEBUG >= 3
 
@@ -474,7 +475,16 @@ def __init__(self, parent, actions):
                                     triggered=self.close_all_right)
         close_all_but_this = create_action(self, _("Close all but this"),
                                            triggered=self.close_all_but_this)
-
+        
+        if sys.platform == 'darwin':
+           text=_("Show in Finder")
+        else:
+           text= _("Show in external file explorer")
+        external_fileexp_action = create_action(self, text,
+                                triggered=self.show_in_external_file_explorer)
+                
+        actions.append(external_fileexp_action)
+        
         self.menu_actions = actions + [None, fileswitcher_action,
                                        symbolfinder_action,
                                        copy_to_cb_action, None, close_right,
@@ -546,6 +556,13 @@ def __init__(self, parent, actions):
         #For opening last closed tabs
         self.last_closed_files = []
 
+    @Slot()
+    def show_in_external_file_explorer(self, fnames=None):
+        """Show file in external file explorer"""
+        if fnames is None:
+            fnames = self.get_current_filename()
+        show_in_external_file_explorer(fnames)
+
     def create_shortcuts(self):
         """Create local shortcuts"""
         # --- Configurable shortcuts
diff --git a/spyder/widgets/explorer.py b/spyder/widgets/explorer.py
--- a/spyder/widgets/explorer.py
+++ b/spyder/widgets/explorer.py
@@ -17,6 +17,8 @@
 import os.path as osp
 import re
 import shutil
+import subprocess
+import sys
 
 # Third party imports
 from qtpy import API, is_pyqt46
@@ -42,6 +44,26 @@
 except:
     nbexporter = None    # analysis:ignore
 
+def open_file_in_external_explorer(filename):
+    if sys.platform == "darwin":
+        subprocess.call(["open", "-R", filename])
+    else:
+        filename=os.path.dirname(filename)
+        if os.name == 'nt':
+            os.startfile(filename)
+        else:
+            subprocess.call(["xdg-open", filename])
+
+def show_in_external_file_explorer(fnames=None):
+    """Show files in external file explorer
+
+    Args:
+        fnames (list): Names of files to show.
+    """
+    if not isinstance(fnames, (tuple, list)):
+        fnames = [fnames]
+    for fname in fnames:
+        open_file_in_external_explorer(fname)
 
 def fixpath(path):
     """Normalize path fixing case, making absolute and removing symlinks"""
@@ -293,6 +315,13 @@ def create_file_manage_actions(self, fnames):
             actions.append(edit_action)
         else:
             actions.append(open_action)
+        if sys.platform == 'darwin':
+            text=_("Show in Finder")
+        else:
+            text=_("Show in external file explorer")
+        external_fileexp_action = create_action(self, text, 
+                                triggered=self.show_in_external_file_explorer)        
+        actions.append(external_fileexp_action)
         actions += [delete_action, rename_action]
         basedir = fixpath(osp.dirname(fnames[0]))
         if all([fixpath(osp.dirname(_fn)) == basedir for _fn in fnames]):
@@ -605,6 +634,13 @@ def rename_file(self, fname):
                               "<br><br>Error message:<br>%s"
                               ) % (osp.basename(fname), to_text_string(error)))
 
+    @Slot()
+    def show_in_external_file_explorer(self, fnames=None):
+        """Show file in external file explorer"""
+        if fnames is None:
+            fnames = self.get_selected_filenames()
+        show_in_external_file_explorer(fnames)
+
     @Slot()
     def rename(self, fnames=None):
         """Rename files"""


Test patch: