├── .gitignore ├── laravelgenerator.sublime-settings ├── README.md ├── Default.sublime-commands └── generate.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /laravelgenerator.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "php_path": "/usr/bin/php" 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## sublime-laravelgenerator 2 | 3 | A Sublime Text plugin that allows you to make use of the [Laravel 4 4 | Generators](https://github.com/JeffreyWay/Laravel-4-Generators) by [Jeffrey 5 | Way](https://github.com/JeffreyWay) directly within Sublime Text. 6 | 7 | ## Installation 8 | 9 | * Install the [Laravel 4 10 | generator commands](https://github.com/JeffreyWay/Laravel-4-Generators) through Composer. 11 | * Install the ST plugin through Package Control: *Sublime Laravel Generator* 12 | * If you are on Windows or php executable is not in PATH, please specify the path to it in `laravelgenerator.sublime-settings`. To do so, copy `laravelgenerator.sublime-settings` from this 13 | plugin to `/Users/` and make the edits to that file. 14 | 15 | ## Usage 16 | 17 | * Open a Laravel Project 18 | * Open the command palette (Ctrl+Shift+P) 19 | * Execute any of the available Generate commands 20 | * See here for a basic workflow [video](http://tutsplus.s3.amazonaws.com/tutspremium/courses_$folder$/WhatsNewInLaravel4/Laravel-Generators-and-Sublime-Text-Workflow.mp4) 21 | 22 | *Note*: `artisan` needs to be in the project root. 23 | 24 | ## Customization 25 | 26 | The plugin is quite extensible. Interested users can extend the plugin for more 27 | artisan commands by adding the appropriate entries in 28 | `Default.sublime-commands`. 29 | 30 | ## Credits 31 | 32 | * [Jeffrey Way](https://github.com/JeffreyWay): for the idea and testing this 33 | plugin throughout the development. 34 | 35 | *** 36 | 37 | *This is a work in progress. Feedback is appreciated. Feel free to report any 38 | issues you come across* 39 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Laravel Generate: Model", 4 | "command": "generate", 5 | "args": { 6 | "generate": "model", 7 | "fill_in": "Enter the name of the model" 8 | } 9 | }, 10 | { 11 | "caption": "Laravel Generate: Seed", 12 | "command": "generate", 13 | "args": { 14 | "generate": "seed", 15 | "fill_in": "Enter the table name you're seeding" 16 | } 17 | }, 18 | { 19 | "caption": "Laravel Generate: Test", 20 | "command": "generate", 21 | "args": { 22 | "generate": "test", 23 | "fill_in": "Enter the file name for the test" 24 | } 25 | }, 26 | { 27 | "caption": "Laravel Generate: View", 28 | "command": "generate", 29 | "args": { 30 | "generate": "view", 31 | "fill_in": "Enter the file name of the view", 32 | "path": true, 33 | "path_label": "Specify path relative to 'app/views/' (optional)" 34 | } 35 | }, 36 | { 37 | "caption": "Laravel Generate: Migration", 38 | "command": "generate", 39 | "args": { 40 | "generate": "migration", 41 | "fill_in": "Enter the Migration Name", 42 | "fields": true, 43 | "fields_label": "Table fields in the column:type format (optional)" 44 | } 45 | }, 46 | { 47 | "caption": "Laravel Generate: Resource", 48 | "command": "generate", 49 | "args": { 50 | "generate": "resource", 51 | "fill_in": "Enter the singular name of the resource", 52 | "fields": true, 53 | "fields_label": "Table fields in the column:type format (optional)" 54 | } 55 | }, 56 | { 57 | "caption": "Laravel Generate: Scaffold", 58 | "command": "generate", 59 | "args": { 60 | "generate": "scaffold", 61 | "fill_in": "Enter the singular name of the resource", 62 | "fields": true, 63 | "fields_label": "Table fields in the column:type format (optional)" 64 | } 65 | }, 66 | { 67 | "caption": "Laravel Artisan Command", 68 | "command": "artisan" 69 | } 70 | ] 71 | -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import time 4 | import shlex 5 | import subprocess 6 | import sublime 7 | import sublime_plugin 8 | 9 | class GenerateCommand(sublime_plugin.WindowCommand): 10 | def __init__(self, *args, **kwargs): 11 | super(GenerateCommand, self).__init__(*args, **kwargs) 12 | 13 | settings = sublime.load_settings('laravelgenerator.sublime-settings') 14 | self.php_path = settings.get('php_path', 'php') 15 | 16 | def run(self, *args, **kwargs): 17 | self.command = kwargs.get('generate', None) 18 | self.fill_in = kwargs.get('fill_in', 'Enter the resource name') 19 | self.accept_fields = kwargs.get('fields', False) 20 | self.fields_label = kwargs.get('fields_label', 'Enter the fields') 21 | self.accept_path = kwargs.get('path', False) 22 | self.path_label = kwargs.get('path_label', 'Enter the path') 23 | 24 | try: 25 | # The first folder needs to be the Laravel Project 26 | self.PROJECT_PATH = self.window.folders()[0] 27 | self.args = [self.php_path, os.path.join(self.PROJECT_PATH, 'artisan'), 'generate:%s' % self.command] 28 | 29 | if os.path.isfile("%s" % os.path.join(self.PROJECT_PATH, 'artisan')): 30 | if self.command in ['model', 'seed', 'test', 'view', 'migration', 'resource', 'scaffold']: 31 | # call function to do the work 32 | self.window.show_input_panel(self.fill_in, '', self.call_artisan, None, None) 33 | else: 34 | sublime.status_message("Generator command not supported") 35 | else: 36 | sublime.status_message("Artisan not found") 37 | except IndexError: 38 | sublime.status_message("Please open a Laravel Project") 39 | 40 | def call_artisan(self, value=''): 41 | if self.accept_fields: 42 | self.args.extend([value, '--fields=']) 43 | self.accept_fields = False 44 | self.window.show_input_panel(self.fields_label, '', self.call_artisan, None, None) 45 | elif self.accept_path and self.command == 'view': 46 | self.args.extend([value, '--path=%s' % os.path.join(self.PROJECT_PATH, 'app/views/')]) 47 | self.accept_path = False 48 | self.window.show_input_panel(self.path_label, '', self.call_artisan, None, None) 49 | else: 50 | if self.args[-1] == '--fields=': 51 | self.args[-1] += '%s' % value 52 | elif self.args[-1] == '--path=%s' % os.path.join(self.PROJECT_PATH, 'app/views/'): 53 | self.args[-1] += '%s' % value 54 | else: 55 | self.args.append(value) 56 | if os.name != 'posix': 57 | self.args = subprocess.list2cmdline(self.args) 58 | try: 59 | proc = subprocess.Popen(self.args, cwd=self.PROJECT_PATH, shell=False, stdout=subprocess.PIPE) 60 | self.proc_status(proc) 61 | except IOError: 62 | sublime.status_message('IOError - command aborted') 63 | 64 | def proc_status(self, proc): 65 | if proc.poll() is None: 66 | sublime.set_timeout(lambda: self.proc_status(proc), 200) 67 | else: 68 | output = proc.communicate()[0].decode('utf-8') 69 | match = re.search(r'/app/\w+/.*[.]php', output) 70 | if match: 71 | if not self.command == 'resource': 72 | self.window.open_file('%s%s' % (self.PROJECT_PATH, match.group(0))) 73 | sublime.status_message("%s generated successfully!" % self.command) 74 | else: 75 | sublime.status_message("Oh snap! generate:%s failed - %s" % (self.command, output)) 76 | 77 | class ArtisanCommand(sublime_plugin.WindowCommand): 78 | def __init__(self, *args, **kwargs): 79 | super(ArtisanCommand, self).__init__(*args, **kwargs) 80 | 81 | settings = sublime.load_settings('laravelgenerator.sublime-settings') 82 | self.php_path = settings.get('php_path', 'php') 83 | 84 | def run(self, *args, **kwargs): 85 | self.window.show_input_panel('Enter an artisan command', '', self.call_artisan, None, None) 86 | 87 | def call_artisan(self, command): 88 | try: 89 | self.PROJECT_PATH = self.window.folders()[0] 90 | self.args = '%s %s %s' % (self.php_path, os.path.join(self.PROJECT_PATH, 'artisan'), command) 91 | if os.name == 'posix': 92 | self.args = shlex.split(str(self.args)) 93 | 94 | if command: 95 | try: 96 | proc = subprocess.Popen(self.args, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 97 | self.proc_status(proc, command) 98 | except IOError: 99 | sublime.status_message('IOError - command aborted') 100 | else: 101 | sublime.status_message('Command not set') 102 | except IndexError: 103 | sublime.status_message('Please open a Laravel Project') 104 | 105 | def proc_status(self, proc, command): 106 | if proc.poll() is None: 107 | sublime.set_timeout(lambda: self.proc_status(proc, command), 200) 108 | else: 109 | result = [x.decode('utf-8') for x in proc.communicate()] 110 | panel_name = 'artisan_output' 111 | panel = self.window.get_output_panel(panel_name) 112 | if not result[1]: 113 | if command == 'routes': 114 | panel.run_command('artisan_output', {'insert': result[0]}) 115 | self.window.run_command('show_panel', {'panel': 'output.' + panel_name}) 116 | sublime.status_message('artisan %s executed successfully' % command) 117 | else: 118 | panel.run_command('artisan_output', {'insert': result[1]}) 119 | self.window.run_command('show_panel', {'panel': 'output.' + panel_name}) 120 | sublime.status_message('artisan %s failed' % command) 121 | 122 | class ArtisanOutputCommand(sublime_plugin.TextCommand): 123 | def run(self, edit, insert): 124 | self.view.insert(edit, 0, insert) 125 | --------------------------------------------------------------------------------