├── .gitignore ├── MIT-License ├── Main.sublime-commands ├── Main.sublime-menu ├── README.md ├── auto_save.py ├── auto_save.sublime-settings ├── demo.gif ├── messages.json ├── messages ├── 1.0.1.txt ├── 1.0.2.txt ├── 1.0.3.txt ├── 1.0.4.txt ├── 1.0.5.txt ├── 1.0.6.txt ├── 1.0.7.txt ├── 1.0.8.txt └── install.txt └── repository.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /MIT-License: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 James Zhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Main.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { "caption": "Toggle AutoSave: all files", "command": "auto_save" }, 3 | { "caption": "Toggle AutoSave: current file only", "command": "auto_save", "args": {"all_files": false} }, 4 | { "caption": "Toggle AutoSave Backup: current file only", "command": "auto_save", "args": {"all_files": false, "backup": true} } 5 | ] 6 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "preferences", 4 | "children": 5 | [ 6 | { 7 | "caption": "Package Settings", 8 | "mnemonic": "P", 9 | "id": "package-settings", 10 | "children": 11 | [ 12 | { 13 | "caption": "Auto-save", 14 | "children": 15 | [ 16 | { 17 | "command": "open_file", 18 | "args": {"file": "${packages}/auto-save/README.md"}, 19 | "caption": "README" 20 | }, 21 | { "caption": "-" }, 22 | { 23 | "command": "open_file", 24 | "args": {"file": "${packages}/auto-save/auto_save.sublime-settings"}, 25 | "caption": "Settings – Default" 26 | }, 27 | { 28 | "command": "open_file", 29 | "args": {"file": "${packages}/User/auto_save.sublime-settings"}, 30 | "caption": "Settings – User" 31 | }, 32 | { "caption": "-" }, 33 | { 34 | "command": "open_file", 35 | "args": {"file": "${packages}/auto-save/Default (${platform}).sublime-keymap"}, 36 | "caption": "Key Bindings – Default" 37 | }, 38 | { 39 | "command": "open_file", 40 | "args": {"file": "${packages}/User/Default (${platform}).sublime-keymap"}, 41 | "caption": "Key Bindings – User" 42 | } 43 | ] 44 | } 45 | ] 46 | } 47 | ] 48 | } 49 | ] 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | auto-save 2 | =============== 3 | A [Sublime Text](http://www.sublimetext.com/) plugin that **automatically saves the current file after every modification**. 4 | 5 | - [Synopsis](#synopsis) 6 | - [Demo](#demo) 7 | - [Installation](#installation) 8 | - [Usage](#usage) 9 | - [License](#license) 10 | - [Author](#author) 11 | 12 | Synopsis 13 | ------- 14 | In the occasion where you'd want Sublime Text to save the current file after 15 | each change, you can use this plugin. 16 | 17 | Demo 18 | ------- 19 | ![Image](https://github.com/jamesfzhang/auto-save/blob/master/demo.gif?raw=true) 20 | 21 | Installation 22 | ------- 23 | #### From Package Control 24 | auto-save is available through [Sublime Package Control](https://sublime.wbond.net/packages/auto-save) 25 | and is the recommended way to install. 26 | 27 | #### From Github 28 | Alternatively, you may install via GitHub by cloning this repository into the `Packages` 29 | directory under Sublime Text's data directory: 30 | 31 | On Mac: 32 | 33 | ``` 34 | cd ~/Library/Application Support/Sublime Text 3/Packages 35 | git clone https://github.com/jamesfzhang/auto-save.git 36 | ``` 37 | 38 | Usage 39 | ------- 40 | **By default, auto-save is disabled** because it is a fairly invasive plugin. To make it less invasive, you can instruct it to only auto-save changes to the file that is active when you turn on auto-save. In this mode, it will ignore changes to all other files. 41 | 42 | To run auto-save whenever a file is modified, set `"auto_save_on_modified": true` in your user settings. To ignore certain files, set `auto_save_ignore_files` to a list of file suffices like `[".yml", "package.json"]`. 43 | 44 | You can also instruct it to auto-backup the file instead of auto-saving it. The backup gets created in the same directory as its source file. The backup file takes the same name as its source file, with the string `.autosave` inserted directly before the file extension. When auto-save is disabled, the backup file is deleted. 45 | 46 | There are two ways to enable it. You can press Command + Shift + P to bring up the Command Palette, and search for **AutoSave**. Here, there are 3 options: 47 | 48 | - Toggle AutoSave: all files 49 | - Toggle AutoSave: current file only 50 | - Toggle AutoSave Backup: current file only 51 | 52 | Alternatively, you can bind commands to turn the plugin on or off. For example, to toggle auto-save for all files, open "Preferences / Key Bindings - User" and add: 53 | 54 | ```js 55 | { "keys": ["ctrl+shift+s"], "command": "auto_save" } 56 | ``` 57 | 58 | To toggle it for only the current file, and instruct to make a backup of the file instead of saving the file itself, you could add: 59 | 60 | ```js 61 | { "keys": ["ctrl+shift+s"], "command": "auto_save", "args": {"all_files": false, "backup": true} } 62 | ``` 63 | 64 | This key bindings file takes an array of key bindings so please ensure that this key binding, along with any existing ones, are properly wrapped in `[]`. 65 | 66 | With this setting, pressing Ctrl + Shift + S will turn the plugin 67 | on or off. A status message will be displayed in the Sublime Status Bar each 68 | time the plugin is turned on or off. 69 | 70 | By default, auto-save debounces "save" events by 1 second. For fast typers, this improves 71 | performance dramatically such that "save" events are not called constantly, just when it matters. 72 | 73 | License 74 | ------- 75 | [MIT-License](https://raw.github.com/jamesfzhang/auto-save/master/MIT-License). 76 | 77 | Author 78 | ------- 79 | auto-save was created and maintained by James Zhang. Give him a shoutout at [@jamesfzhang](https://twitter.com/jamesfzhang) 80 | if you have comments or questions. 81 | -------------------------------------------------------------------------------- /auto_save.py: -------------------------------------------------------------------------------- 1 | ''' 2 | AutoSave - Sublime Text Plugin 3 | 4 | Provides a convenient way to turn on and turn off 5 | automatically saving the current file after every modification. 6 | ''' 7 | 8 | import os 9 | import sublime 10 | import sublime_plugin 11 | from threading import Timer 12 | 13 | 14 | settings_filename = "auto_save.sublime-settings" 15 | 16 | on_modified_field = "auto_save_on_modified" 17 | delay_field = "auto_save_delay_in_seconds" 18 | all_files_field = "auto_save_all_files" 19 | current_file_field = "auto_save_current_file" 20 | ignore_files_field = "auto_save_ignore_files" 21 | backup_field = "auto_save_backup" 22 | backup_suffix_field = "auto_save_backup_suffix" 23 | 24 | 25 | class AutoSaveListener(sublime_plugin.EventListener): 26 | 27 | save_queue = [] # Save queue for on_modified events. 28 | 29 | @staticmethod 30 | def generate_backup_filename(filename, backup_suffix): 31 | dirname, basename = [os.path.dirname(filename), 32 | os.path.basename(filename).split('.')] 33 | if len(basename) > 1: 34 | basename.insert(-1, backup_suffix) 35 | else: 36 | basename.append(backup_suffix) 37 | return dirname + '/' + '.'.join(basename) 38 | 39 | 40 | def on_modified(self, view): 41 | settings = sublime.load_settings(settings_filename) 42 | filename = view.file_name() 43 | 44 | if view.is_auto_complete_visible(): 45 | return 46 | 47 | if not (settings.get(on_modified_field) and filename and view.is_dirty()): 48 | return 49 | 50 | for path in settings.get(ignore_files_field): 51 | if filename.endswith(path): 52 | return 53 | 54 | if not settings.get(all_files_field) and settings.get(current_file_field) != filename: 55 | return 56 | 57 | 58 | def callback(): 59 | ''' 60 | Must use this callback for ST2 compatibility 61 | ''' 62 | if view.is_dirty() and not view.is_loading() and not view.is_auto_complete_visible(): 63 | if not settings.get(backup_field): # Save file 64 | view.run_command("save") 65 | else: # Save backup file 66 | content = view.substr(sublime.Region(0, view.size())) 67 | try: 68 | with open(AutoSaveListener.generate_backup_filename( 69 | view.file_name(), settings.get(backup_suffix_field)), 'w', encoding='utf-8') as f: 70 | f.write(content) 71 | except Exception as e: 72 | sublime.status_message(e) 73 | raise e 74 | 75 | 76 | def debounce_save(): 77 | ''' 78 | If the queue is longer than 1, pop the last item off, 79 | Otherwise save and reset the queue. 80 | ''' 81 | if len(AutoSaveListener.save_queue) > 1: 82 | AutoSaveListener.save_queue.pop() 83 | else: 84 | sublime.set_timeout(callback, 0) 85 | AutoSaveListener.save_queue = [] 86 | 87 | 88 | AutoSaveListener.save_queue.append(0) # Append to queue for every on_modified event. 89 | Timer(settings.get(delay_field), debounce_save).start() # Debounce save by the specified delay. 90 | 91 | 92 | 93 | 94 | class AutoSaveCommand(sublime_plugin.ApplicationCommand): 95 | 96 | def run(self, **kwargs): 97 | ''' 98 | Toggle auto-save on and off. Can be bound to a keystroke, e.g. ctrl+alt+s. 99 | If enable argument is given, auto save will be enabled (if True) or disabled (if False). 100 | If enable is not provided, auto save will be toggled (on if currently off and vice versa). 101 | ''' 102 | enable = kwargs.get('enable', None) 103 | all_files = kwargs.get('all_files', True) 104 | backup = kwargs.get('backup', False) 105 | 106 | settings = sublime.load_settings(settings_filename) 107 | if enable is None: # toggle 108 | enable = not settings.get(on_modified_field) 109 | 110 | if not enable: 111 | message = "AutoSave Turned Off" 112 | filename = settings.get(current_file_field) 113 | if settings.get(backup_field) and filename: # Delete backup file 114 | try: 115 | os.remove(AutoSaveListener.generate_backup_filename( 116 | filename, settings.get(backup_suffix_field))) 117 | except: 118 | pass 119 | 120 | settings.set(on_modified_field, enable) 121 | settings.set(all_files_field, all_files) 122 | filename = sublime.Window.active_view(sublime.active_window()).file_name() 123 | settings.set(current_file_field, filename) 124 | settings.set(backup_field, backup) 125 | 126 | if enable: 127 | message = "AutoSave %sTurned On" % ("Backup " if backup else "") 128 | if not all_files: 129 | message += " for: " + os.path.basename(filename) 130 | sublime.status_message(message) 131 | -------------------------------------------------------------------------------- /auto_save.sublime-settings: -------------------------------------------------------------------------------- 1 | // AutoSave's default settings. 2 | 3 | { 4 | "auto_save_on_modified": false, 5 | "auto_save_delay_in_seconds": 1, 6 | "auto_save_all_files": true, 7 | "auto_save_current_file": "", 8 | "auto_save_ignore_files": [], 9 | "auto_save_backup": false, 10 | "auto_save_backup_suffix": "autosave" 11 | } 12 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jamesfzhang/auto-save/c1b0651d116561bef6a3462bb9d5b01041eff84b/demo.gif -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "messages/install.txt", 3 | "1.0.1": "messages/1.0.1.txt", 4 | "1.0.2": "messages/1.0.2.txt", 5 | "1.0.3": "messages/1.0.3.txt", 6 | "1.0.4": "messages/1.0.4.txt", 7 | "1.0.5": "messages/1.0.5.txt", 8 | "1.0.6": "messages/1.0.6.txt", 9 | "1.0.7": "messages/1.0.7.txt", 10 | "1.0.8": "messages/1.0.8.txt" 11 | } 12 | -------------------------------------------------------------------------------- /messages/1.0.1.txt: -------------------------------------------------------------------------------- 1 | Fixes: 2 | 3 | * Don't try to save files that don't exist yet. Thanks to https://github.com/jisaacks 4 | 5 | -------------------------------------------------------------------------------- /messages/1.0.2.txt: -------------------------------------------------------------------------------- 1 | Improvements: 2 | 3 | * Debounce save to improve performance dramatically. 4 | - New setting called "auto_save_delay_in_seconds", which defaults to 1. 5 | - The higher this number, the longer "save" is debounced. 6 | - Anywhere between 1-3 seconds is reasonable. 7 | - Set to 0 to avoid debouncing all together (not recommended). 8 | -------------------------------------------------------------------------------- /messages/1.0.3.txt: -------------------------------------------------------------------------------- 1 | Fixes: 2 | 3 | * Fixed bug where turning on/off resulted in plugin breaking. 4 | * Thanks for reporting the issue, https://github.com/fertingoff 5 | -------------------------------------------------------------------------------- /messages/1.0.4.txt: -------------------------------------------------------------------------------- 1 | Fixes: 2 | 3 | * Fixed bug where plugin was broken for ST2. 4 | * Thanks for reporting the issue and fixing it https://github.com/mateuszjarzewski 5 | -------------------------------------------------------------------------------- /messages/1.0.5.txt: -------------------------------------------------------------------------------- 1 | Fixes: 2 | 3 | * Fixed bug when file is reloaded from disk (thanks https://github.com/scholer) 4 | -------------------------------------------------------------------------------- /messages/1.0.6.txt: -------------------------------------------------------------------------------- 1 | Improvements: 2 | 3 | * Add explicit enable/disable flag in addition to toggle (thanks https://github.com/scholer) 4 | * Add preferences menu 5 | * Performance optimizations 6 | -------------------------------------------------------------------------------- /messages/1.0.7.txt: -------------------------------------------------------------------------------- 1 | Improvements: 2 | 3 | * Add option for enabling this plugin for only current file 4 | * Add option for enabling "auto backup" 5 | 6 | See [this pull request](https://github.com/jamesfzhang/auto-save/pull/26) for more information. Thanks [kylebebak](https://github.com/kylebebak)! 7 | -------------------------------------------------------------------------------- /messages/1.0.8.txt: -------------------------------------------------------------------------------- 1 | Improvements: 2 | 3 | * Add option for ignoring files 4 | * Don't save when auto-complete menu is open--otherwise, the menu closes unexpectedly 5 | -------------------------------------------------------------------------------- /messages/install.txt: -------------------------------------------------------------------------------- 1 | Thank you for installing AutoSave 2 | ---------------------------------------- 3 | 4 | You're one step closer to having your files save automatically after every modification! 5 | 6 | 7 | Documentation 8 | ============= 9 | The plugin is dead simple. When turned on, the current file you are viewing will 10 | save automatically as you modify it. In other words, the file saves after every keystroke. 11 | The plugin is turned off by default since it is so invasive. You may enable it by adding 12 | a key binding to the "auto_save" command in "Preferences / Key Bindings - User", for example: 13 | 14 | { "keys": ["ctrl+shift+s"], "command": "auto_save" } 15 | 16 | See links below for more help. 17 | 18 | Useful Links 19 | ============ 20 | * Documentation & Code: https://github.com/jamesfzhang/auto-save 21 | * Report issues: https://github.com/jamesfzhang/auto-save/issues 22 | * Follow me on Twitter: @jamesfzhang 23 | -------------------------------------------------------------------------------- /repository.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "2.0", 3 | "packages": [ 4 | { 5 | "details": "https://github.com/jamesfzhang/auto-save", 6 | "releases": [ 7 | { 8 | "sublime_text": "*", 9 | "details": "https://github.com/jamesfzhang/auto-save/tags" 10 | } 11 | ] 12 | } 13 | ] 14 | } --------------------------------------------------------------------------------