├── dep └── shellenv │ ├── __init__.pyc │ ├── _posix.pyc │ ├── _types.pyc │ ├── _encoding.pyc │ ├── _linux │ ├── getent.pyc │ ├── __init__.pyc │ ├── getent.py │ └── __init__.py │ ├── _types.py │ ├── _osx │ ├── __init__.py │ ├── core_foundation.py │ └── open_directory.py │ ├── __init__.py │ ├── _win.py │ ├── _posix.py │ └── _encoding.py ├── messages.json ├── AUTHORS.md ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── CHANGELOG.md ├── messages ├── install.txt └── 0.1.9.txt ├── LICENSE.md ├── Default.sublime-settings ├── Default.sublime-commands ├── GoRenameResults.tmLanguage ├── Main.sublime-menu ├── README.md └── goRename.py /dep/shellenv/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/__init__.pyc -------------------------------------------------------------------------------- /dep/shellenv/_posix.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/_posix.pyc -------------------------------------------------------------------------------- /dep/shellenv/_types.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/_types.pyc -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "messages/install.txt", 3 | "0.1.9": "messages/0.1.9.txt" 4 | } 5 | -------------------------------------------------------------------------------- /dep/shellenv/_encoding.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/_encoding.pyc -------------------------------------------------------------------------------- /dep/shellenv/_linux/getent.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/_linux/getent.pyc -------------------------------------------------------------------------------- /dep/shellenv/_linux/__init__.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alvarolm/GoRename/HEAD/dep/shellenv/_linux/__init__.pyc -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | This is the official list of GoSublime authors for copyright purposes. 2 | 3 | * Jesse "waigani" Meek https://github.com/waigani 4 | * Jordan "Liggitt" https://github.com/liggitt 5 | * David Eads https://github.com/deads2k -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+alt+r"], "command": "go_rename"}, 3 | { "keys": ["ctrl+alt+shift+r"], "command": "go_rename_show_results"}, 4 | 5 | { "keys": ["enter"], "command": "go_rename_confirm", "context": 6 | [{ "key": "selector", "operator": "equal", "operand": "text.gorename-results" }] 7 | } 8 | 9 | ] -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+alt+r"], "command": "go_rename"}, 3 | { "keys": ["ctrl+alt+shift+r"], "command": "go_rename_show_results"}, 4 | 5 | { "keys": ["enter"], "command": "go_rename_confirm", "context": 6 | [{ "key": "selector", "operator": "equal", "operand": "text.gorename-results" }] 7 | } 8 | 9 | ] -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["ctrl+alt+r"], "command": "go_rename"}, 3 | { "keys": ["ctrl+alt+shift+r"], "command": "go_rename_show_results"}, 4 | 5 | { "keys": ["enter"], "command": "go_rename_confirm", "context": 6 | [{ "key": "selector", "operator": "equal", "operand": "text.gorename-results" }] 7 | } 8 | 9 | ] -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | GoRename Changes 2 | ---------------- 3 | 4 | ## 0.1.0 5 | * ... 6 | 7 | ## 0.1.1 (first working version) 8 | * new feature: prevent renaming when referenced file has changed 9 | * new feature: arguments review before renaming 10 | * new feature: enable optional flags (-d, -force, -v) per renaming basis 11 | 12 | -------------------------------------------------------------------------------- /dep/shellenv/_types.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import sys 5 | 6 | 7 | if sys.version_info < (3,): 8 | str_cls = unicode # noqa 9 | byte_cls = str 10 | 11 | else: 12 | str_cls = str 13 | byte_cls = bytes 14 | 15 | 16 | def type_name(value): 17 | """ 18 | Returns a user-readable name for the type of an object 19 | 20 | :param value: 21 | A value to get the type name of 22 | 23 | :return: 24 | A unicode string of the object's type name 25 | """ 26 | 27 | cls = value.__class__ 28 | if cls.__module__ in set(['builtins', '__builtin__']): 29 | return cls.__name__ 30 | return '%s.%s' % (cls.__module__, cls.__name__) 31 | -------------------------------------------------------------------------------- /messages/install.txt: -------------------------------------------------------------------------------- 1 | 2 | _____ _____ 3 | / ____| | __ \ 4 | | | __ ___ | |__) |___ _ __ __ _ _ __ ___ ___ 5 | | | |_ |/ _ \| _ // _ \ '_ \ / _` | '_ ` _ \ / _ \ 6 | | |__| | (_) | | \ \ __/ | | | (_| | | | | | | __/ 7 | \_____|\___/|_| \_\___|_| |_|\__,_|_| |_| |_|\___| 8 | 9 | 10 | Thanks for using GoRename ! 11 | Please report any issues or improvements here: 12 | 13 | https://github.com/alvarolm/GoRename/issues 14 | 15 | For instructions on how to use this package 16 | check out README.md: from menu: 17 | Preferences > Package Settings > GoRename > Read Me 18 | 19 | http://alvarolm.github.io/GoRename 20 | 21 | ;-) -------------------------------------------------------------------------------- /messages/0.1.9.txt: -------------------------------------------------------------------------------- 1 | 2 | _____ _____ 3 | / ____| | __ \ 4 | | | __ ___ | |__) |___ _ __ __ _ _ __ ___ ___ 5 | | | |_ |/ _ \| _ // _ \ '_ \ / _` | '_ ` _ \ / _ \ 6 | | |__| | (_) | | \ \ __/ | | | (_| | | | | | | __/ 7 | \_____|\___/|_| \_\___|_| |_|\__,_|_| |_| |_|\___| 8 | _ _ 9 | | | | | 10 | _ _ _ __ __| | __ _| |_ ___ 11 | | | | | '_ \ / _` |/ _` | __/ _ \ 12 | | |_| | |_) | (_| | (_| | || __/ 13 | \__,_| .__/ \__,_|\__,_|\__\___| 14 | | | 15 | |_| 16 | 17 | Version 0.1.9 18 | 19 | the settings variables have been renamed, 20 | so remember to update your user config 21 | otherwise GoRename may not work as you expected. 22 | 23 | Alvaro -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 The GoOracle Authors 2 | 3 | Permission is herby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /dep/shellenv/_osx/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | from .._posix import get_shell_env 5 | 6 | 7 | def get_env(shell=None, for_subprocess=False): 8 | """ 9 | Uses the user's login shell to fetch the environmental variables that are 10 | set when a new shell is opened. This is necessary since on OS X, Sublime 11 | Text is launched from the dock, which does not pick up the user's shell 12 | environment. 13 | 14 | :param shell: 15 | The shell to get the env from, if None, uses the current user's login 16 | shell 17 | 18 | :param for_subprocess: 19 | If True, and the code is being run in Sublime Text 2, the result will 20 | be byte strings instead of unicode strings 21 | 22 | :return: 23 | A 2-element tuple: 24 | 25 | - [0] unicode string shell path 26 | - [1] env dict with keys and values as unicode strings 27 | """ 28 | 29 | return get_shell_env(shell, for_subprocess=for_subprocess) 30 | -------------------------------------------------------------------------------- /Default.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "gorename_version" : "0.1.12", // DO NOT MODIFY 3 | // Please do not edit this file, instead use the user config. 4 | 5 | // rename files that had been modified after the 'go_rename' command has been executed. 6 | // (DO NOT set to true unless you want a renaming nightmare) 7 | "gorename_rename_modified_files": false, 8 | 9 | // use golangconfig, if false then shellenv will be used to get golang environment variables 10 | "gorename_use_golangconfig": false, 11 | 12 | // fill variable name text field by default 13 | "gorename_autofill": false, 14 | 15 | // The output can either be one of: 'buffer', 'output_panel' 16 | // Buffers can hold results from more than one invocation 17 | // Output panels sit underneath the editor area and are easily dismissed 18 | "gorename_output": "output_panel", 19 | 20 | // print debug info to the terminal 21 | "gorename_debug": false, 22 | 23 | // env overwrites the default shell environment vars 24 | // e.g "env": { "GOPATH": "$HOME/go/bin:$PATH" } 25 | // not used when gorename_use_golangconfig is set to true 26 | "gorename_env": {}, 27 | } 28 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "GoRename", 4 | "command": "go_rename" 5 | }, 6 | { 7 | "caption": "GoRename: Show Results", 8 | "command": "go_guru_show_results" 9 | }, 10 | { 11 | "caption": "GoRename: User Settings", 12 | "command": "open_file", 13 | "args": { 14 | "file": "${packages}/User/GoRename.sublime-settings" 15 | } 16 | }, 17 | { 18 | "caption": "GoRename: Default Settings", 19 | "command": "open_file", 20 | "args": { 21 | "file": "${packages}/GoRename/Default.sublime-settings" 22 | } 23 | }, 24 | { 25 | "caption": "GoRename: Default Key Bindings", 26 | "command": "open_file", 27 | "args": { 28 | "file": "${packages}/GoRename/Default (Linux).sublime-keymap", 29 | "platform": "Linux" 30 | } 31 | }, 32 | { 33 | "caption": "GoRename: Default Key Bindings", 34 | "command": "open_file", 35 | "args": { 36 | "file": "${packages}/GoRename/Default (Windows).sublime-keymap", 37 | "platform": "Windows" 38 | } 39 | }, 40 | { 41 | "caption": "GoRename: Default Key Bindings", 42 | "command": "open_file", 43 | "args": { 44 | "file": "${packages}/GoRename/Default (OSX).sublime-keymap", 45 | "platform": "OSX" 46 | } 47 | }, 48 | 49 | ] 50 | -------------------------------------------------------------------------------- /dep/shellenv/_linux/getent.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import subprocess 5 | from getpass import getuser 6 | 7 | from .._types import str_cls, type_name 8 | 9 | 10 | _login_shells = {} 11 | 12 | 13 | def get_user_login_shell(username=None): 14 | """ 15 | Uses getent to get the user's login shell 16 | 17 | :param username: 18 | A unicode string of the user to get the shell for - None for the 19 | current user 20 | 21 | :return: 22 | A unicode string of the user's login shell 23 | """ 24 | 25 | if username is None: 26 | username = getuser() 27 | if not isinstance(username, str_cls): 28 | username = username.decode('utf-8') 29 | 30 | if not isinstance(username, str_cls): 31 | raise TypeError('username must be a unicode string, not %s' % type_name(username)) 32 | 33 | if username not in _login_shells: 34 | 35 | proc = subprocess.Popen(['getent', 'passwd', username], stdout=subprocess.PIPE) 36 | 37 | out = b'' 38 | while proc.poll() is None: 39 | out += proc.stdout.read() 40 | out += proc.stdout.read() 41 | 42 | proc.stdout.close() 43 | 44 | line = out.decode('utf-8').strip() 45 | parts = line.split(':', 6) 46 | login_shell = parts[6] 47 | 48 | _login_shells[username] = login_shell 49 | 50 | return _login_shells.get(username) 51 | -------------------------------------------------------------------------------- /GoRenameResults.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Gorename Results 7 | 8 | patterns 9 | 10 | 11 | 12 | match 13 | "([^"]*:[0-9]+:[0-9]+)" 14 | captures 15 | 16 | 1 17 | 18 | name 19 | entity.name.filename.find-in-files 20 | 21 | 22 | 23 | 24 | 25 | match 26 | ^([^:]*:[0-9]+.[0-9]+)[-:] 27 | captures 28 | 29 | 1 30 | 31 | name 32 | entity.name.filename.find-in-files 33 | 34 | 35 | 36 | 37 | 38 | 39 | match 40 | \>([^"]*:[0-9]+:[0-9]+)< 41 | captures 42 | 43 | 1 44 | 45 | name 46 | entity.name.filename.find-in-files 47 | 48 | 49 | 50 | 51 | 52 | scopeName 53 | text.gorename-results 54 | 55 | 56 | -------------------------------------------------------------------------------- /dep/shellenv/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import sys 5 | import os 6 | from getpass import getuser 7 | 8 | from ._types import str_cls, type_name 9 | from ._encoding import env_encode, env_decode, path_encode, path_decode # noqa 10 | 11 | if sys.platform == 'win32': 12 | from ._win import get_env, get_user_login_shell 13 | 14 | elif sys.platform == 'darwin': 15 | from ._osx import get_env 16 | from ._osx.open_directory import get_user_login_shell 17 | 18 | else: 19 | from ._linux import get_env 20 | from ._linux.getent import get_user_login_shell # noqa 21 | 22 | 23 | __version__ = '1.4.2' 24 | __version_info__ = (1, 4, 2) 25 | 26 | 27 | _paths = {} 28 | 29 | 30 | def get_path(shell=None): 31 | """ 32 | Returns the PATH as defined by the shell. If no shell is provided, gets the 33 | path from the user's login shell. 34 | 35 | :param shell: 36 | A unicode string of the shell to get the PATH from. Pass None to use 37 | the current user's login shell. 38 | 39 | :return: 40 | A 2-element tuple: 41 | 42 | - [0] a unicode string of the shell the path was retrieved from 43 | - [1] a list of unicode strings of the directories that are part of the PATH 44 | """ 45 | 46 | if shell is not None and not isinstance(shell, str_cls): 47 | raise TypeError('shell must be a unicode string, not %s' % type_name(shell)) 48 | 49 | shell_key = shell if shell else 'default' 50 | if shell_key not in _paths: 51 | shell, env = get_env(shell) 52 | _paths[shell_key] = (shell, env.get('PATH', '').split(os.pathsep)) 53 | return _paths[shell_key] 54 | 55 | 56 | def get_user(): 57 | """ 58 | Returns the current username as a unicode string 59 | 60 | :return: 61 | A unicode string of the current user's username 62 | """ 63 | 64 | output = getuser() 65 | if not isinstance(output, str_cls): 66 | output = output.decode('utf-8') 67 | return output 68 | -------------------------------------------------------------------------------- /dep/shellenv/_linux/__init__.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import os 5 | import sys 6 | 7 | from .._posix import get_shell_env 8 | from .getent import get_user_login_shell 9 | 10 | 11 | def get_env(shell=None, for_subprocess=False): 12 | """ 13 | Fetches the environmental variables for the current user. This is necessary 14 | since depending on how the sublime_text binary is launched, the process will 15 | not get the environment a user has in the terminal. 16 | 17 | Because sublime_text may have been launched from the terminal, the env from 18 | the shell specified and python's os.environ are compared to see which 19 | contains more information. 20 | 21 | :param shell: 22 | The shell to get the env from, if None, uses the current user's login 23 | shell 24 | 25 | :param for_subprocess: 26 | If True, and the code is being run in Sublime Text 2, the result will 27 | be byte strings instead of unicode strings 28 | 29 | :return: 30 | A 2-element tuple: 31 | 32 | - [0] unicode string shell path 33 | - [1] env dict with keys and values as unicode strings 34 | """ 35 | 36 | # If we should compare the login shell env and os.environ 37 | # to see which seems to contain the correct information 38 | compare = False 39 | 40 | login_shell = get_user_login_shell() 41 | 42 | if shell is None: 43 | shell = login_shell 44 | compare = True 45 | elif shell == login_shell: 46 | compare = True 47 | 48 | if not compare: 49 | return get_shell_env(shell, for_subprocess=for_subprocess) 50 | 51 | _, login_env = get_shell_env(shell, for_subprocess=for_subprocess) 52 | 53 | if sys.version_info < (3,) and for_subprocess: 54 | shell = shell.encode('utf-8') 55 | 56 | if len(login_env) >= len(os.environ): 57 | return (shell, login_env) 58 | 59 | if sys.version_info < (3,) and not for_subprocess: 60 | values = {} 61 | for key, value in os.environ.items(): 62 | values[key.decode('utf-8', 'replace')] = value.decode('utf-8', 'replace') 63 | else: 64 | values = dict(os.environ) 65 | 66 | return (shell, values) 67 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "id": "preferences", 5 | "children": 6 | [ 7 | { 8 | "caption": "Package Settings", 9 | "id": "package-settings", 10 | "children": 11 | [ 12 | { 13 | "caption": "GoRename", 14 | "children": 15 | [ 16 | { 17 | "caption": "Settings – Default", 18 | "command": "open_file", 19 | "args": { 20 | "file": "${packages}/GoRename/Default.sublime-settings" 21 | } 22 | }, 23 | { 24 | "caption": "Settings – User", 25 | "command": "open_file", 26 | "args": { 27 | "file": "${packages}/User/GoRename.sublime-settings" 28 | } 29 | }, 30 | { "caption": "-" }, 31 | { 32 | "caption": "Key Bindings – Default", 33 | "platform": "Linux", 34 | "command": "open_file", 35 | "args": { 36 | "file": "${packages}/GoRename/Default (Linux).sublime-keymap" 37 | } 38 | }, 39 | { 40 | "caption": "Key Bindings – Default", 41 | "platform": "Windows", 42 | "command": "open_file", 43 | "args": { 44 | "file": "${packages}/GoRename/Default (Windows).sublime-keymap" 45 | } 46 | }, 47 | { 48 | "caption": "Key Bindings – Default", 49 | "platform": "OSX", 50 | "command": "open_file", 51 | "args": { 52 | "file": "${packages}/GoRename/Default (OSX).sublime-keymap" 53 | } 54 | }, 55 | { "caption": "-" }, 56 | { 57 | "caption": "Changes & Announcements", 58 | "command": "open_file", 59 | "args": { 60 | "file": "${packages}/GoRename/CHANGELOG.md" 61 | } 62 | }, 63 | { "caption": "-" }, 64 | { 65 | "caption": "Read Me", 66 | "command": "open_file", 67 | "args": { 68 | "file": "${packages}/GoRename/README.md" 69 | } 70 | }, 71 | { 72 | "caption": "Authors & Contributors", 73 | "command": "open_file", 74 | "args": { 75 | "file": "${packages}/GoRename/AUTHORS.md" 76 | } 77 | }, 78 | { 79 | "caption": "License (MIT)", 80 | "command": "open_file", 81 | "args": { 82 | "file": "${packages}/GoRename/LICENSE.md" 83 | } 84 | } 85 | ] 86 | } 87 | ] 88 | } 89 | ] 90 | } 91 | ] 92 | -------------------------------------------------------------------------------- /dep/shellenv/_win.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import os 5 | import locale 6 | import sys 7 | import ctypes 8 | 9 | from ._types import str_cls 10 | 11 | 12 | _sys_encoding = locale.getpreferredencoding() 13 | 14 | kernel32 = ctypes.windll.kernel32 15 | 16 | kernel32.GetEnvironmentStringsW.argtypes = [] 17 | kernel32.GetEnvironmentStringsW.restype = ctypes.c_void_p 18 | 19 | 20 | def get_env(shell=None, for_subprocess=False): 21 | """ 22 | Return environment variables for the current user 23 | 24 | :param shell: 25 | The shell to get the env from - unused on Windows 26 | 27 | :param for_subprocess: 28 | If True, and the code is being run in Sublime Text 2, the result will 29 | be byte strings instead of unicode strings 30 | 31 | :return: 32 | A 2-element tuple: 33 | 34 | - [0] unicode string shell path 35 | - [1] env dict with keys and values as unicode strings 36 | """ 37 | 38 | shell = os.environ['ComSpec'] 39 | if not isinstance(shell, str_cls) and for_subprocess is False: 40 | shell = shell.decode(_sys_encoding) 41 | 42 | if sys.version_info < (3,) and for_subprocess is False: 43 | str_pointer = kernel32.GetEnvironmentStringsW() 44 | string = ctypes.wstring_at(str_pointer) 45 | 46 | values = {} 47 | while string != '': 48 | if string[0].isalpha(): 49 | name, value = string.split(u'=', 1) 50 | values[name.upper()] = value 51 | # Include the trailing null byte, and measure each 52 | # char as 2 bytes since Windows uses UTF-16 for 53 | # wide chars 54 | str_pointer += (len(string) + 1) * 2 55 | string = ctypes.wstring_at(str_pointer) 56 | else: 57 | values = dict(os.environ) 58 | 59 | return (shell, values) 60 | 61 | 62 | def get_user_login_shell(username=None): 63 | """ 64 | Return the path to cmd.exe. Exists for API compatiblity with OS X/Linux. 65 | 66 | :param username: 67 | A unicode string of the user to get the shell for - None for the 68 | current user 69 | 70 | :return: 71 | A unicode string of the user's login shell 72 | """ 73 | 74 | shell = os.environ['ComSpec'] 75 | if not isinstance(shell, str_cls): 76 | shell = shell.decode(_sys_encoding) 77 | return shell 78 | -------------------------------------------------------------------------------- /dep/shellenv/_posix.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import re 5 | import os 6 | import sys 7 | import subprocess 8 | 9 | from ._types import str_cls, type_name 10 | 11 | if sys.platform == 'darwin': 12 | from ._osx.open_directory import get_user_login_shell 13 | else: 14 | from ._linux.getent import get_user_login_shell 15 | 16 | 17 | _envs = {'bytes': {}, 'unicode': {}} 18 | 19 | 20 | def get_shell_env(shell=None, for_subprocess=False): 21 | """ 22 | Fetches the environmental variables that are set when a new shell is opened. 23 | 24 | :param shell: 25 | The shell to get the env from, if None, uses the current user's login 26 | shell 27 | 28 | :param for_subprocess: 29 | If True, and the code is being run in Sublime Text 2, the result will 30 | be byte strings instead of unicode strings 31 | 32 | :return: 33 | A 2-element tuple: 34 | 35 | - [0] unicode string shell path 36 | - [1] env dict with keys and values as unicode strings 37 | """ 38 | 39 | if shell is not None and not isinstance(shell, str_cls): 40 | raise TypeError('shell must be a unicode string, not %s' % type_name(shell)) 41 | 42 | if shell is None: 43 | shell = get_user_login_shell() 44 | _, shell_name = shell.rsplit('/', 1) 45 | 46 | output_type = 'bytes' if sys.version_info < (3,) and for_subprocess else 'unicode' 47 | 48 | if shell not in _envs[output_type]: 49 | args = [shell, '-l'] 50 | # For bash we invoke interactively or else ~/.bashrc is not 51 | # loaded, and many distros and users use .bashrc for env vars 52 | if shell_name == 'bash': 53 | args.append('-i') 54 | env_proc = subprocess.Popen( 55 | args, 56 | stdin=subprocess.PIPE, 57 | stdout=subprocess.PIPE, 58 | stderr=subprocess.STDOUT 59 | ) 60 | 61 | stdout, _ = env_proc.communicate(b'/usr/bin/env\n') 62 | 63 | _envs[output_type][shell] = {} 64 | 65 | entries = re.split(b'\n(?=\\w+=)', stdout.strip()) 66 | for entry in entries: 67 | if entry == b'': 68 | continue 69 | parts = entry.split(b'=', 1) 70 | if len(parts) < 2: 71 | continue 72 | name = parts[0] 73 | value = parts[1] 74 | if output_type == 'unicode': 75 | name = name.decode('utf-8', 'replace') 76 | value = value.decode('utf-8', 'replace') 77 | _envs[output_type][shell][name] = value 78 | 79 | if output_type == 'bytes': 80 | shell = shell.encode('utf-8') 81 | 82 | return (shell, _envs[output_type][shell].copy()) 83 | -------------------------------------------------------------------------------- /dep/shellenv/_encoding.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import locale 3 | 4 | from ._types import str_cls, byte_cls, type_name 5 | 6 | 7 | py2 = sys.version_info < (3,) 8 | 9 | # Encoding used for environment variables with ST2 10 | _env_encoding = locale.getpreferredencoding() if sys.platform == 'win32' else 'utf-8' 11 | 12 | # Encoding used for fileystem paths with ST2 13 | _fs_encoding = 'mbcs' if sys.platform == 'win32' else 'utf-8' 14 | 15 | 16 | def env_encode(value): 17 | """ 18 | Ensures a environment variable name or value is encoded properly to be 19 | used with subprocess.Popen() 20 | 21 | :param value: 22 | A unicode string 23 | 24 | :return: 25 | On Python 3, a unicode string, on Python 2, a byte string 26 | """ 27 | 28 | if not isinstance(value, str_cls): 29 | raise TypeError('value must be a unicode string, not %s' % type_name(value)) 30 | 31 | if not py2: 32 | return value 33 | 34 | return value.encode(_env_encoding) 35 | 36 | 37 | def env_decode(value): 38 | """ 39 | Decodes an environment variable name or value that was returned by 40 | get_env(for_subprocess=True) 41 | 42 | :param value: 43 | On Python 3, a unicode string, on Python 2, a byte string 44 | 45 | :return: 46 | A unicode string 47 | """ 48 | 49 | if not py2: 50 | if not isinstance(value, str_cls): 51 | raise TypeError('value must be a unicode string, not %s' % type_name(value)) 52 | 53 | return value 54 | 55 | if not isinstance(value, byte_cls): 56 | raise TypeError('value must be a byte string, not %s' % type_name(value)) 57 | 58 | return value.decode(_env_encoding) 59 | 60 | 61 | def path_encode(value): 62 | """ 63 | Ensures a filesystem path is encoded properly to be used with 64 | subprocess.Popen() 65 | 66 | :param value: 67 | A unicode string 68 | 69 | :return: 70 | On Python 3, a unicode string, on Python 2, a byte string 71 | """ 72 | 73 | if not isinstance(value, str_cls): 74 | raise TypeError('value must be a unicode string, not %s' % type_name(value)) 75 | 76 | if not py2: 77 | return value 78 | 79 | return value.encode(_fs_encoding) 80 | 81 | 82 | def path_decode(value): 83 | """ 84 | Decodes a filesystem path that was returned by get_env(for_subprocess=True) 85 | 86 | :param value: 87 | On Python 3, a unicode string, on Python 2, a byte string 88 | 89 | :return: 90 | A unicode string 91 | """ 92 | 93 | if not py2: 94 | if not isinstance(value, str_cls): 95 | raise TypeError('value must be a unicode string, not %s' % type_name(value)) 96 | 97 | return value 98 | 99 | if not isinstance(value, byte_cls): 100 | raise TypeError('value must be a byte string, not %s' % type_name(value)) 101 | 102 | return value.decode(_fs_encoding) 103 | -------------------------------------------------------------------------------- /dep/shellenv/_osx/core_foundation.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | import ctypes 5 | from ctypes.util import find_library 6 | from ctypes import c_void_p, c_char_p, c_uint32, POINTER, c_long 7 | 8 | 9 | cf_path = find_library('CoreFoundation') 10 | CoreFoundation = ctypes.CDLL(cf_path, use_errno=True) 11 | 12 | 13 | CFIndex = c_long 14 | CFStringEncoding = c_uint32 15 | CFString = c_void_p 16 | CFArray = c_void_p 17 | CFDictionary = c_void_p 18 | CFError = c_void_p 19 | CFType = c_void_p 20 | 21 | CFAllocatorRef = c_void_p 22 | CFStringRef = POINTER(CFString) 23 | CFArrayRef = POINTER(CFArray) 24 | CFDictionaryRef = POINTER(CFDictionary) 25 | CFErrorRef = POINTER(CFError) 26 | CFTypeRef = POINTER(CFType) 27 | 28 | CoreFoundation.CFStringGetCStringPtr.argtypes = [CFStringRef, CFStringEncoding] 29 | CoreFoundation.CFStringGetCStringPtr.restype = c_char_p 30 | 31 | CoreFoundation.CFStringGetCString.argtypes = [CFStringRef, c_char_p, CFIndex, CFStringEncoding] 32 | CoreFoundation.CFStringGetCString.restype = ctypes.c_bool 33 | 34 | CoreFoundation.CFStringCreateWithCString.argtypes = [CFAllocatorRef, c_char_p, CFStringEncoding] 35 | CoreFoundation.CFStringCreateWithCString.restype = CFStringRef 36 | 37 | CoreFoundation.CFArrayGetCount.argtypes = [CFArrayRef] 38 | CoreFoundation.CFArrayGetCount.restype = CFIndex 39 | 40 | CoreFoundation.CFArrayGetValueAtIndex.argtypes = [CFArrayRef, CFIndex] 41 | CoreFoundation.CFArrayGetValueAtIndex.restype = CFTypeRef 42 | 43 | kCFStringEncodingUTF8 = CFStringEncoding(0x08000100) 44 | setattr(CoreFoundation, 'kCFAllocatorDefault', CFAllocatorRef.in_dll(CoreFoundation, 'kCFAllocatorDefault')) 45 | setattr(CoreFoundation, 'CFIndex', CFIndex) 46 | setattr(CoreFoundation, 'CFStringRef', CFStringRef) 47 | setattr(CoreFoundation, 'CFTypeRef', CFTypeRef) 48 | setattr(CoreFoundation, 'CFAllocatorRef', CFAllocatorRef) 49 | setattr(CoreFoundation, 'CFArrayRef', CFArrayRef) 50 | setattr(CoreFoundation, 'CFDictionaryRef', CFDictionaryRef) 51 | setattr(CoreFoundation, 'CFErrorRef', CFErrorRef) 52 | 53 | 54 | def cfstring_to_unicode(value): 55 | """ 56 | Creates a python unicode string from a CoreFoundation CFStringRef 57 | 58 | :param value: 59 | A CFStringRef 60 | 61 | :return: 62 | A unicode string 63 | """ 64 | 65 | string = CoreFoundation.CFStringGetCStringPtr( 66 | ctypes.cast(value, CFStringRef), 67 | kCFStringEncodingUTF8 68 | ) 69 | if string is None: 70 | buf = ctypes.create_string_buffer(1024) 71 | result = CoreFoundation.CFStringGetCString( 72 | ctypes.cast(value, CFStringRef), 73 | buf, 74 | 1024, 75 | kCFStringEncodingUTF8 76 | ) 77 | if not result: 78 | raise OSError('Error copying C string from CFStringRef') 79 | string = buf.value 80 | if string is not None: 81 | string = string.decode('utf-8') 82 | return string 83 | 84 | 85 | def unicode_to_cfstring(value): 86 | """ 87 | Creates a CoreFoundation CFStringRef from a python unicode string 88 | 89 | :param value: 90 | A unicode string 91 | 92 | :return: 93 | A CFStringRef 94 | """ 95 | 96 | return CoreFoundation.CFStringCreateWithCString( 97 | CoreFoundation.kCFAllocatorDefault, 98 | value.encode('utf-8'), 99 | kCFStringEncodingUTF8 100 | ) 101 | -------------------------------------------------------------------------------- /dep/shellenv/_osx/open_directory.py: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | from __future__ import unicode_literals, division, absolute_import, print_function 3 | 4 | from getpass import getuser 5 | import ctypes 6 | from ctypes.util import find_library 7 | from ctypes import c_void_p, c_uint32, POINTER, c_bool, byref 8 | 9 | from .core_foundation import CoreFoundation, unicode_to_cfstring, cfstring_to_unicode 10 | from .._types import str_cls, type_name 11 | 12 | od_path = find_library('OpenDirectory') 13 | OpenDirectory = ctypes.CDLL(od_path, use_errno=True) 14 | 15 | 16 | ODAttributeType = CoreFoundation.CFStringRef 17 | ODMatchType = c_uint32 18 | ODRecordType = CoreFoundation.CFStringRef 19 | 20 | ODSessionRef = c_void_p 21 | ODNodeRef = c_void_p 22 | ODQueryRef = c_void_p 23 | ODRecordRef = c_void_p 24 | 25 | OpenDirectory.ODSessionCreate.argtypes = [ 26 | CoreFoundation.CFAllocatorRef, 27 | CoreFoundation.CFDictionaryRef, 28 | POINTER(CoreFoundation.CFErrorRef) 29 | ] 30 | OpenDirectory.ODSessionCreate.restype = ODSessionRef 31 | 32 | OpenDirectory.ODNodeCreateWithName.argtypes = [ 33 | CoreFoundation.CFAllocatorRef, 34 | ODSessionRef, 35 | CoreFoundation.CFStringRef, 36 | POINTER(CoreFoundation.CFErrorRef) 37 | ] 38 | OpenDirectory.ODNodeCreateWithName.restype = ODNodeRef 39 | 40 | OpenDirectory.ODQueryCreateWithNode.argtypes = [ 41 | CoreFoundation.CFAllocatorRef, 42 | ODNodeRef, 43 | CoreFoundation.CFTypeRef, 44 | ODAttributeType, 45 | ODMatchType, 46 | CoreFoundation.CFTypeRef, 47 | CoreFoundation.CFTypeRef, 48 | CoreFoundation.CFIndex, 49 | POINTER(CoreFoundation.CFErrorRef) 50 | ] 51 | OpenDirectory.ODQueryCreateWithNode.restype = ODQueryRef 52 | 53 | OpenDirectory.ODQueryCopyResults.argtypes = [ 54 | ODQueryRef, 55 | c_bool, 56 | POINTER(CoreFoundation.CFErrorRef) 57 | ] 58 | OpenDirectory.ODQueryCopyResults.restype = CoreFoundation.CFArrayRef 59 | 60 | OpenDirectory.ODRecordCopyValues.argtypes = [ 61 | ODRecordRef, 62 | ODAttributeType, 63 | POINTER(CoreFoundation.CFErrorRef) 64 | ] 65 | OpenDirectory.ODRecordCopyValues.restype = CoreFoundation.CFArrayRef 66 | 67 | kODMatchEqualTo = ODMatchType(0x2001) 68 | 69 | kODRecordTypeUsers = ODRecordType.in_dll(OpenDirectory, 'kODRecordTypeUsers') 70 | kODAttributeTypeRecordName = ODAttributeType.in_dll(OpenDirectory, 'kODAttributeTypeRecordName') 71 | kODAttributeTypeUserShell = ODAttributeType.in_dll(OpenDirectory, 'kODAttributeTypeUserShell') 72 | 73 | 74 | _login_shells = {} 75 | 76 | 77 | def get_user_login_shell(username=None): 78 | """ 79 | Uses OS X's OpenDirectory.framework to get the user's login shell 80 | 81 | :param username: 82 | A unicode string of the user to get the shell for - None for the 83 | current user 84 | 85 | :return: 86 | A unicode string of the user's login shell 87 | """ 88 | 89 | if username is None: 90 | username = getuser() 91 | if not isinstance(username, str_cls): 92 | username = username.decode('utf-8') 93 | 94 | if not isinstance(username, str_cls): 95 | raise TypeError('username must be a unicode string, not %s' % type_name(username)) 96 | 97 | if username not in _login_shells: 98 | 99 | error_ref = CoreFoundation.CFErrorRef() 100 | 101 | session = OpenDirectory.ODSessionCreate( 102 | CoreFoundation.kCFAllocatorDefault, 103 | None, 104 | byref(error_ref) 105 | ) 106 | if bool(error_ref): 107 | raise OSError('Error!') 108 | 109 | node = OpenDirectory.ODNodeCreateWithName( 110 | CoreFoundation.kCFAllocatorDefault, 111 | session, 112 | unicode_to_cfstring("/Local/Default"), 113 | byref(error_ref) 114 | ) 115 | if bool(error_ref): 116 | raise OSError('Error!') 117 | 118 | query = OpenDirectory.ODQueryCreateWithNode( 119 | CoreFoundation.kCFAllocatorDefault, 120 | node, 121 | kODRecordTypeUsers, 122 | kODAttributeTypeRecordName, 123 | kODMatchEqualTo, 124 | unicode_to_cfstring(username), 125 | kODAttributeTypeUserShell, 126 | 1, 127 | byref(error_ref) 128 | ) 129 | if bool(error_ref): 130 | raise OSError('Error!') 131 | 132 | results = OpenDirectory.ODQueryCopyResults( 133 | query, 134 | False, 135 | byref(error_ref) 136 | ) 137 | if bool(error_ref): 138 | raise OSError('Error!') 139 | 140 | login_shell = None 141 | 142 | num_results = CoreFoundation.CFArrayGetCount(results) 143 | if num_results == 1: 144 | od_record = CoreFoundation.CFArrayGetValueAtIndex(results, 0) 145 | attributes = OpenDirectory.ODRecordCopyValues(od_record, kODAttributeTypeUserShell, byref(error_ref)) 146 | if bool(error_ref): 147 | raise OSError('Error!') 148 | num_attributes = CoreFoundation.CFArrayGetCount(results) 149 | if num_attributes == 1: 150 | string_ref = CoreFoundation.CFArrayGetValueAtIndex(attributes, 0) 151 | login_shell = cfstring_to_unicode(string_ref) 152 | 153 | _login_shells[username] = login_shell 154 | 155 | return _login_shells.get(username) 156 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GoRename [![documentation](https://img.shields.io/badge/info-documentation-blue.svg)](http://alvarolm.github.io/GoRename/) 2 | ========= 3 | 4 | GoRename is a Golang plugin for [SublimeText](http://www.sublimetext.com/) 3 that integrates the Go [gorename](https://godoc.org/golang.org/x/tools/cmd/gorename) tool. 5 | 6 | ``` 7 | The gorename command performs precise type-safe renaming of identifiers in Go source code. 8 | ``` 9 | useful for refactoring. 10 | 11 | (based on previus work from [waigani](http://github.com/waigani/GoOracle)) 12 | 13 | Usage 14 | ----- 15 | 16 | 1) Place the cursor over the identifier you want to rename (could be a variable, method, etc.). 17 | 18 | 2) press CTRL+ALT+R, then using the up and down keys select the optional flags to be used with ENTER, once you're done press ESC or click away. 19 | 20 | 3) type the new name and press ENTER. 21 | 22 | 4) review the parameters and press ENTER again to confirm and execute the gorename tool. 23 | 24 | (If by any chance the results panel disappears just press CTRL+SHIFT+ALT+R) 25 | 26 | configurable flags: 27 | ``` 28 | -force causes the renaming to proceed even if conflicts were reported. 29 | The resulting program may be ill-formed, or experience a change 30 | in behaviour. 31 | 32 | WARNING: this flag may even cause the renaming tool to crash. 33 | (In due course this bug will be fixed by moving certain 34 | analyses into the type-checker.) 35 | 36 | -d display diffs instead of rewriting files 37 | 38 | -v enables verbose logging. 39 | ``` 40 | 41 | Install 42 | ------- 43 | 44 | Install Sublime Package Control (if you haven't done so already) from http://wbond.net/sublime_packages/package_control. Be sure to restart ST to complete the installation. 45 | 46 | Bring up the command palette (default ctrl+shift+p or cmd+shift+p) and start typing Package Control: 'Install Package' then press return or click on that option to activate it. You will be presented with a new Quick Panel with the list of available packages. Type 'GoRename' and press return or click on its entry to install GoRename. If there is no entry for 'GoRename', you most likely already have it installed. 47 | 48 | GoOracle has several variables to be set in order to work. These are explained in the comments of the default settings `Preferences > Package Settings > GoOracle > Settings-Default`: 49 | 50 | ```javascript 51 | { 52 | // rename files that had been modified after the 'go_rename' command has been executed. 53 | // (DO NOT set to true unless you want a renaming nightmare) 54 | "gorename_rename_modified_files": false, 55 | 56 | // use golangconfig, if false then shellenv will be used to get golang environment variables 57 | "gorename_use_golangconfig": false, 58 | 59 | // fill variable name text field by default 60 | "gorename_autofill": false, 61 | 62 | // The output can either be one of: 'buffer', 'output_panel' 63 | // Buffers can hold results from more than one invocation 64 | // Output panels sit underneath the editor area and are easily dismissed 65 | "gorename_output": "output_panel", 66 | 67 | // print debug info to the terminal 68 | "gorename_debug": false, 69 | 70 | // env overwrites the default shell environment vars 71 | // e.g "env": { "GOPATH": "$HOME/go/bin:$PATH" } 72 | // not used when gorename_use_golangconfig is set to true 73 | "gorename_env": {}, 74 | } 75 | ``` 76 | You set your own variables in `Preferences > Package Settings > GoRename > Settings-User`. 77 | 78 | You can also make project specific settings. First save your current workspace as a project `Project > Save as project ...`, then edit your project `Project > Edit Project`. Below is an example which sets up GoOracle to be used on the [github.com/juju/juju](https://github.com/juju/juju) codebase: 79 | 80 | ```javascript 81 | { 82 | "folders": 83 | [ 84 | { 85 | "follow_symlinks": true, 86 | "path": "/home/user/go/src/github.com/juju/juju" 87 | } 88 | ], 89 | "settings": 90 | { 91 | "GoRename": { 92 | "gorename_scope": ["github.com/juju/juju/cmd/juju", "github.com/juju/juju/cmd/jujud"], 93 | "output": "output_panel" 94 | } 95 | }, 96 | } 97 | ``` 98 | 99 | Default key binding: 100 | 101 | ```javascript 102 | [ 103 | { "keys": ["ctrl+alt+r"], "command": "go_rename"}, 104 | { "keys": ["ctrl+alt+shift+r"], "command": "go_rename_show_results"}, 105 | 106 | { "keys": ["enter"], "command": "go_rename_confirm", "context": 107 | [{ "key": "selector", "operator": "equal", "operand": "text.gorename-results" }] 108 | } 109 | ] 110 | ``` 111 | 112 | You can set your own key binding by copying the above into `Preferences > Keybindings - User` and replacing ctrl+shift+g with your preferred key(s). 113 | 114 | 115 | Dependencies 116 | ------------ 117 | GoRename relies on the gorename tool. You must install it in order for Gorename to work. Run the following on your command line: 118 | 119 | `go get -u golang.org/x/tools/cmd/gorename` 120 | 121 | 122 | 123 | Copyright, License & Contributors 124 | ================================= 125 | 126 | GoRename is released under the MIT license. See [LICENSE.md](LICENSE.md) 127 | 128 | GoRename is the copyrighted work of *The GoRename Authors* i.e me ([alvarolm](https://github.com/alvarolm/GoRename)) and *all* contributors. If you submit a change, be it documentation or code, so long as it's committed to GoRename's history I consider you a contributor. See [AUTHORS.md](AUTHORS.md) for a list of all the GoRename authors/contributors. 129 | -------------------------------------------------------------------------------- /goRename.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2014 Jesse Meek 2 | # Copyright (c) 2016 Alvaro Leiva 3 | # This program is Free Software see LICENSE file for details. 4 | 5 | """ 6 | GoRename is a Go gorename plugin for Sublime Text 3. 7 | It depends on the gorename tool being installed: 8 | go get -u golang.org/x/tools/cmd/gorename 9 | """ 10 | 11 | # TODO: review & clean 12 | 13 | import sublime, sublime_plugin, subprocess, time, re, os, subprocess, sys, time, hashlib 14 | 15 | DEBUG = False 16 | VERSION = '' 17 | use_golangconfig = False 18 | # holds renaming parameters 19 | renameMe = {} 20 | runningTool = False 21 | 22 | def log(*msg): 23 | print("GoRename:", msg[0:]) 24 | 25 | def debug(*msg): 26 | if DEBUG: 27 | print("GoRename [DEBUG]:", msg[0:]) 28 | 29 | def error(*msg): 30 | print("GoRename [ERROR]:", msg[0:]) 31 | 32 | def plugin_loaded(): 33 | global DEBUG 34 | global VERSION 35 | global use_golangconfig 36 | 37 | DEBUG = get_setting("gorename_debug", False) 38 | use_golangconfig = get_setting("gorename_use_golangconfig", False) 39 | 40 | # load shellenv 41 | def load_shellenv(): 42 | global shellenv 43 | from .dep import shellenv 44 | 45 | # try golangconfig 46 | if use_golangconfig: 47 | try: 48 | global golangconfig 49 | import golangconfig 50 | except: 51 | error("couldn't import golangconfig:", sys.exc_info()[0]) 52 | log("using shellenv instead of golangconfig") 53 | use_golangconfig = False 54 | load_shellenv() 55 | 56 | else: 57 | load_shellenv() 58 | 59 | log("debug:", DEBUG) 60 | log("use_golangconfig", use_golangconfig) 61 | 62 | # keep track of the version if possible (pretty nasty workaround, any other ideas ?) 63 | try: 64 | PluginPath = os.path.dirname(os.path.realpath(__file__)) 65 | p = subprocess.Popen(["git", "describe", "master", "--tags"], stdout=subprocess.PIPE, cwd=PluginPath) 66 | GITVERSION = p.communicate()[0].decode("utf-8").rstrip() 67 | if p.returncode != 0: 68 | debug("git return code", p.returncode) 69 | raise Exception("git return code", p.returncode) 70 | 71 | 72 | defsettings = os.path.join(PluginPath, 'Default.sublime-settings') 73 | f = open(defsettings,'r') 74 | filedata = f.read() 75 | f.close() 76 | newdata = filedata.replace(get_setting('gorename_version'), GITVERSION+'_') 77 | f = open(defsettings,'w') 78 | f.write(newdata) 79 | f.close() 80 | except: 81 | debug("couldn't get git tag:", sys.exc_info()[0]) 82 | 83 | # read version 84 | VERSION = sublime.load_settings('Default.sublime-settings').get('gorename_version') 85 | log("version:", VERSION) 86 | 87 | # check if user setting exists and creates it 88 | us = sublime.load_settings("GoRename.sublime-settings") 89 | if (not us.has('gorename_debug')): 90 | us.set('gorename_debug', DEBUG) 91 | sublime.save_settings("GoRename.sublime-settings") 92 | 93 | class GoRenameCommand(sublime_plugin.TextCommand): 94 | def __init__(self, view): 95 | self.view = view 96 | # ... 97 | def run(self, edit, simulate=False, force=False, verbose=False): 98 | 99 | try: 100 | current_selection = self.view.sel() 101 | region = current_selection[0] 102 | text = self.view.substr(sublime.Region(0, region.end())) 103 | cb_map = self.get_map(text) 104 | byte_end = cb_map[sorted(cb_map.keys())[-1]] 105 | byte_begin = None 106 | 107 | if not region.empty(): 108 | byte_begin = cb_map[region.begin()-1] 109 | else: 110 | byte_begin = byte_end 111 | except: 112 | sublime.error_message('GoRename:\nCouldn\'t get cursor positon, make sure that the Go source file is saved and the cursor is over the identifier (variable, function ...) you want to query.') 113 | error("couldn't cursor position: ", sys.exc_info()[0]) 114 | 115 | word = self.view.substr(self.view.word(region.begin())).rstrip() 116 | position = self.view.rowcol(region.begin()) 117 | line_number = position[0]+1 118 | del position 119 | line_string = self.view.substr(self.view.line(region)) 120 | 121 | 122 | 123 | # TODO: improve preliminary identifier validation 124 | if len(word) == 0: 125 | self.view.show_popup('Gorename:
Invalid identifier:\nno identifier here.') 126 | return 127 | 128 | message = 'Running GoRename %s:\nFrom %s to %s\n[Line Number: %s][Byte Offset: %s]\nFlags: %s\nReference:\n%s' 129 | 130 | global s, f, v, flags 131 | s = simulate 132 | f = force 133 | v = verbose 134 | flags = '' 135 | 136 | def compile_flags(only_enabled=False): # and construct flags argument 137 | compiled_flags_array = [] 138 | enabledTitle = 'ENABLED: ' 139 | if only_enabled: 140 | enabledTitle = '' 141 | global flags 142 | 143 | # reset 144 | flags = '' 145 | 146 | if s: 147 | compiled_flags_array.append(enabledTitle+'Simulate (-d)') 148 | flags = '-d ' 149 | elif not only_enabled: 150 | compiled_flags_array.append('DISABLED: Simulate (-d)') 151 | 152 | if f: 153 | compiled_flags_array.append(enabledTitle+'force (-force)') 154 | flags = flags + '-force ' 155 | elif not only_enabled: 156 | compiled_flags_array.append('DISABLED: force (-force)') 157 | 158 | if v: 159 | compiled_flags_array.append(enabledTitle+'verbose (-v)') 160 | flags = flags + '-v' 161 | elif not only_enabled: 162 | compiled_flags_array.append('DISABLED: verbose (-v)') 163 | return compiled_flags_array 164 | 165 | def rename_name_input(name): 166 | debug('flags:', flags) 167 | 168 | global renameMe 169 | renameMe['compiled_message'] = message % ('%s', 170 | word.replace('%', '%%'), 171 | name.replace('%', '%%'), 172 | line_number, 173 | byte_begin, 174 | str(compile_flags(True)).replace('%', '%%'), 175 | line_string.replace('%', '%%'), 176 | ) 177 | self.write_running(renameMe['compiled_message'] % ('[press ENTER to continue]'), True, True) 178 | renameMe['offset'] = byte_begin 179 | renameMe['name'] = name 180 | renameMe['flags'] = flags 181 | renameMe['file_path'] = self.view.file_name() 182 | renameMe['checksum'] = hashlib.sha256(open(renameMe['file_path'],'rb').read()).hexdigest() 183 | 184 | def popup_menu_callback(flag_opt): 185 | global s,f,v 186 | if flag_opt == 0: 187 | s = not s 188 | elif flag_opt == 1: 189 | f = not f 190 | elif flag_opt == 2: 191 | v = not v 192 | if flag_opt != -1: 193 | pop_menu() 194 | else: 195 | varName = '' 196 | if get_setting("gorename_autofill", False): 197 | varName = word 198 | self.view.window().show_input_panel('GoRename: rename "%s" (from line %s) to' % (word, line_number), varName, rename_name_input, on_change=None, on_cancel=None) 199 | 200 | def pop_menu(): 201 | self.view.show_popup_menu(compile_flags(), popup_menu_callback) 202 | 203 | pop_menu() 204 | 205 | 206 | 207 | def gorename_complete(self, out, err, focus=False): 208 | self.write_out(out, err) 209 | 210 | def write_running(self, content, readonly=False, focus=False): 211 | """ Write the "Running..." header to a new file and focus it to get results 212 | """ 213 | 214 | #window = self.view.window() 215 | window = sublime.active_window() 216 | view = get_output_view(window) 217 | view.set_read_only(False) 218 | 219 | # Run a new command to use the edit object for this view. 220 | view.run_command('go_rename_write_running', {'content': content}) 221 | 222 | if get_setting("gorename_output", "buffer") == "output_panel": 223 | window.run_command('show_panel', {'panel': "output." + view.name() }) 224 | else: 225 | window.focus_view(view) 226 | 227 | view.set_read_only(readonly) 228 | 229 | # focus no matter what 230 | if focus: 231 | window.focus_view(view) 232 | 233 | def write_out(self, result, err): 234 | 235 | """ Write the gorename output to a new file. 236 | """ 237 | 238 | #window = self.view.window() 239 | window = sublime.active_window() 240 | view = get_output_view(window) 241 | 242 | # Run a new command to use the edit object for this view. 243 | view.run_command('go_rename_write_results', { 244 | 'result': result, 245 | 'err': err}) 246 | 247 | if get_setting("gorename_output", "buffer") == "output_panel": 248 | window.run_command('show_panel', {'panel': "output." + view.name() }) 249 | else: 250 | window.focus_view(view) 251 | 252 | def get_map(self, chars): 253 | """ Generate a map of character offset to byte offset for the given string 'chars'. 254 | """ 255 | 256 | byte_offset = 0 257 | cb_map = {} 258 | 259 | for char_offset, char in enumerate(chars): 260 | cb_map[char_offset] = byte_offset 261 | byte_offset += len(char.encode('utf-8')) 262 | if char == '\n' and self.view.line_endings() == "Windows": 263 | byte_offset += 1 264 | return cb_map 265 | 266 | def gorename(self, file_path, begin_offset=None, flags=None, name=None, callback=None): 267 | """ Builds the gorename shell command and calls it, returning it's output as a string. 268 | """ 269 | 270 | global runningTool 271 | runningTool = True 272 | 273 | pos = "#" + str(begin_offset) 274 | 275 | # golangconfig or shellenv ? 276 | cmd_env = '' 277 | if use_golangconfig: 278 | try: 279 | toolpath, cmd_env = golangconfig.subprocess_info('gorename', ['GOPATH', 'PATH'], view=self.view) 280 | toolpath = os.path.realpath(toolpath) 281 | except: 282 | error("golangconfig:", sys.exc_info()) 283 | return 284 | else: 285 | toolpath = 'gorename' 286 | cmd_env = shellenv.get_env(for_subprocess=True)[1] 287 | cmd_env.update(get_setting("gorename_env", {})) 288 | 289 | debug("env", cmd_env) 290 | 291 | gorename_json = "" 292 | if get_setting("gorename_json", False): 293 | gorename_json = "-json" 294 | 295 | # Build gorename cmd. 296 | cmd = "%(toolpath)s -offset \"%(file_path)s:%(pos)s\" -to %(name)s %(flags)s" % { 297 | "toolpath": toolpath, 298 | "file_path": os.path.realpath(file_path), 299 | "pos": pos, 300 | "name": name, 301 | "flags": flags} 302 | 303 | debug("cmd", cmd) 304 | 305 | sublime.set_timeout_async(lambda: self.runInThread(cmd, callback, cmd_env), 0) 306 | 307 | def runInThread(self, cmd, callback, env): 308 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, shell=True, env=env) 309 | out, err = proc.communicate() 310 | callback(out.decode('utf-8'), err.decode('utf-8')) 311 | global runningTool 312 | runningTool = False 313 | 314 | class GoRenameConfirmCommand(sublime_plugin.TextCommand): 315 | """ Writes the gorename output to the current view. 316 | """ 317 | 318 | def run(self, edit): 319 | global renameMe 320 | #view = self.view 321 | debug('Stored rename parameters:', renameMe) 322 | # check that the referenced file hasn't changed 323 | 324 | if (len(renameMe)==0): 325 | sublime.error_message("Invalid GoRename parameters") 326 | if (runningTool == False): 327 | if ((hashlib.sha256(open(renameMe['file_path'],'rb').read()).hexdigest() != renameMe['checksum']) and (get_setting('gorename_rename_modified_files', False) == False)): 328 | sublime.error_message("Couldn't execute gorename, the referenced file has changed, please start over.") 329 | # reset renameMe 330 | renameMe = {} 331 | else: 332 | GR = GoRenameCommand(self) 333 | GR.write_running(renameMe['compiled_message'] % ('[Running...]'), True, True) 334 | GR.gorename(file_path=renameMe['file_path'] ,begin_offset=renameMe['offset'], name=renameMe['name'], flags=renameMe['flags'], callback=GR.gorename_complete) 335 | # reset renameMe 336 | renameMe = {} 337 | else: 338 | sublime.message_dialog("GoRename tool already executing") 339 | 340 | 341 | 342 | class GoRenameWriteResultsCommand(sublime_plugin.TextCommand): 343 | """ Writes the gorename output to the current view. 344 | """ 345 | 346 | def run(self, edit, result, err): 347 | view = self.view 348 | 349 | view.set_read_only(False) 350 | 351 | if result: 352 | view.insert(edit, view.size(), result) 353 | if err: 354 | errLen = view.insert(edit, view.size(), err) 355 | 356 | view.set_read_only(True) 357 | 358 | # reset 359 | global renameMe 360 | renameMe = {} 361 | 362 | 363 | class GoRenameWriteRunningCommand(sublime_plugin.TextCommand): 364 | """ Writes the gorename output to the current view. 365 | """ 366 | 367 | def run(self, edit, content): 368 | view = self.view 369 | 370 | view.set_viewport_position(view.text_to_layout(view.size() - 1)) 371 | view.insert(edit, view.size(), content) 372 | 373 | 374 | class GoRenameShowResultsCommand(sublime_plugin.TextCommand): 375 | def run(self, edit): 376 | if get_setting("gorename_output", "buffer") == "output_panel": 377 | self.view.window().run_command('show_panel', {'panel': "output.GoRename Output" }) 378 | else: 379 | output_view = get_output_view(self.view.window()) 380 | self.view.window().focus_view(output_view) 381 | 382 | 383 | class GoRenameOpenResultCommand(sublime_plugin.EventListener): 384 | 385 | ''' 386 | def on_modification(self, view): 387 | if view.name() == "GoRename Output": 388 | log("on modif") 389 | ''' 390 | 391 | def on_selection_modified(self, view): 392 | if view.name() == "GoRename Output": 393 | if len(view.sel()) != 1: 394 | return 395 | if view.sel()[0].size() == 0: 396 | return 397 | 398 | lines = view.lines(view.sel()[0]) 399 | if len(lines) != 1: 400 | return 401 | 402 | line = view.full_line(lines[0]) 403 | text = view.substr(line) 404 | 405 | format = get_setting("gorename_format") 406 | 407 | # "filename:line:col" pattern for json 408 | m = re.search("\"([^\"]+):([0-9]+):([0-9]+)\"", text) 409 | 410 | # >filename:line:col< pattern for xml 411 | if m == None: 412 | m = re.search(">([^<]+):([0-9]+):([0-9]+)<", text) 413 | 414 | # filename:line.col-line.col: pattern for plain 415 | if m == None: 416 | m = re.search("^([^:]+):([0-9]+).([0-9]+)[-: ]", text) 417 | 418 | if m: 419 | w = view.window() 420 | new_view = w.open_file(m.group(1) + ':' + m.group(2) + ':' + m.group(3), sublime.ENCODED_POSITION) 421 | group, index = w.get_view_index(new_view) 422 | if group != -1: 423 | w.focus_group(group) 424 | 425 | 426 | def get_output_view(window): 427 | view = None 428 | buff_name = 'GoRename Output' 429 | 430 | if get_setting("gorename_output", "buffer") == "output_panel": 431 | view = window.create_output_panel(buff_name) 432 | else: 433 | # If the output file is already open, use that. 434 | for v in window.views(): 435 | if v.name() == buff_name: 436 | view = v 437 | break 438 | # Otherwise, create a new one. 439 | if view is None: 440 | view = window.new_file() 441 | 442 | view.set_name(buff_name) 443 | view.set_scratch(True) 444 | view_settings = view.settings() 445 | view_settings.set('line_numbers', False) 446 | view.set_syntax_file('Packages/GoRename/GoRenameResults.tmLanguage') 447 | 448 | return view 449 | 450 | def get_setting(key, default=None): 451 | """ Returns the setting in the following hierarchy: project setting, user setting, 452 | default setting. If none are set the 'default' value passed in is returned. 453 | """ 454 | 455 | val = None 456 | try: 457 | val = sublime.active_window().active_view().settings().get('GoRename', {}).get(key) 458 | except AttributeError: 459 | pass 460 | 461 | if not val: 462 | val = sublime.load_settings("GoRename.sublime-settings").get(key) 463 | if not val: 464 | val = sublime.load_settings("Default.sublime-settings").get(key) 465 | if not val: 466 | val = default 467 | return val --------------------------------------------------------------------------------