├── .gitignore ├── CHANGELOG.md ├── Context.sublime-menu ├── Default.sublime-commands ├── LICENSE-MIT ├── Main.sublime-menu ├── Phabricator.sublime-settings ├── README.md ├── docs ├── phab_arcanist.png └── sublime_arcanist.png ├── messages.json ├── messages └── install.md ├── phabricator.py └── symlink.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # sublime-phabricator changelog 2 | 3 | 0.5.0 - Fix browse path, allow `arc.land.onto.default` Via @vihangm in #7 and #8 4 | 5 | 0.4.0 - Added setting for preselected `branch`. Via @vihangm in #6 6 | 7 | 0.3.0 - Added context menu for "Open in Phabricator". Via @chrisjantze in #5 8 | 9 | 0.2.0 - Added settings file for specifying `arc` path. Via @yangsu in #4 10 | 11 | 0.1.0 - Initial release 12 | -------------------------------------------------------------------------------- /Context.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | {"caption": "Open in Phabricator", "command": "phabricator_open"} 3 | ] 4 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Phabricator: Open", 4 | "command": "phabricator_open" 5 | } 6 | ] 7 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Uber 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "id": "preferences", 5 | "mnemonic": "n", 6 | "children": 7 | [ 8 | { 9 | "caption": "Package Settings", 10 | "id": "package-settings", 11 | "mnemonic": "P", 12 | "children": 13 | [ 14 | { 15 | "caption": "Phabricator", 16 | "children": 17 | [ 18 | { 19 | "caption": "Settings – Default", 20 | "command": "open_file", "args": 21 | { 22 | "file": "${packages}/Phabricator/Phabricator.sublime-settings" 23 | } 24 | }, 25 | { 26 | "caption": "Settings – User", 27 | "command": "open_file", "args": 28 | { 29 | "file": "${packages}/User/Phabricator.sublime-settings" 30 | } 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /Phabricator.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "arc_path": "arc" 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sublime-phabricator 2 | 3 | Open files in [Phabricator][] via [Sublime Text][] 4 | 5 | This was built to remove the inconvenience of switching to CLI and losing the context of line numbers. It is strongly inspired by [GitHubinator][]. 6 | 7 | [Phabricator]: http://phabricator.org/ 8 | [Sublime Text]: http://sublimetext.com/ 9 | [GitHubinator]: https://github.com/ehamiter/ST2-GitHubinator 10 | 11 | ![Open Phabricator via Sublime Text](docs/sublime_arcanist.png) 12 | 13 | ![View selected content in Phabricator](docs/phab_arcanist.png) 14 | 15 | ## Getting Started 16 | ### Installation 17 | This package is available under `phabricator` inside of [Package Control][], a [Sublime Text][] plugin that allows for easy management of other plugins. 18 | 19 | [Sublime Text]: http://www.sublimetext.com/ 20 | [Package Control]: http://wbond.net/sublime_packages/package_control 21 | 22 | If you prefer the manual route, you can install the script via the following command in the Sublime Text terminal (``ctrl+` ``) which utilizes `git clone`. 23 | 24 | ```python 25 | import os; path=sublime.packages_path(); (os.makedirs(path) if not os.path.exists(path) else None); window.run_command('exec', {'cmd': ['git', 'clone', 'https://github.com/twolfson/sublime-phabricator', 'phabricator'], 'working_dir': path}) 26 | ``` 27 | 28 | Packages can be uninstalled via "Package Control: Remove Package" via the command pallete, `ctrl+shift+p` on Windows/Linux, `command+shift+p` on Mac. 29 | 30 | ### Configuration 31 | Set your preferences by going to `Preferences -> Package Settings -> Phabricator -> Settings - User`. Be sure to set `arc_path` to the absolute path to `arc` in your system. 32 | 33 | Set `branch` to the branch in the repo you want to view files on. 34 | 35 | If you would like the plugin to just use the `arc.land.onto.default` value from the arc config for the current project, 36 | you can leave the branch key unset and instead set `branch_use_arc_land_onto_default` to `True`. 37 | 38 | If neither the `branch` or the `branch_use_arc_land_onto_default` keys are set, the branch you are currently on is used. 39 | 40 | For example, your configuration on Mac OS X may be: 41 | ```json 42 | { 43 | "arc_path": "/usr/local/bin/arc", 44 | "branch": "master" 45 | } 46 | ``` 47 | 48 | ## Documentation 49 | We provide a single command via the command pallete. 50 | 51 | ### Phabricator: Open 52 | Open the current file inside of Phabricator. The first selected area will be highlighted in the open window. 53 | 54 | This command can be accessed as `phabricator_open` via `run_command`. 55 | 56 | ## Contributing 57 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. 58 | 59 | ## License 60 | Copyright (c) 2014 Uber 61 | 62 | Licensed under the MIT license. 63 | -------------------------------------------------------------------------------- /docs/phab_arcanist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uber/sublime-phabricator/f2a83a0be62def1148b08074cb59125082f86d0e/docs/phab_arcanist.png -------------------------------------------------------------------------------- /docs/sublime_arcanist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uber/sublime-phabricator/f2a83a0be62def1148b08074cb59125082f86d0e/docs/sublime_arcanist.png -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "messages/install.md" 3 | } -------------------------------------------------------------------------------- /messages/install.md: -------------------------------------------------------------------------------- 1 | # sublime-phabricator 2 | 3 | Open files in [Phabricator][] via [Sublime Text][] 4 | 5 | This was built to remove the inconvenience of switching to CLI and losing the context of line numbers. It is strongly inspired by [GitHubinator][]. 6 | 7 | [Phabricator]: http://phabricator.org/ 8 | [Sublime Text]: http://sublimetext.com/ 9 | [GitHubinator]: https://github.com/ehamiter/ST2-GitHubinator 10 | 11 | ## Documentation 12 | We provide a single command via the command pallete. 13 | 14 | ### Phabricator: Open 15 | Open the current file inside of Phabricator. The first selected area will be highlighted in the open window. 16 | 17 | This command can be accessed as `phabricator_open` via `run_command`. 18 | 19 | ## Contributing 20 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. 21 | 22 | ## License 23 | Copyright (c) 2014 Uber 24 | 25 | Licensed under the MIT license. 26 | -------------------------------------------------------------------------------- /phabricator.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | try: 4 | # Attempt to load Python 2 quote 5 | from urllib import quote 6 | except ImportError: 7 | # Fallback to Python 3 quote 8 | from urllib.parse import quote 9 | import sublime 10 | import sublime_plugin 11 | import subprocess 12 | 13 | SETTINGS_FILE = 'Phabricator.sublime-settings' 14 | 15 | 16 | class PhabricatorOpenCommand(sublime_plugin.WindowCommand): 17 | def run(self): 18 | """Open a file inside of Phabricator with the selected lines.""" 19 | settings = sublime.load_settings(SETTINGS_FILE) 20 | 21 | # Get the first selection 22 | view = sublime.active_window().active_view() 23 | first_sel = view.sel()[0] 24 | 25 | # Find the lines that are selected. Logic taken from: 26 | # https://github.com/ehamiter/ST2-GitHubinator/blob/c3fce41aaf2fc564/githubinator.py#L44-L49 27 | begin_line = view.rowcol(first_sel.begin())[0] + 1 28 | end_line = view.rowcol(first_sel.end())[0] + 1 29 | if begin_line == end_line: 30 | lines = begin_line 31 | else: 32 | lines = '{0}-{1}'.format(begin_line, end_line) 33 | 34 | # Find the file directory and name 35 | filepath = view.file_name() 36 | filedir = os.path.dirname(filepath) 37 | filename = os.path.basename(filepath) 38 | 39 | # Find the preselected branch 40 | git_branch = settings.get('branch') 41 | 42 | if git_branch is None and settings.get('branch_use_arc_land_onto_default', False): 43 | # Get current branch 44 | arc_args = [settings.get('arc_path', 'arc'), 'get-config', 'arc.land.onto.default'] 45 | arc_child = subprocess.Popen( 46 | arc_args, cwd=filedir, 47 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) 48 | # DEV: We decode for Python 3 which receives bytes 49 | arc_stdout = arc_child.stdout.read().decode('utf-8') 50 | arc_stderr = arc_child.stderr.read().decode('utf-8') 51 | if arc_stderr: 52 | print('Ran `{0}` in `{1}`'.format(' '.join(arc_args), filedir)) 53 | print('STDERR: {0}'.format(arc_stderr)) 54 | 55 | # Grep the output to find the return value. 56 | # If something fails, git_branch will be unset and we will fallthrough into the next 57 | # case 58 | m = re.search('.*Current Value: "(?P.*)"\n.*', arc_stdout) 59 | git_branch = m.group('value') 60 | 61 | # If no preselected branch is provided and we are not using arc.land.onto.default setting 62 | if git_branch is None: 63 | # Get current branch 64 | git_args = ['git', 'symbolic-ref', 'HEAD'] 65 | git_child = subprocess.Popen( 66 | git_args, cwd=filedir, 67 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) 68 | # DEV: We decode for Python 3 which receives bytes 69 | git_stdout = git_child.stdout.read().decode('utf-8') 70 | git_stderr = git_child.stderr.read().decode('utf-8') 71 | if git_stderr: 72 | print('Ran `{0}` in `{1}`'.format(' '.join(git_args), filedir)) 73 | print('STDERR: {0}'.format(git_stderr)) 74 | 75 | # Strip away `refs/head` that Phabricator dislikes 76 | # `refs/heads/dev/my.branch` -> `dev/my.branch` 77 | git_branch = git_stdout.replace('refs/heads/', '').replace('\r', '').replace('\n', '') 78 | 79 | # Double escape branch name for Phabricator 80 | # `dev/my.branch` -> `dev%2Fmy.branch` -> `dev%252Fmy.branch` 81 | escaped_branch = quote(quote(git_branch, safe=''), safe='') 82 | 83 | # Run `arc browse` and dump the output to the console 84 | browse_path = '{0}:{1}'.format(filename, lines) 85 | arc_args = [ 86 | settings.get('arc_path', 'arc'), 'browse', browse_path, '--branch', escaped_branch] 87 | arc_child = subprocess.Popen( 88 | arc_args, cwd=filedir, 89 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) 90 | arc_stdout = arc_child.stdout.read().decode('utf-8') 91 | arc_stderr = arc_child.stderr.read().decode('utf-8') 92 | if arc_stdout or arc_stderr: 93 | print('Ran `{0}` in `{1}`'.format(' '.join(arc_args), filedir)) 94 | if arc_stdout: 95 | print('STDOUT: {0}'.format(arc_stdout)) 96 | if arc_stderr: 97 | print('STDERR: {0}'.format(arc_stderr)) 98 | -------------------------------------------------------------------------------- /symlink.sh: -------------------------------------------------------------------------------- 1 | ln -s $PWD ~/Library/Application\ Support/Sublime\ Text\ 2/Packages/phabricator 2 | --------------------------------------------------------------------------------