Sublime Forum

Opening files Emacs-style

#1

Hi all,

I am in the early stages of migrating from Emacs and there on thing I miss at the moment: opening files using auto-complete. Within Sublime, the only way I can find to open files is via the GUI. In Emacs you can tab to autocomplete file names and that’s really fast. I can leave Sublime and open a file via a command line. This gives me the ability to auto-complete but it seems very roundabout. Is there a better way?

Thanks!

0 Likes

#2

I thing Sublime’s Ctrl-P GoTo Anything ability supersedes any tab-completion functionality.

0 Likes

#3

Have you tried Goto Anything (Ctrl+P) or are you talking about files outside of your project?

0 Likes

#4

Yes, I’m talking about files outside of my project. I want to be able to open new files without having to mess around with the open file GUI, which is system-specific.

Edit:
On the subject of goto-anything, is there are a way to get it to tab-autocomplete? That would be really useful because otherwise you have to scroll down down the list of completions, which takes longer. Unless I’m missing something, of course.

0 Likes

#5

I had started working on a plugin to do this a while back but ended up stopping when I discovered there’s no easy way in the API to add a folder to the sidebar. So now I just use Alfred.app with the default action set to open in ST2. But this wouldn’t be too difficult if you just want to open one file.

0 Likes

#6

The current autocomplete logic in ST isn’t very friendly to items with spaces in them (I suppose it can’t be anyway). I think file system autocompletion should be integrated in the API. I tried to implement it for VintageEx, but never found a working solution. That’s a long way of saying you can’t do that now, I’m afraid.

0 Likes

#7

@guillermooo, I’d imagine that the best way to implement something like this is with an input panel. @Castles was able to add snippets/tabstops and autocompletion into his unfinished version of ZenCoding, so I wouldn’t say it’s impossible. From there, you could do something like AutoFileName does to complete the filename.

0 Likes

#8

@C0D312, an input panel is just a regular view for the most part, so they can implement EventListeners of their own and add snippets, etc. The problem occurs when you have spaces in the items you want to autocomplete. I suppose it can still be done, but I would imagine you’d need to do quite a bit of bookkeeping to see what’s the prefix to base completions on (“C:\Program” or “C:\Program Files” or “C:\Program Files (x86)”, etc.).

0 Likes

#9

Hmmm… AutoFileName seems to handle spaces just fine.

0 Likes

#10

It’s likely what I’m saying’s just a bunch of BS. :smiley: Where’s this AutoFileName thing?

0 Likes

#11

I was in the same boat as you and wrote a plugin that allows you to open a file by path from the prompt. Autocomplete and everything. It can be downloaded from:

bitbucket.org/chrisguilbeau/cg-sublime

Or if you just want to copy the text and paste it into a file:

[code]import sublime, sublime_plugin
from os import listdir
from os.path import commonprefix
from os.path import isdir
from os import getenv

class PromptOpenFilePath(sublime_plugin.WindowCommand):

def run(self):
    currentDir = getenv('HOME') + '/'
    activeView = self.window.active_view()
    if activeView:
        currentFilePath = activeView.file_name()
        if currentFilePath:
            currentFileParts = currentFilePath.split('/')
            currentDir = '/'.join(
                part for part in currentFileParts:-1]) + '/'
    self._ip = self.window.show_input_panel(
        "Open file:",
        currentDir,
        self.on_done,
        self.on_change,
        None
    )

def on_change(self, text):
    if not text:
        return
    if text.endswith('\t'):
        currentFilePath = text.strip('\t')
        currentFileParts = currentFilePath.split('/')
        currentFile = currentFileParts-1]
        currentDir = '/'.join(
            part for part in currentFileParts:-1]) + '/'
        filesInDir = 
            fileName
            for fileName in listdir(currentDir)
            if fileName.startswith(currentFile)
        ]
        if filesInDir:
            if len(filesInDir) > 1:
                sublime.status_message(
                    ', '.join(f for f in filesInDir))
                newPath = currentDir + commonprefix(filesInDir)
            else:
                newPath = currentDir + filesInDir[0]
        else:
            newPath = text:-1]
            sublime.status_message(
                'No files match "%s"' % currentFile)
        theEdit = self._ip.begin_edit()
        allTextRegion = self._ip.full_line(0)
        self._ip.replace(
            theEdit,
            allTextRegion,
            newPath + (
                isdir(newPath) and not newPath.endswith('/') and '/' or '')
            )
        self._ip.end_edit(theEdit)

def on_done(self, text):
    try:
        self.window.open_file(text)
        numGroups = self.window.num_groups()
        currentGroup = self.window.active_group()
        if currentGroup < numGroups - 1:
            newGroup = currentGroup + 1
        else:
            newGroup = 0
        self.window.run_command("move_to_group", {"group": newGroup} )
    except:
        sublime.status_message('Unable to open "%s"' % text)

[/code]

0 Likes

#12

@chrisguilbeau’s plugin seems to work great. It’s a shame window.open_file doesn’t open folders :frowning: but other than that, it should work perfectly.

0 Likes

#13

The package “sublime files” goes some way towards doing what I’d like, but it doesn’t tab auto-complete, which is a pity.

0 Likes

#14

Presumably replacing ‘/’ with os.path.**sep **would enable prompt_open_file_path to work with Windows.

0 Likes

#15

Ah, didn’t see you post, Chris. Thanks, the script works well. I found a minor bug which I will PM you about.

0 Likes