├── GitStatusBar.sublime-settings ├── LICENSE.txt ├── Main.sublime-menu ├── README.md ├── git_status_bar.py └── screenshot.png /GitStatusBar.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | // "git": "/usr/bin/git", 3 | "prefix": "" 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Randy Lai 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Preferences", 4 | "mnemonic": "n", 5 | "id": "preferences", 6 | "children": 7 | [ 8 | { 9 | "caption": "Package Settings", 10 | "mnemonic": "P", 11 | "id": "package-settings", 12 | "children": 13 | [ 14 | { 15 | "caption": "GitStatusBar", 16 | "children": 17 | [ 18 | { 19 | "command": "open_file", "args": 20 | { 21 | "file": "${packages}/GitStatusBar/GitStatusBar.sublime-settings" 22 | }, 23 | "caption": "Settings – Default" 24 | }, 25 | { 26 | "command": "open_file", "args": 27 | { 28 | "file": "${packages}/User/GitStatusBar.sublime-settings" 29 | }, 30 | "caption": "Settings – User" 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | 39 | 40 | ] 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Git-StatusBar: A more compact Git StatusBar 2 | ==== 3 | 4 | [sublime-text-git](https://github.com/kemayo/sublime-text-git) does an amazing job in integrating `git` commands into Sublime Text. However, it is showing too much text in the status bar. This plugin minimizes the amount of text by only showing important information. Less is more! 5 | 6 | ### Screenshot 7 | 8 | ![](https://raw.githubusercontent.com/randy3k/Git-StatusBar/master/screenshot.png) 9 | 10 | ### Explain the badge 11 | 12 | | symbol | | 13 | | ---- | ---- | 14 | | * | the current branch is dirty | 15 | | +n | the current branch is n commits ahead the remote branch | 16 | | -n | the current branch is n commits behind the remote branch | 17 | 18 | ### Note 19 | The `sublime-text-git` status bar will be disabled automatically by this plugin. -------------------------------------------------------------------------------- /git_status_bar.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | import subprocess 4 | import os 5 | import re 6 | 7 | 8 | def plugin_loaded(): 9 | s = sublime.load_settings("Git.sublime-settings") 10 | if s.get("statusbar_branch"): 11 | s.set("statusbar_branch", False) 12 | sublime.save_settings("Git.sublime-settings") 13 | if s.get("statusbar_status"): 14 | s.set("statusbar_status", False) 15 | sublime.save_settings("Git.sublime-settings") 16 | ofile = os.path.join(sublime.packages_path(), "User", "Git-StatusBar.sublime-settings") 17 | nfile = os.path.join(sublime.packages_path(), "User", "GitStatusBar.sublime-settings") 18 | if os.path.exists(ofile): 19 | os.rename(ofile, nfile) 20 | 21 | 22 | def plugin_unloaded(): 23 | """reset sublime-text-git status bar""" 24 | s = sublime.load_settings("Git.sublime-settings") 25 | if s.get("statusbar_branch") is False: 26 | s.set("statusbar_branch", True) 27 | sublime.save_settings("Git.sublime-settings") 28 | if s.get("statusbar_status") is False: 29 | s.set("statusbar_status", True) 30 | sublime.save_settings("Git.sublime-settings") 31 | 32 | 33 | class GitManager: 34 | def __init__(self, view): 35 | self.view = view 36 | s = sublime.load_settings("GitStatusBar.sublime-settings") 37 | self.git = s.get("git", "git") 38 | self.prefix = s.get("prefix", "") 39 | 40 | def run_git(self, cmd, cwd=None): 41 | plat = sublime.platform() 42 | if not cwd: 43 | cwd = self.getcwd() 44 | if cwd: 45 | if type(cmd) == str: 46 | cmd = [cmd] 47 | cmd = [self.git] + cmd 48 | if plat == "windows": 49 | # make sure console does not come up 50 | startupinfo = subprocess.STARTUPINFO() 51 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 52 | p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, 53 | cwd=cwd, startupinfo=startupinfo) 54 | else: 55 | my_env = os.environ.copy() 56 | my_env["PATH"] = "/usr/local/bin:/usr/bin:" + my_env["PATH"] 57 | p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, 58 | cwd=cwd, env=my_env) 59 | p.wait() 60 | stdoutdata, _ = p.communicate() 61 | return stdoutdata.decode('utf-8') 62 | 63 | def getcwd(self): 64 | f = self.view.file_name() 65 | cwd = None 66 | if f: 67 | cwd = os.path.dirname(f) 68 | if not cwd: 69 | window = self.view.window() 70 | if window: 71 | pd = window.project_data() 72 | if pd: 73 | cwd = pd.get("folders")[0].get("path") 74 | return cwd 75 | 76 | def branch(self): 77 | ret = self.run_git(["symbolic-ref", "HEAD", "--short"]) 78 | if ret: 79 | ret = ret.strip() 80 | else: 81 | output = self.run_git("branch") 82 | if output: 83 | m = re.search(r"\* *\(detached from (.*?)\)", output, flags=re.MULTILINE) 84 | if m: 85 | ret = m.group(1) 86 | return ret 87 | 88 | def is_dirty(self): 89 | output = self.run_git("status") 90 | if not output: 91 | return False 92 | ret = re.search(r"working (tree|directory) clean", output) 93 | if ret: 94 | return False 95 | else: 96 | return True 97 | 98 | def unpushed_info(self): 99 | branch = self.branch() 100 | a, b = 0, 0 101 | if branch: 102 | output = self.run_git(["branch", "-v"]) 103 | if output: 104 | m = re.search(r"\* .*?\[behind ([0-9])+\]", output, flags=re.MULTILINE) 105 | if m: 106 | a = int(m.group(1)) 107 | m = re.search(r"\* .*?\[ahead ([0-9])+\]", output, flags=re.MULTILINE) 108 | if m: 109 | b = int(m.group(1)) 110 | return (a, b) 111 | 112 | def badge(self): 113 | branch = self.branch() 114 | if not branch: 115 | return "" 116 | ret = branch 117 | if self.is_dirty(): 118 | ret = ret + "*" 119 | a, b = self.unpushed_info() 120 | if a: 121 | ret = ret + "-%d" % a 122 | if b: 123 | ret = ret + "+%d" % b 124 | return self.prefix + ret 125 | 126 | 127 | class GitStatusBarHandler(sublime_plugin.EventListener): 128 | def update_status_bar(self, view): 129 | sublime.set_timeout_async(lambda: self._update_status_bar(view)) 130 | 131 | def _update_status_bar(self, view): 132 | if not view or view.is_scratch() or view.settings().get('is_widget'): 133 | return 134 | gm = GitManager(view) 135 | badge = gm.badge() 136 | if badge: 137 | view.set_status("git-statusbar", badge) 138 | else: 139 | view.erase_status("git-statusbar") 140 | 141 | def on_new(self, view): 142 | self.update_status_bar(view) 143 | 144 | def on_load(self, view): 145 | self.update_status_bar(view) 146 | 147 | def on_activated(self, view): 148 | self.update_status_bar(view) 149 | 150 | def on_deactivated(self, view): 151 | self.update_status_bar(view) 152 | 153 | def on_post_save(self, view): 154 | self.update_status_bar(view) 155 | 156 | def on_pre_close(self, view): 157 | self.update_status_bar(view) 158 | 159 | def on_window_command(self, window, command_name, args): 160 | if command_name == "hide_panel": 161 | self.update_status_bar(window.active_view()) 162 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/randy3k/GitStatusBar/d9371af69942d85273443b463fcbab71de5b1c57/screenshot.png --------------------------------------------------------------------------------