import sublime, sublime_plugin | |
class ImplementCommand(sublime_plugin.TextCommand): | |
# Gets the currently selected symbol | |
# | |
def get_selected_symbol(self): | |
point = self.view.sel()[0] | |
region = self.view.word(point) | |
return self.view.substr(region) | |
# Gets files with names that match the currently selected symbol | |
# | |
def get_matching_files(self): | |
window = self.view.window() | |
selected_symbol = self.get_selected_symbol() | |
locations = window.lookup_symbol_in_index(selected_symbol) | |
files = [] | |
for location in locations: | |
files.append(location[0]) | |
return files | |
# Handles the selection of a quick panel item | |
# | |
def on_done(self, index): | |
if index == -1: | |
return | |
self.view.run_command("parse", {"path": self.files[index]}) | |
# Runs the plugin | |
# | |
def run(self, edit): | |
self.files = self.get_matching_files() | |
if (len(self.files) == 1): | |
self.view.run_command("parse", {"path": self.files[0]}) | |
if (len(self.files) > 1): | |
self.view.window().show_quick_panel(self.files, self.on_done) |
import sublime, sublime_plugin, re | |
class ParseCommand(sublime_plugin.TextCommand): | |
# Normalizes a given path to the current system style | |
# -- This method is from the PHP Companion utils file | |
# | |
def normalize_to_system_style_path(self, path): | |
if sublime.platform() == "windows": | |
path = re.sub(r"/([A-Za-z])/(.+)", r"\1:/\2", path) | |
path = re.sub(r"/", r"\\", path) | |
return path | |
# Runs the plugin | |
# | |
def run(self, edit, path): | |
# Get the contents of the file at the given path | |
with open(self.normalize_to_system_style_path(path), "r") as f: | |
content = f.read() | |
# Get the methods from the content | |
self.methods = re.findall("(?<!\* )(?:abstract )?(?:public|protected|private)(?: static)? function [A-z0-9]*\([A-z0-9$=, ]*\)[A-z :]*", content) | |
self.methods.insert(0, 'Insert all methods') | |
# Show the available methods in the quick panel | |
if (len(self.methods) > 0): | |
self.view.window().show_quick_panel(self.methods, self.on_done) | |
# Handles selection of a quick panel item | |
# | |
def on_done(self, index): | |
if index == -1: | |
return | |
# Find the closing brackets. We'll place the method | |
# stubs just before the last closing bracket. | |
closing_brackets = self.view.find_all("[}]") | |
# Add the method stub(s) to the current file | |
region = closing_brackets[-1] | |
point = region.end() - 1 | |
template = "\n\t{0}\n\t{{\n\t\tthrow new \Exception('Method not implemented');\n\t}}\n" | |
# Better way to handle add all selection? | |
if index == 0: | |
for method in self.methods[1:]: | |
method_stub = template.format(method) | |
self.view.run_command("create", {"stub": method_stub, "offset": point}) | |
else: | |
method_stub = template.format(self.methods[index]) | |
self.view.run_command("create", {"stub": method_stub, "offset": point}) |
This comment has been minimized.
This comment has been minimized.
Looks awesome! I like being able to select the methods. That works better for abstract classes anyway, which I forgot about at first. I'll play around with a better regex too. Also, this one doesn't do anything if more than one file is found. I'll tinker around on your fork and share it then. |
This comment has been minimized.
This comment has been minimized.
Here is a long winded regex that does a bit better: https://regex101.com/r/yD6nY7/7. Edit (newer version with unit tests): https://regex101.com/r/yD6nY7/12 |
This comment has been minimized.
This comment has been minimized.
Take a look at the updated gist when you have some time. It now supports multiple files, like if you are working with a lot of packages that have some overlapping names. I also tweaked the regex and it seems to be working pretty nicely. It accommodates a mix of abstract, static, and other methods with various visibility. I also tested it with type hinting and return type declarations since I think that has been approved for PHP7. Updated: Also just added an "Insert all methods" option as well. For interfaces, this would be useful if you have an empty class that you are just starting to work on. |
This comment has been minimized.
This comment has been minimized.
What keybinding do you use ? |
This comment has been minimized.
This comment has been minimized.
I am using f1 at the moment. It runs implement.py to kick everything off.
|
This comment has been minimized.
This comment has been minimized.
This seems like a really useful script, could you turn it into a plugin and upload it to package control? It would be much easier to install then and easier for people to find. |
This comment has been minimized.
This comment has been minimized.
Glad you think it looks useful, thanks for the feedback! I was hoping we could add this to PHP Companion (erichard's awesome plugin) instead of making a standalone plugin. Right now I use it by downloading a zip of this gist and dropping it into my packages folder. I'm on Windows so the directory is C:\Users\USERNAME\AppData\Roaming\Sublime Text 3\Packages. Not sure what it is on OS X or Linux. Then you need to add a keybinding like the one I mentioned in the comment above to run the command. |
This comment has been minimized.
Checkout my fork. Instead of inserting all methods I let the user choose the method he wants. Also I think the
findall
method on line 40 a bit too simple.It doesn't match theses methods :
public static function myStaticMethod()
protected function myProtectedMethod()
But will match function statement in comments :
Not sure we can do all with regexes but I will try...