├── .gitignore ├── .no-sublime-package ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── Default.sublime-commands ├── Default.sublime-keymap ├── LICENCE ├── Main.sublime-menu ├── README.md ├── Side Bar.sublime-menu ├── SublimeTmpl.sublime-settings ├── packages.json ├── sublime-tmpl.py └── templates ├── css.tmpl ├── html.tmpl ├── js.tmpl ├── php.tmpl ├── python.tmpl ├── ruby.tmpl └── xml.tmpl /.gitignore: -------------------------------------------------------------------------------- 1 | *.user.tmpl 2 | -------------------------------------------------------------------------------- /.no-sublime-package: -------------------------------------------------------------------------------- 1 | .no-sublime-package -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+alt+h"], "command": "sublime_tmpl", 4 | "args": {"type": "html"}, "context": [{"key": "sublime_tmpl.html"}] 5 | } 6 | ,{ 7 | "keys": ["ctrl+alt+j"], "command": "sublime_tmpl", 8 | "args": {"type": "js"}, "context": [{"key": "sublime_tmpl.js"}] 9 | } 10 | ,{ 11 | "keys": ["ctrl+alt+c"], "command": "sublime_tmpl", 12 | "args": {"type": "css"}, "context": [{"key": "sublime_tmpl.css"}] 13 | } 14 | ,{ 15 | "keys": ["ctrl+alt+p"], "command": "sublime_tmpl", 16 | "args": {"type": "php"}, "context": [{"key": "sublime_tmpl.php"}] 17 | } 18 | ,{ 19 | "keys": ["ctrl+alt+r"], "command": "sublime_tmpl", 20 | "args": {"type": "ruby"}, "context": [{"key": "sublime_tmpl.ruby"}] 21 | } 22 | ,{ 23 | "keys": ["ctrl+alt++shift+p"], "command": "sublime_tmpl", 24 | "args": {"type": "python"}, "context": [{"key": "sublime_tmpl.python"}] 25 | } 26 | ] -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+alt+h"], "command": "sublime_tmpl", 4 | "args": {"type": "html"}, "context": [{"key": "sublime_tmpl.html"}] 5 | } 6 | ,{ 7 | "keys": ["ctrl+alt+j"], "command": "sublime_tmpl", 8 | "args": {"type": "js"}, "context": [{"key": "sublime_tmpl.js"}] 9 | } 10 | ,{ 11 | "keys": ["ctrl+alt+c"], "command": "sublime_tmpl", 12 | "args": {"type": "css"}, "context": [{"key": "sublime_tmpl.css"}] 13 | } 14 | ,{ 15 | "keys": ["ctrl+alt+p"], "command": "sublime_tmpl", 16 | "args": {"type": "php"}, "context": [{"key": "sublime_tmpl.php"}] 17 | } 18 | ,{ 19 | "keys": ["ctrl+alt+r"], "command": "sublime_tmpl", 20 | "args": {"type": "ruby"}, "context": [{"key": "sublime_tmpl.ruby"}] 21 | } 22 | ,{ 23 | "keys": ["ctrl+alt++shift+p"], "command": "sublime_tmpl", 24 | "args": {"type": "python"}, "context": [{"key": "sublime_tmpl.python"}] 25 | } 26 | ] -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+alt+h"], "command": "sublime_tmpl", 4 | "args": {"type": "html"}, "context": [{"key": "sublime_tmpl.html"}] 5 | } 6 | ,{ 7 | "keys": ["ctrl+alt+j"], "command": "sublime_tmpl", 8 | "args": {"type": "js"}, "context": [{"key": "sublime_tmpl.js"}] 9 | } 10 | ,{ 11 | "keys": ["ctrl+alt+c"], "command": "sublime_tmpl", 12 | "args": {"type": "css"}, "context": [{"key": "sublime_tmpl.css"}] 13 | } 14 | ,{ 15 | "keys": ["ctrl+alt+p"], "command": "sublime_tmpl", 16 | "args": {"type": "php"}, "context": [{"key": "sublime_tmpl.php"}] 17 | } 18 | ,{ 19 | "keys": ["ctrl+alt+r"], "command": "sublime_tmpl", 20 | "args": {"type": "ruby"}, "context": [{"key": "sublime_tmpl.ruby"}] 21 | } 22 | ,{ 23 | "keys": ["ctrl+alt++shift+p"], "command": "sublime_tmpl", 24 | "args": {"type": "python"}, "context": [{"key": "sublime_tmpl.python"}] 25 | } 26 | ] -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "caption": "Tmpl: Create project-specific", "command": "sublime_tmpl", 4 | "args": {"type": "project"} 5 | }, 6 | { 7 | "caption": "Tmpl: Create html", "command": "sublime_tmpl", 8 | "args": {"type": "html"} 9 | }, 10 | { 11 | "caption": "Tmpl: Create javascript", "command": "sublime_tmpl", 12 | "args": {"type": "js"} 13 | }, 14 | { 15 | "caption": "Tmpl: Create css", "command": "sublime_tmpl", 16 | "args": {"type": "css"} 17 | }, 18 | { 19 | "caption": "Tmpl: Create php", "command": "sublime_tmpl", 20 | "args": {"type": "php"} 21 | }, 22 | { 23 | "caption": "Tmpl: Create python", "command": "sublime_tmpl", 24 | "args": {"type": "python"} 25 | }, 26 | { 27 | "caption": "Tmpl: Create ruby", "command": "sublime_tmpl", 28 | "args": {"type": "ruby"} 29 | } 30 | ] 31 | -------------------------------------------------------------------------------- /Default.sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "keys": ["ctrl+alt+h"], "command": "sublime_tmpl", 4 | "args": {"type": "html"}, "context": [{"key": "sublime_tmpl.html"}] 5 | } 6 | ,{ 7 | "keys": ["ctrl+alt+j"], "command": "sublime_tmpl", 8 | "args": {"type": "js"}, "context": [{"key": "sublime_tmpl.js"}] 9 | } 10 | ,{ 11 | "keys": ["ctrl+alt+c"], "command": "sublime_tmpl", 12 | "args": {"type": "css"}, "context": [{"key": "sublime_tmpl.css"}] 13 | } 14 | ,{ 15 | "keys": ["ctrl+alt+p"], "command": "sublime_tmpl", 16 | "args": {"type": "php"}, "context": [{"key": "sublime_tmpl.php"}] 17 | } 18 | ,{ 19 | "keys": ["ctrl+alt+r"], "command": "sublime_tmpl", 20 | "args": {"type": "ruby"}, "context": [{"key": "sublime_tmpl.ruby"}] 21 | } 22 | ,{ 23 | "keys": ["ctrl+alt++shift+p"], "command": "sublime_tmpl", 24 | "args": {"type": "python"}, "context": [{"key": "sublime_tmpl.python"}] 25 | } 26 | ] -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Kairyou. 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 | "id": "file", 4 | "children": 5 | [ 6 | { 7 | "id": "sublimetmpl", 8 | "caption": "New File (SublimeTmpl)", 9 | "children": 10 | [ 11 | { 12 | "id": "project", 13 | "caption": "Project Specific", 14 | "command": "sublime_tmpl", 15 | "args": { 16 | "type": "project" 17 | } 18 | }, 19 | { 20 | "id": "html", 21 | "caption": "HTML", 22 | "command": "sublime_tmpl", 23 | "args": { 24 | "type": "html" 25 | } 26 | }, 27 | { 28 | "id": "js", 29 | "caption": "Javascript", 30 | "command": "sublime_tmpl", 31 | "args": { 32 | "type": "js" 33 | } 34 | }, 35 | { 36 | "id": "css", 37 | "caption": "CSS", 38 | "command": "sublime_tmpl", 39 | "args": { 40 | "type": "css" 41 | } 42 | }, 43 | { 44 | "id": "php", 45 | "caption": "PHP", 46 | "command": "sublime_tmpl", 47 | "args": { 48 | "type": "php" 49 | } 50 | }, 51 | { 52 | "id": "python", 53 | "caption": "python", 54 | "command": "sublime_tmpl", 55 | "args": { 56 | "type": "python" 57 | } 58 | }, 59 | { 60 | "id": "ruby", 61 | "caption": "ruby", 62 | "command": "sublime_tmpl", 63 | "args": { 64 | "type": "ruby" 65 | } 66 | }, 67 | {"caption": "-"}, 68 | { 69 | "id": "menu", 70 | "command": "open_file", 71 | "args": {"file": "${packages}/SublimeTmpl/Main.sublime-menu"}, 72 | "caption": "Menu – Default" 73 | }, 74 | { 75 | "id": "menu", 76 | "command": "open_file", 77 | "args": {"file": "${packages}/User/SublimeTmpl/Main.sublime-menu"}, 78 | "caption": "Menu – User" 79 | } 80 | ] 81 | } 82 | ] 83 | }, 84 | { 85 | "id": "preferences", 86 | "children": 87 | [ 88 | { 89 | "caption": "Package Settings", 90 | "mnemonic": "P", 91 | "id": "package-settings", 92 | "children": 93 | [ 94 | { 95 | "caption": "SublimeTmpl", 96 | "children": 97 | [ 98 | { 99 | "command": "open_file", 100 | "args": {"file": "${packages}/SublimeTmpl/Main.sublime-menu"}, 101 | "caption": "Menu – Default" 102 | }, 103 | { 104 | "command": "open_file", 105 | "args": {"file": "${packages}/User/SublimeTmpl/Main.sublime-menu"}, 106 | "caption": "Menu – User" 107 | }, 108 | { "caption": "-" }, 109 | { 110 | "command": "open_file", 111 | "args": {"file": "${packages}/SublimeTmpl/Default.sublime-commands"}, 112 | "caption": "Commands – Default" 113 | }, 114 | { 115 | "command": "open_file", 116 | "args": {"file": "${packages}/User/SublimeTmpl/Default.sublime-commands"}, 117 | "caption": "Commands – User" 118 | }, 119 | { "caption": "-" }, 120 | { 121 | "command": "open_file", 122 | "args": {"file": "${packages}/SublimeTmpl/SublimeTmpl.sublime-settings"}, 123 | "caption": "Settings – Default" 124 | }, 125 | { 126 | "command": "open_file", 127 | "args": {"file": "${packages}/User/SublimeTmpl.sublime-settings"}, 128 | "caption": "Settings – User" 129 | }, 130 | { "caption": "-" }, 131 | { 132 | "command": "open_file", 133 | "args": { 134 | "file": "${packages}/SublimeTmpl/Default (OSX).sublime-keymap", 135 | "platform": "OSX" 136 | }, 137 | "caption": "Key Bindings – Default" 138 | }, 139 | { 140 | "command": "open_file", 141 | "args": { 142 | "file": "${packages}/SublimeTmpl/Default (Linux).sublime-keymap", 143 | "platform": "Linux" 144 | }, 145 | "caption": "Key Bindings – Default" 146 | }, 147 | { 148 | "command": "open_file", 149 | "args": { 150 | "file": "${packages}/SublimeTmpl/Default (Windows).sublime-keymap", 151 | "platform": "Windows" 152 | }, 153 | "caption": "Key Bindings – Default" 154 | }, 155 | { 156 | "command": "open_file", 157 | "args": { 158 | "file": "${packages}/User/Default (OSX).sublime-keymap", 159 | "platform": "OSX" 160 | }, 161 | "caption": "Key Bindings – User" 162 | }, 163 | { 164 | "command": "open_file", 165 | "args": { 166 | "file": "${packages}/User/Default (Linux).sublime-keymap", 167 | "platform": "Linux" 168 | }, 169 | "caption": "Key Bindings – User" 170 | }, 171 | { 172 | "command": "open_file", 173 | "args": { 174 | "file": "${packages}/User/Default (Windows).sublime-keymap", 175 | "platform": "Windows" 176 | }, 177 | "caption": "Key Bindings – User" 178 | }, 179 | { "caption": "-" } 180 | ] 181 | } 182 | ] 183 | } 184 | ] 185 | } 186 | ] 187 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SublimeTmpl 2 | =========== 3 | 4 | A Sublime Text 2/3 plugin for create file from templates. 5 | 6 | Installation 7 | ------------ 8 | 9 | **Github** 10 | 11 | Go to the "Packages" directory (`Preferences` / `Browse Packages`). Then clone this repository: 12 | 13 | $ git clone https://github.com/kairyou/SublimeTmpl.git 14 | 15 | **Package Control** 16 | 17 | Install [Package Control][1]. Then `Package Control: Install Package`, look for `SublimeTmpl` / `tmpl` and install it. 18 | 19 | Usage 20 | ----- 21 | 22 | - Create file with menu 23 | `File - New File (SublimeTmpl)` 24 | 25 | - Create file with command 26 | use `cmd+shift+p` then look for `tmpl:` 27 | 28 | Settings 29 | -------- 30 | 31 | Default Settings: `Preferences` > `Packages Settings` > `SublimeTmpl` > `Settings - Default` 32 | 33 | Custom settings (**Recommend*): `Preferences` > `Package Settings` > `SublimeTmpl` > `Settings - User` 34 | 35 | Default template files: `Packages/SublimeTmpl/templates` 36 | 37 | Custom template files (**Recommend**): `Packages/User/SublimeTmpl/templates/` 38 | 39 | Project-specific template files (ST3 only): via `settings`: `SublimeTmpl`: `template_folder` key within your sublime-project file (see "Features added" below) 40 | 41 | 42 | Default key bindings 43 | -------------------- 44 | 45 | ctrl+alt+h html 46 | ctrl+alt+j javascript 47 | ctrl+alt+c css 48 | ctrl+alt+p php 49 | ctrl+alt+r ruby 50 | ctrl+alt+shift+p python 51 | 52 | **Disable shortcuts** 53 | 54 | If you’re unhappy with default keymap, you can disable keyboard shortcuts with `disable_keymap_actions` preference of `SublimeTmpl.sublime-settings`. 55 | 56 | Use a comma-separated list of action names which default keyboard shortcuts should be disabled. For example, if you want to disable creat `html` and `css` shortcuts, your must set the following value: 57 | 58 | "disabled_keymap_actions": "html, css" 59 | 60 | To disable all default shortcuts, set value to `all`. 61 | 62 | 63 | ## Features added 64 | 65 | - custom template files 66 | 67 | > put your custom template files in `Packages/User/SublimeTmpl/templates` 68 | > Project-specific template files can be specified in project files, along with overriding other templating options. 69 | 70 | - `*.tmpl` file support `${date}` variable 71 | 72 | > default "date_format" : "%Y-%m-%d %H:%M:%S" . 73 | 74 | - `*.tmpl` file support `${saved_filename}`, `${saved_filepath}` on save file 75 | 76 | > Enable: `SublimeTmpl > settings - user` add `"enable_file_variables_on_save": true,` 77 | 78 | - `*.tmpl` file support `${project_base_name}`, `${project_path}` and `${platform}` 79 | 80 | NOTE: This will only work with SublimeText 3.0 or above. 81 | 82 | > Enable: `SublimeTmpl > settings - user` add `"enable_project_variables": true,` 83 | 84 | 85 | It is recommended that you put your own custom settings in `settings - user`. Please see note below in "*Detailed Instructions for Sublime Newbies" 86 | 87 | - custom variables: `attr` 88 | 89 | > custom the attr variables in settings, example: 90 | > 91 | ``` json 92 | "attr": { 93 | "author": "Your Name" , 94 | "email": "you@example.org", 95 | "link": "http://example.org", 96 | "hello": "word" 97 | } 98 | ``` 99 | 100 | > The `*.tmpl` file will support `${author}` `${email}` `${link}` `${hello}` variables. 101 | 102 | - Project specific overrides via `SublimeTmpl` attribute in sublime-project file. 103 | > 104 | ``` json 105 | "settings": 106 | { 107 | "SublimeTmpl": 108 | { 109 | "template_folder": "Path\\to\\some\\custom\\template\\folder", 110 | "template_replace_pattern": "{{%s}}", 111 | "enable_project_variables": true, 112 | "enable_file_variables_on_save": true, 113 | "attr": { // Fully overrides "attr" settings (i.e. elements missing here will not attempt to be replaced in template) 114 | "author": "Alternative Name" 115 | }, 116 | "project_variables": { 117 | // Allows for use with other template formats, provide mapping here 118 | // "tmpl_formatted_name": "current_template_name" 119 | "project_base_name": "projectbase", 120 | "project_path": "projectpath", 121 | "platform": "plat" 122 | }, 123 | 124 | "file_variables_on_save": { 125 | // Allows for use with other template formats, provide mapping here 126 | // "tmpl_formatted_name": "current_template_name" 127 | "saved_filename": "name", 128 | "saved_filepath": "filepath" 129 | }, 130 | }, 131 | }, 132 | ``` 133 | 134 | *Detailed Instructions for Sublime Newbies 135 | ----------------------------------------- 136 | 137 | Sublime Text keeps settings in bunch of files in a folder. For example, OS X, it is located at 138 | 139 | ```/Users/yourusername/Library/Application Support/Sublime Text 3/Packages``` 140 | 141 | You can navigate to it easily by using the following menu item in Sublime, for example: `Sublime Text>Preferences>Browse Packages` 142 | 143 | Now go to `Packages\SublimeTmpl` folder and open the file SublimeTmpl.sublime-settings. Save the file with the same file name under `Packages\User`. Delete everything except the variables that are custom to you. By the time you are finished, the file might look as simple as this (JSON format): 144 | ``` 145 | { 146 | "attr": { 147 | "author": "Chuck Norris" , 148 | "email": "chuck@kickbutt.com", 149 | } 150 | } 151 | ``` 152 | 153 | If you don't want the `"link"` and `"hello"` variables to show up, you should copy the (for example) python.tmpl file to `Packages/User/SublimeTmpl/templates` and remove those elements from it. 154 | 155 | 156 | Contributors 157 | ------- 158 | - [View Contributors](https://github.com/kairyou/SublimeTmpl/graphs/contributors) 159 | 160 | ### Donate 161 | PayPal donate button 162 | 163 | FAQ 164 | --- 165 | - SublimeTmpl not work after update the package. 166 | 167 | Please open `Preferences` / `Settings - User`, remove "SublimeTmpl" from `ignored_packages`. 168 | - Alert message `Replace pattern None doesn't seem to work: unsupported operand type(s) for %: 'NoneType' and 'str'` 169 | 170 | Please restart Sublime Text and try again. 171 | 172 | -------------------- 173 | Source: [https://github.com/kairyou/SublimeTmpl][0] 174 | 175 | Docs: [中文文档](https://xhl.me/archives/sublime-template-engine-sublimetmpl/) 176 | 177 | 178 | [0]: https://github.com/kairyou/SublimeTmpl 179 | [1]: https://packagecontrol.io 180 | -------------------------------------------------------------------------------- /Side Bar.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "sublimetmpl", 4 | "caption": "New File (SublimeTmpl)", 5 | "children": 6 | [ 7 | { 8 | "id": "project", 9 | "caption": "Project Specific", 10 | "command": "sublime_tmpl", 11 | "args": { 12 | "type": "project", 13 | "paths": [], 14 | } 15 | }, 16 | { 17 | "id": "html", 18 | "caption": "HTML", 19 | "command": "sublime_tmpl", 20 | "args": { 21 | "type": "html", 22 | "paths": [], 23 | } 24 | }, 25 | { 26 | "id": "js", 27 | "caption": "Javascript", 28 | "command": "sublime_tmpl", 29 | "args": { 30 | "type": "js", 31 | "paths": [], 32 | } 33 | }, 34 | { 35 | "id": "css", 36 | "caption": "CSS", 37 | "command": "sublime_tmpl", 38 | "args": { 39 | "type": "css", 40 | "paths": [], 41 | } 42 | }, 43 | { 44 | "id": "php", 45 | "caption": "PHP", 46 | "command": "sublime_tmpl", 47 | "args": { 48 | "type": "php", 49 | "paths": [], 50 | } 51 | }, 52 | { 53 | "id": "python", 54 | "caption": "python", 55 | "command": "sublime_tmpl", 56 | "args": { 57 | "type": "python", 58 | "paths": [], 59 | } 60 | }, 61 | { 62 | "id": "ruby", 63 | "caption": "ruby", 64 | "command": "sublime_tmpl", 65 | "args": { 66 | "type": "ruby", 67 | "paths": [], 68 | } 69 | }, 70 | {"caption": "-"}, 71 | { 72 | "id": "menu", 73 | "command": "open_file", 74 | "args": {"file": "${packages}/SublimeTmpl/Side Bar.sublime-menu"}, 75 | "caption": "Side Bar Menu – Default" 76 | }, 77 | { 78 | "id": "menu", 79 | "command": "open_file", 80 | "args": {"file": "${packages}/User/SublimeTmpl/Side Bar.sublime-menu"}, 81 | "caption": "Side Bar Menu – User" 82 | } 83 | ] 84 | } 85 | ] -------------------------------------------------------------------------------- /SublimeTmpl.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "html": { 3 | "syntax": "Packages/HTML/HTML.tmLanguage", 4 | "extension": "html" // default_extension 5 | }, 6 | "js": { 7 | "syntax": "Packages/JavaScript/JavaScript.tmLanguage", 8 | "extension": "js" 9 | }, 10 | "css": { 11 | "syntax": "Packages/CSS/CSS.tmLanguage", 12 | "extension": "css" 13 | }, 14 | "xml": { 15 | "syntax": "Packages/XML/XML.tmLanguage", 16 | "extension": "xml" 17 | }, 18 | "php": { 19 | "syntax": "Packages/PHP/PHP.tmLanguage", 20 | "extension": "php" 21 | }, 22 | "java": { 23 | "syntax": "Packages/Java/Java.tmLanguage", 24 | "extension": "java" 25 | }, 26 | "ruby": { 27 | "syntax": "Packages/Ruby/Ruby.tmLanguage", 28 | "extension": "rb" 29 | }, 30 | "python": { 31 | "syntax": "Packages/Python/Python.tmLanguage", 32 | "extension": "py" 33 | }, 34 | "objective-c": { 35 | "syntax": "Packages/Objective-C/Objective-C.tmLanguage", 36 | "extension": "m" 37 | }, 38 | "c++": { 39 | "syntax": "Packages/C++/C++.tmLanguage", 40 | "extension": "cpp" 41 | }, 42 | "C#": { 43 | "syntax": "Packages/C#/C#.tmLanguage", 44 | "extension": "cs" 45 | }, 46 | "Perl": { 47 | "syntax": "Packages/Perl/Perl.tmLanguage", 48 | "extension": "pl" 49 | }, 50 | "sass": { 51 | "syntax": "Packages/SCSS/SCSS.tmLanguage", 52 | // "syntax": "Packages/Sass/Syntaxes/Sass.tmLanguage", 53 | "extension": "scss" 54 | }, 55 | "go": { 56 | "syntax": "Packages/Go/Go.tmLanguage", 57 | "extension": "go" 58 | }, 59 | "groovy": { 60 | "syntax": "Packages/Groovy/Groovy.tmLanguage", 61 | "extension": "groovy" 62 | }, 63 | "erlang": { 64 | "syntax": "Packages/Erlang/Erlang.tmLanguage", 65 | "extension": "erl" 66 | }, 67 | "jade": { 68 | "syntax": "Packages/Jade/Syntaxes/Jade.tmLanguage", 69 | "extension": "jade" 70 | }, 71 | "less": { 72 | "syntax": "Packages/LESS/LESS.tmLanguage", 73 | "extension": "less" 74 | }, 75 | "lisp": { 76 | "syntax": "Packages/Lisp/Lisp.tmLanguage", 77 | "extension": "lisp" 78 | }, 79 | "lua": { 80 | "syntax": "Packages/Lua/Lua.tmLanguage", 81 | "extension": "lua" 82 | }, 83 | "make": { 84 | "syntax": "Packages/Makefile/Makefile.tmLanguage", 85 | "extension": "make" 86 | }, 87 | "rust": { 88 | "syntax": "Packages/Rust/Rust.tmLanguage", 89 | "extension": "rs" 90 | }, 91 | "scala": { 92 | "syntax": "Packages/Scala/Scala.tmLanguage", 93 | "extension": "scala" 94 | }, 95 | "shellscript": { 96 | "syntax": "Packages/ShellScript/Shell-Unix-Generic.tmLanguage", 97 | "extension": "sh" 98 | }, 99 | "sql": { 100 | "syntax": "Packages/SQL/SQL.tmLanguage", 101 | "extension": "sql" 102 | }, 103 | "yaml": { 104 | "syntax": "Packages/YAML/YAML.tmLanguage", 105 | "extension": "yaml" 106 | }, 107 | "disable_keymap_actions": false, // "all"; "html,css" 108 | "enable_project_variables": false, 109 | "enable_file_variables_on_save": false, 110 | "date_format" : "%Y-%m-%d %H:%M:%S", 111 | "attr": { 112 | "author": "Your Name", 113 | "email": "you@example.org", 114 | "link": "http://example.org" 115 | }, 116 | "project_variables": { 117 | // Allows for use with other template formats, provide mapping here 118 | // "tmpl_formatted_name": "current_template_name" 119 | "project_base_name": "project_base_name", 120 | "project_path": "project_path", 121 | "platform": "platform" 122 | }, 123 | 124 | "file_variables_on_save": { 125 | // Allows for use with other template formats, provide mapping here 126 | // "tmpl_formatted_name": "current_template_name" 127 | "saved_filename": "saved_filename", 128 | "saved_filepath": "saved_filepath" 129 | }, 130 | "template_replace_pattern": "${%s}", 131 | "template_extension": ".tmpl" 132 | } -------------------------------------------------------------------------------- /packages.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.2", 3 | "packages": [ 4 | { 5 | "name": "SublimeTmpl", 6 | "description": "Create File From Templates for ST2/ST3.", 7 | "author": "kairyou", 8 | "homepage": "https://github.com/kairyou/SublimeTmpl", 9 | "last_modified": "2013-05-24 12:00:00", 10 | "platforms": { 11 | "*": [ 12 | { 13 | "version": "1.0.4", 14 | "url": "https://nodeload.github.com/kairyou/SublimeTmpl/zipball/master" 15 | } 16 | ] 17 | } 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /sublime-tmpl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # + Python 3 support 4 | # + sublime text 3 support 5 | 6 | import sublime 7 | import sublime_plugin 8 | # import sys 9 | import os 10 | import glob 11 | import datetime 12 | import zipfile 13 | import re 14 | import shutil 15 | 16 | PACKAGE_NAME = 'SublimeTmpl' 17 | TMLP_DIR = 'templates' 18 | KEY_SYNTAX = 'syntax' 19 | KEY_FILE_EXT = 'extension' 20 | 21 | # st3: Installed Packages/xx.sublime-package 22 | BASE_PATH = os.path.abspath(os.path.dirname(__file__)) 23 | PACKAGES_PATH = sublime.packages_path() # for ST2 24 | 25 | # sys.path += [BASE_PATH] 26 | # sys.path.append(BASE_PATH) 27 | # import sys;print(sys.path) 28 | 29 | IS_GTE_ST3 = int(sublime.version()[0]) >= 3 30 | DISABLE_KEYMAP = None 31 | 32 | 33 | def get_replace_pattern(settings): 34 | """ Set replacement pattern to look for in template files """ 35 | replace_pattern = settings.get('template_replace_pattern') 36 | 37 | # sanity check the pattern 38 | try: 39 | x = replace_pattern % "test" 40 | except Exception as ex: 41 | sublime.message_dialog("[Warning] Replace pattern {0} doesn't seem to work: {1}".format(replace_pattern, ex)) 42 | raise 43 | 44 | return replace_pattern 45 | 46 | class MergedSettings(sublime.Settings): 47 | """ Helper class to merge project and plugin settings. 48 | Attempts to use project overrides first before defaulting back to plugin settings. """ 49 | def __init__(self, view): 50 | self.fallback_settings = {} 51 | self.settings = sublime.load_settings(PACKAGE_NAME + '.sublime-settings') 52 | if IS_GTE_ST3: 53 | self.fallback_settings = self.settings 54 | self.settings = view.settings().get("SublimeTmpl", {}) # project overrides 55 | 56 | def get(self, name, default=None): 57 | return self.settings.get(name, self.fallback_settings.get(name, default)) 58 | 59 | 60 | def get_settings(view, type=None): 61 | """ Get settings object, with any project-specific overrides merged in """ 62 | settings = MergedSettings(view) 63 | 64 | if not type: 65 | return settings 66 | 67 | opts = settings.get(type, []) 68 | return opts 69 | 70 | 71 | class SublimeTmplCommand(sublime_plugin.TextCommand): 72 | 73 | def run(self, edit, type='html', paths = None): 74 | view = self.view 75 | 76 | if type == 'project': 77 | # need to present project-specific templates for user to select 78 | 79 | projectFolder = self.get_project_template_folder() 80 | if not projectFolder: 81 | sublime.message_dialog('No "template_folder" specified in current project file') 82 | return False 83 | 84 | template_extension = self.get_template_extension() 85 | self.project_templates = [] 86 | for dirpath, dirnames, filenames in os.walk(projectFolder): 87 | # for dirname in dirnames: 88 | # self.project_templates.append(dirname) 89 | for filename in filenames: 90 | if os.path.splitext(filename)[1] == template_extension: 91 | self.project_templates.append((dirpath, os.path.splitext(filename)[0])) 92 | 93 | options = [] 94 | for (path, name) in self.project_templates: 95 | options.append("Template: {}".format(name)) 96 | 97 | if not options: 98 | sublime.message_dialog('No templates found in current project template folder {0}'.format(projectFolder)) 99 | return False 100 | 101 | self.view.window().show_quick_panel( 102 | options, 103 | selected_index=0, 104 | on_select=self.run_project_template, 105 | on_highlight=None, 106 | ) 107 | 108 | return 109 | 110 | opts = get_settings(self.view, type) 111 | tmpl = self.get_code(type) 112 | 113 | # print('global', DISABLE_KEYMAP, IS_GTE_ST3); 114 | if DISABLE_KEYMAP: 115 | return False 116 | 117 | # print(KEY_SYNTAX in opts) 118 | self.tab = self.creat_tab(view, paths) 119 | 120 | self.set_syntax(opts) 121 | # sublime.set_timeout(lambda: self.set_syntax(opts), 1000) 122 | self.set_code(tmpl) 123 | 124 | def run_project_template(self, index): 125 | self.view.run_command('sublime_tmpl', 126 | args={'type': self.project_templates[index][1]}) 127 | 128 | @staticmethod 129 | def open_file(path, mode='r'): 130 | with open(path, mode) as fp: 131 | code = fp.read() 132 | return code 133 | 134 | @staticmethod 135 | def is_resource_path(path): 136 | """ Check if an absolute path points to an ST3 resource folder """ 137 | if IS_GTE_ST3: 138 | return os.path.commonprefix([path, sublime.packages_path()]) == sublime.packages_path() 139 | else: 140 | return False # doesn't apply for ST2 141 | 142 | @staticmethod 143 | def format_as_resource_path(path): 144 | """ Convert an absolute path to an ST3 resource path """ 145 | return os.path.join('Packages', os.path.relpath(path, sublime.packages_path())) 146 | 147 | def get_template_folders(self): 148 | """ Returns list of paths expected to contain templates. 149 | Paths are absolute, additional conversion needed for ST3 resource paths """ 150 | PACKAGES_PATH = sublime.packages_path() 151 | project_tmpl_dir = self.get_project_template_folder() 152 | tmpl_dir = os.path.join(PACKAGES_PATH, PACKAGE_NAME, TMLP_DIR) 153 | user_tmpl_dir = os.path.join(PACKAGES_PATH, 'User', PACKAGE_NAME, TMLP_DIR) 154 | 155 | if project_tmpl_dir is not None: 156 | project_tmpl_dir = os.path.abspath(project_tmpl_dir) 157 | 158 | paths = [] 159 | 160 | # inserted in order we want to search (more specific -> more general) 161 | if project_tmpl_dir is not None and os.path.exists(project_tmpl_dir): 162 | paths.append(project_tmpl_dir) 163 | if os.path.exists(user_tmpl_dir): 164 | paths.append(user_tmpl_dir) 165 | if os.path.exists(tmpl_dir): 166 | paths.append(tmpl_dir) 167 | 168 | return paths 169 | 170 | def get_project_template_folder(self): 171 | """ Get project template folder (if one is set) """ 172 | return get_settings(self.view).get('template_folder', None) 173 | 174 | def get_template_extension(self): 175 | return get_settings(self.view).get('template_extension', '.tmpl') 176 | 177 | def get_code(self, type): 178 | code = '' 179 | file_name = "%s%s" % (type, self.get_template_extension()) 180 | templateFound = False 181 | 182 | paths = self.get_template_folders() 183 | 184 | for path in paths: 185 | fullpath = os.path.join(path, file_name) 186 | if self.is_resource_path(fullpath): 187 | try: 188 | fullpath = self.format_as_resource_path(fullpath) 189 | code = sublime.load_resource(fullpath) 190 | templateFound = True 191 | except IOError: 192 | pass # try the next folder 193 | else: 194 | if os.path.isfile(fullpath): 195 | code = self.open_file(fullpath) 196 | templateFound = True 197 | 198 | if templateFound: 199 | break 200 | 201 | if not templateFound: 202 | sublime.message_dialog('[Warning] No such file {0} found in paths {1}: '.format( 203 | file_name, paths)) 204 | 205 | return self.format_tag(code) 206 | 207 | def format_tag(self, code): 208 | """ Replace matched patterns in file contents """ 209 | win = self.view.window() 210 | code = code.replace('\r', '') # replace \r\n -> \n 211 | # format 212 | settings = get_settings(self.view) 213 | pattern = get_replace_pattern(settings) 214 | 215 | format = settings.get('date_format', '%Y-%m-%d') 216 | date = datetime.datetime.now().strftime(format) 217 | if not IS_GTE_ST3: 218 | code = code.decode('utf8') # for st2 && Chinese characters 219 | code = code.replace(pattern.replace("%s", "date"), date) 220 | 221 | attr = settings.get('attr', {}) 222 | for key in attr: 223 | code = code.replace(pattern % key, attr.get(key, '')) 224 | 225 | if settings.get('enable_project_variables', False) and hasattr(win, 'extract_variables'): 226 | variables = win.extract_variables() 227 | project_variables = settings.get('project_variables', {}) 228 | for key in project_variables: 229 | code = code.replace(pattern % project_variables[key], variables.get(key, '')) 230 | 231 | # keep ${var..} 232 | if pattern == "${%s}": 233 | code = re.sub(r"(?= 3016 319 | # global PACKAGES_PATH 320 | PACKAGES_PATH = sublime.packages_path() 321 | TARGET_PATH = os.path.join(PACKAGES_PATH, PACKAGE_NAME) 322 | # print(BASE_PATH, os.path.dirname(BASE_PATH), TARGET_PATH) 323 | 324 | # auto create custom_path 325 | custom_path = os.path.join(PACKAGES_PATH, 'User', PACKAGE_NAME, TMLP_DIR) 326 | # print(custom_path, os.path.isdir(custom_path)) 327 | not_existed = not os.path.isdir(custom_path) 328 | if not_existed: 329 | os.makedirs(custom_path) 330 | 331 | files = glob.iglob(os.path.join(BASE_PATH, TMLP_DIR, '*.tmpl')) 332 | for file in files: 333 | dst_file = os.path.join(custom_path, os.path.basename(file)) 334 | if not os.path.exists(dst_file): 335 | shutil.copy(file, dst_file) 336 | 337 | 338 | # first run (https://git.io/vKMIS, does not need extract files) 339 | if not os.path.isdir(TARGET_PATH): 340 | os.makedirs(os.path.join(TARGET_PATH, TMLP_DIR)) 341 | # copy user files 342 | tmpl_dir = TMLP_DIR + '/' 343 | file_list = [ 344 | 'Default.sublime-commands', 'Main.sublime-menu', 345 | # if don't copy .py, ST3 throw: ImportError: No module named # fix: restart sublime 346 | 'sublime-tmpl.py', 347 | 'README.md', 348 | tmpl_dir + 'css.tmpl', tmpl_dir + 'html.tmpl', 349 | tmpl_dir + 'js.tmpl', tmpl_dir + 'php.tmpl', 350 | tmpl_dir + 'python.tmpl', tmpl_dir + 'ruby.tmpl', 351 | tmpl_dir + 'xml.tmpl' 352 | ] 353 | try: 354 | extract_zip_resource(BASE_PATH, file_list, TARGET_PATH) 355 | except Exception as e: 356 | print(e) 357 | 358 | # old: *.user.tmpl compatible fix 359 | files = glob.iglob(os.path.join(os.path.join(TARGET_PATH, TMLP_DIR), '*.user.tmpl')) 360 | for file in files: 361 | filename = os.path.basename(file).replace('.user.tmpl', '.tmpl') 362 | # print(file, '=>', os.path.join(custom_path, filename)); 363 | os.rename(file, os.path.join(custom_path, filename)) 364 | 365 | # old: settings-custom_path compatible fix 366 | settings = sublime.load_settings(PACKAGE_NAME + '.sublime-settings') 367 | old_custom_path = settings.get('custom_path', '') 368 | if old_custom_path and os.path.isdir(old_custom_path): 369 | # print(old_custom_path) 370 | files = glob.iglob(os.path.join(old_custom_path, '*.tmpl')) 371 | for file in files: 372 | filename = os.path.basename(file).replace('.user.tmpl', '.tmpl') 373 | # print(file, '=>', os.path.join(custom_path, filename)) 374 | os.rename(file, os.path.join(custom_path, filename)) 375 | 376 | if not IS_GTE_ST3: 377 | sublime.set_timeout(plugin_loaded, 0) 378 | 379 | def extract_zip_resource(path_to_zip, file_list, extract_dir=None): 380 | if extract_dir is None: 381 | return 382 | # print(extract_dir) 383 | if os.path.exists(path_to_zip): 384 | with zipfile.ZipFile(path_to_zip, 'r') as z: 385 | for f in z.namelist(): 386 | # if f.endswith('.tmpl'): 387 | if f in file_list: 388 | # print(f) 389 | z.extract(f, extract_dir) 390 | -------------------------------------------------------------------------------- /templates/css.tmpl: -------------------------------------------------------------------------------- 1 | ${1:@charset "${2:UTF-8}";} 2 | /** 3 | * ${3:} 4 | * @authors ${author} (${email}) 5 | * @date ${date} 6 | * @version \$Id\$ 7 | */ 8 | $0 -------------------------------------------------------------------------------- /templates/html.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${1:Examples} 7 | ${2: 8 | 9 | } 10 | 11 | 12 | $0 13 | 14 | -------------------------------------------------------------------------------- /templates/js.tmpl: -------------------------------------------------------------------------------- 1 | /** 2 | * ${1:} 3 | * @authors ${author} (${email}) 4 | * @date ${date} 5 | * @version \$Id\$ 6 | */ 7 | 8 | $0 -------------------------------------------------------------------------------- /templates/php.tmpl: -------------------------------------------------------------------------------- 1 | 2 | <${1:root}> 3 | $0 4 | --------------------------------------------------------------------------------