├── .gitignore ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── Main.sublime-menu ├── README.md ├── Verilog Automatic.py └── Verilog Automatic.sublime-settings /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.cache 3 | *.sublime-project -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["shift+f6"], "command": "auto_port" }, 3 | { "keys": ["shift+f7"], "command": "auto_inst" }, 4 | { "keys": ["shift+f8"], "command": "auto_def" }, 5 | { "keys": ["shift+f9"], "command": "add_header" } 6 | ] 7 | -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["shift+f6"], "command": "auto_def" }, 3 | { "keys": ["shift+f7"], "command": "auto_port" }, 4 | { "keys": ["shift+f8"], "command": "auto_inst" } 5 | ] -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": ["shift+f6"], "command": "auto_port" }, 3 | { "keys": ["shift+f7"], "command": "auto_inst" }, 4 | { "keys": ["shift+f8"], "command": "auto_def" }, 5 | { "keys": ["shift+f9"], "command": "add_header" } 6 | ] -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": "tools", 4 | "caption": "Tools", 5 | "children": 6 | [ 7 | { 8 | "id": "packages", 9 | "caption": "Packages", 10 | "children": 11 | [ 12 | { 13 | "id": "Verilog Automatic", 14 | "caption": "Verilog Automatic", 15 | "children": 16 | [ 17 | { 18 | "caption": "Auto Port", 19 | "command": "auto_port" 20 | }, 21 | { 22 | "caption": "Auto Instance", 23 | "command": "auto_inst" 24 | }, 25 | { 26 | "caption": "Auto Define", 27 | "command": "auto_def" 28 | }, 29 | { "caption": "-" }, 30 | { 31 | "caption": "Add File Header", 32 | "command": "add_header" 33 | } 34 | 35 | ] 36 | } 37 | ] 38 | } 39 | ] 40 | }, 41 | { 42 | 43 | "id": "preferences", 44 | "children": 45 | [ 46 | { 47 | "caption": "Package Settings", 48 | "mnemonic": "P", 49 | "id": "package-settings", 50 | "children": 51 | [ 52 | { 53 | "caption": "Verilog Automatic", 54 | "children": 55 | [ 56 | { 57 | "command": "open_file", 58 | "args": {"file": "${packages}/Verilog Automatic/README.md"}, 59 | "caption": "README" 60 | }, 61 | { "caption": "-" }, 62 | { 63 | "command": "open_file", 64 | "args": {"file": "${packages}/Verilog Automatic/Verilog Automatic.sublime-settings"}, 65 | "caption": "Settings - Default" 66 | }, 67 | { 68 | "command": "open_file", 69 | "args": {"file": "${packages}/User/Verilog Automatic.sublime-settings"}, 70 | "caption": "Settings – User" 71 | }, 72 | { 73 | "command": "open_file_settings", 74 | "caption": "Settings – Syntax Specific – User" 75 | }, 76 | { "caption": "-" }, 77 | { 78 | "command": "open_file", 79 | "args": { 80 | "file": "${packages}/Verilog Automatic/Default (OSX).sublime-keymap", 81 | "platform": "OSX" 82 | }, 83 | "caption": "Key Bindings – Default" 84 | }, 85 | { 86 | "command": "open_file", 87 | "args": { 88 | "file": "${packages}/Verilog Automatic/Default (Linux).sublime-keymap", 89 | "platform": "Linux" 90 | }, 91 | "caption": "Key Bindings – Default" 92 | }, 93 | { 94 | "command": "open_file", 95 | "args": { 96 | "file": "${packages}/Verilog Automatic/Default (Windows).sublime-keymap", 97 | "platform": "Windows" 98 | }, 99 | "caption": "Key Bindings – Default" 100 | }, 101 | { 102 | "command": "open_file", 103 | "args": { 104 | "file": "${packages}/User/Default (OSX).sublime-keymap", 105 | "platform": "OSX" 106 | }, 107 | "caption": "Key Bindings – User" 108 | }, 109 | { 110 | "command": "open_file", 111 | "args": { 112 | "file": "${packages}/User/Default (Linux).sublime-keymap", 113 | "platform": "Linux" 114 | }, 115 | "caption": "Key Bindings – User" 116 | }, 117 | { 118 | "command": "open_file", 119 | "args": { 120 | "file": "${packages}/User/Default (Windows).sublime-keymap", 121 | "platform": "Windows" 122 | }, 123 | "caption": "Key Bindings – User" 124 | }, 125 | { "caption": "-" } 126 | ] 127 | } 128 | ] 129 | } 130 | ] 131 | } 132 | 133 | ] 134 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Verilog Automatic 2 | ==================== 3 | This plugin can automatically add ports to the current editing file, generate module instances (need ctags),add instance connections ,add file header for verilog code. Both verilog-1995 and verilog-2001 style are supported. 4 | I borrowed the idea from automatic.vim which is a similar plugin for VIM, I just rewrote one for sublime text2&3. 5 | 6 | # Features 7 | *********** 8 | * AutoPort 9 | * AutoInst 10 | * AutoDef 11 | * AddFileHeader 12 | 13 | 14 | # Description 15 | 16 | 17 | ## AutoPort:(shift+f6) 18 | ******************* 19 | Automatically add ports to the current editing file after the "/*autoport*/" mark. 20 | 21 | * NOTE: NOT SUPPORTED STYLE: 22 | 23 | input clk,output single_out, //multiple input/output/inout keywords in the same line 24 | input clk,rst, 25 | chip_en; //multiple signals separated by comma written in different lines 26 | 27 | * NOTE: Do not use this function when there are multiple modules in the same file. 28 | 29 | Example: 30 | 31 | #### Before 32 | 33 | (verilog-1995 style): 34 | 35 | module test(/*autoport*/); 36 | input [1:0]a; 37 | input b; 38 | output [2:0]c,d; 39 | inout e; 40 | 41 | (verilog-2001 style): 42 | 43 | module test(/*autoport*/); 44 | input wire[1:0]a; 45 | input wire b; 46 | output reg [2:0]c,d; 47 | inout wire e; 48 | 49 | #### After: 50 | 51 | module test(/*autoport*/ 52 | //inout 53 | e, 54 | //output 55 | c, 56 | d, 57 | //input 58 | a, 59 | b); 60 | 61 | 62 | ## AutoInst:(shift+f7) 63 | ******************* 64 | Automatically generate module instances after the "/*autoinst*/" mark (need ctags). 65 | 66 | * NOTE:Need to place the cursor on the module name, multiple-cursor supported to generate multiple instances. 67 | 68 | Example: 69 | 70 | #### Before: 71 | test test_instance(/*autoinst*/); 72 | 73 | #### After: 74 | * Place the cursor on the module name "test" 75 | 76 | test test_instance(/*autoinst*/ 77 | .e(e), 78 | .c(c), 79 | .d(d[2:0]), 80 | .a(a[1:0]), 81 | .b(b)); 82 | 83 | 84 | 85 | ## AutoDef:(shift+f8) 86 | ****************** 87 | Automatically add instance connections after the /*autodef*/ mark. 88 | 89 | Example: 90 | #### before: 91 | 92 | /*autodef*/ 93 | 94 | 95 | 96 | test test_instance(/*autoinst*/ 97 | .e(e), 98 | .c(c), 99 | .d(d[2:0]), 100 | .a(a[1:0]), 101 | .b(b)); 102 | #### after: 103 | 104 | /*autodef*/ 105 | wire e; 106 | wire [2:0]d; 107 | wire c; 108 | wire b; 109 | wire [1:0]a; 110 | //assign e= 111 | //assign d= 112 | //assign c= 113 | //assign b= 114 | //assign a= 115 | 116 | 117 | 118 | test test_instance(/*autoinst*/ 119 | .e(e), 120 | .c(c), 121 | .d(d[2:0]), 122 | .a(a[1:0]), 123 | .b(b)); 124 | 125 | 126 | ## AddFileHeader:(shift+f9) 127 | ************************ 128 | Add your personal information in the setting file(the user's setting file is better),like below or leave any of them empty: 129 | 130 | { 131 | "Author":"Mike", 132 | "Company":"Microsoft", 133 | "Email":"whatever@yahoo.com" 134 | } 135 | thus generates the file header like this: 136 | 137 | //================================================================================================== 138 | // Filename : test.v 139 | // Created On : 2013-04-01 21:37:31 140 | // Last Modified : 141 | // Revision : 142 | // Author : Mike 143 | // Company : Microsoft 144 | // Email : whatever@yahoo.com 145 | // 146 | // Description : 147 | // 148 | // 149 | //================================================================================================== 150 | 151 | ## Change log 152 | 153 | #### 05/08/2013 154 | Add verilog-2001 style port declaration support. 155 | Add comments support, single line commneted-out code will be ignored. -------------------------------------------------------------------------------- /Verilog Automatic.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | import re 4 | import os 5 | import time 6 | from os.path import normpath, dirname 7 | 8 | sublime_version = 2 9 | if int(sublime.version()) > 3000: 10 | sublime_version = 3 11 | 12 | 13 | def find_tags_relative_to(file_name): 14 | if not file_name: 15 | return None 16 | 17 | dirs = dirname(normpath(file_name)).split(os.path.sep) 18 | 19 | while dirs: 20 | joined = os.path.sep.join(dirs + ['.tags']) 21 | if os.path.exists(joined) and not os.path.isdir(joined): 22 | return joined 23 | else: 24 | dirs.pop() 25 | 26 | return None 27 | 28 | 29 | def get_match(pattern, string, group_number): 30 | compiled_pattern = re.compile(pattern) 31 | match = re.search(compiled_pattern, string) 32 | return match.group(group_number) 33 | 34 | 35 | def get_list(text_command, pattern, group_number, split_flag): 36 | match_list = [] 37 | regions = text_command.view.find_all(pattern) 38 | for region in regions: 39 | if 'comment' in text_command.view.scope_name(region.begin()): 40 | continue 41 | line_string = text_command.view.substr(region) 42 | match_substring = get_match(pattern, line_string, group_number) 43 | if split_flag: 44 | port_list = match_substring.split(',') 45 | for each_port in port_list: 46 | match_list.append(each_port.strip()) 47 | else: 48 | if match_substring is not None: 49 | match_list.append(match_substring.strip()) 50 | else: 51 | match_list.append(match_substring) 52 | return match_list 53 | 54 | 55 | def find_insert_region(text_command, insert_pattern, insert_mark, search_start): 56 | insert_region = text_command.view.find(insert_pattern, search_start) 57 | if (insert_region is None and sublime_version == 2) or (insert_region.begin() == -1 and sublime_version == 3): 58 | sublime.status_message('Can not find the "' + insert_mark + '" mark !') 59 | raise Exception('Can not find the "' + insert_mark + '" mark !') 60 | return insert_region 61 | 62 | 63 | def check_file_ext(file_name): 64 | ext_name = os.path.splitext(file_name)[1] 65 | if ext_name != '.v' and ext_name != '.V': 66 | sublime.status_message( 67 | 'This file "' + file_name + '" is not a verilog file !') 68 | raise Exception( 69 | 'This file "' + file_name + '" is not a verilog file !') 70 | 71 | 72 | class AutoDefCommand(sublime_plugin.TextCommand): 73 | 74 | """auto add wire declaration for instances to connect""" 75 | 76 | def run(self, edit): 77 | file_name = self.view.file_name() 78 | check_file_ext(file_name) 79 | undefined_instance_port_dict = {} 80 | insert_pattern = r"/\*\bautodef\b\*/" 81 | insert_mark = "/*autodef*/" 82 | insert_region = find_insert_region( 83 | self, insert_pattern, insert_mark, 0) 84 | insert_point = insert_region.end() 85 | search_defined_pattern = r'^\s*(?:\b(?:input|wire|reg|signed)\b)\s*(?:\[\S+\s*:\s*\S+\])*\s*((\w+\s*[,]*\s*)*)' 86 | search_instance_pattern = r'^\s*(?:[.]\w+\s*\(\s*)(\w+)\s*(\[\s*\w+\s*[:]\s*\w+\s*\])*\)' 87 | instance_port_name_list = get_list(self, search_instance_pattern, 1, 0) 88 | instance_port_bitwidth_list = get_list( 89 | self, search_instance_pattern, 2, 0) 90 | list_length = len(instance_port_name_list) 91 | defined_list = get_list(self, search_defined_pattern, 1, 1) 92 | for i in range(list_length): 93 | if instance_port_name_list[i] in defined_list: 94 | continue 95 | else: 96 | undefined_instance_port_dict[instance_port_name_list[ 97 | i]] = instance_port_bitwidth_list[i] 98 | for key in undefined_instance_port_dict.keys(): 99 | insert_content = "\n//assign " + key + "=" 100 | self.view.insert(edit, insert_point, insert_content) 101 | for key in undefined_instance_port_dict.keys(): 102 | if undefined_instance_port_dict[key] is not None: 103 | insert_content = "\nwire " + \ 104 | undefined_instance_port_dict[key] + key + ";" 105 | else: 106 | insert_content = "\nwire " + key + ";" 107 | self.view.insert(edit, insert_point, insert_content) 108 | sublime.status_message( 109 | "Instance port-connections successfully generated !") 110 | 111 | 112 | class AutoPortCommand(sublime_plugin.TextCommand): 113 | 114 | """auto add module port to the current verilog module""" 115 | 116 | def insert_list(self, edit, list_to_insert, insert_point): 117 | range_list = list(range(len(list_to_insert))) 118 | range_list.reverse() 119 | for i in range_list: 120 | self.view.insert(edit, insert_point, list_to_insert[i]) 121 | self.view.insert(edit, insert_point, '\t\t\t') 122 | if i != 0: 123 | self.view.insert(edit, insert_point, ',\n') 124 | else: 125 | self.view.insert(edit, insert_point, '\n') 126 | 127 | def run(self, edit): 128 | file_name = self.view.file_name() 129 | check_file_ext(file_name) 130 | input_pattern = r'^\s*(?:\binput\b)\s*(?:wire|reg)*\s*(?:signed)*\s*(\[\S+\s*:\s*\S+\])*\s*((\w+\s*[,]*\s*)*)' 131 | output_pattern = r'^\s*(?:\boutput\b)\s*(?:wire|reg)*\s*(?:signed)*\s*(\[\S+\s*:\s*\S+\])*\s*((\w+\s*[,]*\s*)*)' 132 | inout_pattern = r'^\s*(?:\binout\b)\s*(?:wire|reg)*\s*(?:signed)*\s*(\[\S+\s*:\s*\S+\])*\s*((\w+\s*[,]*\s*)*)' 133 | insert_pattern = r"((?<=/\*\bautoport\b\*/)[\d\D]*?(?=\);))" 134 | insert_mark = r"/*autoport*/" 135 | insert_region = find_insert_region( 136 | self, insert_pattern, insert_mark, 0) 137 | insert_point = insert_region.begin() 138 | self.view.erase(edit, insert_region) 139 | input_list = get_list(self, input_pattern, 2, 1) 140 | output_list = get_list(self, output_pattern, 2, 1) 141 | inout_list = get_list(self, inout_pattern, 2, 1) 142 | if len(input_list) > 0: 143 | self.insert_list(edit, input_list, insert_point) 144 | self.view.insert(edit, insert_point, "\n//input") 145 | if len(output_list) > 0: 146 | if len(input_list) > 0: 147 | self.view.insert(edit, insert_point, ",") 148 | self.insert_list(edit, output_list, insert_point) 149 | self.view.insert(edit, insert_point, "\n//output") 150 | if len(inout_list) > 0: 151 | if len(input_list) > 0 or len(output_list) > 0: 152 | self.view.insert(edit, insert_point, ",") 153 | self.insert_list(edit, inout_list, insert_point) 154 | self.view.insert(edit, insert_point, "\n//inout") 155 | sublime.status_message("Module ports successfully generated !") 156 | 157 | 158 | class AutoInstCommand(sublime_plugin.TextCommand): 159 | 160 | """auto generate instance""" 161 | 162 | def get_module_file_handle(self, module_to_find, tag_handle, tag_file): 163 | found_module_flag = 0 164 | search_pattern = r"^[\d\D]*\bmodule\b\s*" + module_to_find + r"\b" 165 | compiled_search_pattern = re.compile(search_pattern) 166 | replaced_line = '' 167 | for line in tag_handle: 168 | if re.match(compiled_search_pattern, line): 169 | replaced_line = line.replace('\\', '/') 170 | found_module_flag = 1 171 | break 172 | if not found_module_flag: 173 | sublime.status_message( 174 | 'Can not find module "' + module_to_find + '" in the tag file !') 175 | raise Exception( 176 | 'Can not find module "' + module_to_find + '" in the tag file !') 177 | capture_module_file_pattern = r"^(?:\w+\s*)(\S+)" 178 | module_file_path = re.match( 179 | capture_module_file_pattern, replaced_line).group(1) 180 | tag_dirname = os.path.dirname(tag_file) 181 | module_file_os_path = os.path.normpath(module_file_path) 182 | module_file_os_name = os.path.join(tag_dirname, module_file_os_path) 183 | try: 184 | module_file_handle = open(module_file_os_name) 185 | return module_file_handle 186 | except IOError: 187 | sublime.status_message( 188 | 'Can not find module "' + module_to_find + '", the definition file does not exist !') 189 | raise Exception( 190 | 'Can not find module "' + module_to_find + '", the definition file does not exist !') 191 | 192 | def check_file_ext(self, file_name): 193 | ext_name = os.path.splitext(file_name)[1] 194 | if ext_name != '.v' and ext_name != '.V': 195 | sublime.status_message( 196 | 'This file "' + file_name + '" is not a verilog file !') 197 | raise Exception( 198 | 'This file "' + file_name + '" is not a verilog file !') 199 | 200 | def get_module_name(self, region): 201 | word_region = self.view.word(region.begin()) 202 | module_name = self.view.substr(word_region) 203 | # check the module name if valid 204 | if re.match('\w+', module_name) is None: 205 | sublime.status_message( 206 | "Invalid module name '" + module_name + "' selected !") 207 | raise Exception( 208 | "Invalid module name '" + module_name + "' selected !") 209 | else: 210 | return module_name 211 | 212 | def find_tag(self, file_name): 213 | tag_file = find_tags_relative_to(file_name) 214 | if tag_file: 215 | return tag_file 216 | else: 217 | sublime.status_message( 218 | "Can not find any tag file ! Please generate the tag file using Ctags !") 219 | raise Exception( 220 | 'Can not find any tag file ! Please generate the tag file using Ctags !') 221 | 222 | def check_if_commented(self, line, check_word): 223 | if '//' in line: 224 | if line.index('//') < line.index(check_word): 225 | return 1 226 | return 0 227 | 228 | def get_list(self, pattern, file_handle, module_name): 229 | bitwidth_list = [] 230 | port_list = [] 231 | scope_valid = 0 232 | compiled_pattern = re.compile(pattern) 233 | file_handle.seek(0) 234 | module_scope_start_pattern = r"\bmodule\b\s*\b" + module_name + r"\b" 235 | module_scope_end_pattern = r"\s*\bendmodule\b" 236 | 237 | for line in file_handle: 238 | module_scope_begin_match = re.search( 239 | module_scope_start_pattern, line) 240 | module_scope_end_match = re.search( 241 | module_scope_end_pattern, line) 242 | 243 | if module_scope_begin_match: 244 | if self.check_if_commented(line, 'module'): 245 | continue 246 | scope_valid = 1 247 | elif module_scope_end_match and scope_valid: 248 | if self.check_if_commented(line, 'endmodule'): 249 | continue 250 | scope_valid = 0 251 | break 252 | if scope_valid: 253 | match = re.search(compiled_pattern, line) 254 | if match: 255 | bitwidth_match = match.group(1) 256 | port_name_match = match.group(2) 257 | if self.check_if_commented(line, port_name_match): 258 | continue 259 | port_line_list = port_name_match.split(',') 260 | for each_port in port_line_list: 261 | port_list.append(each_port.strip()) 262 | bitwidth_list.append(bitwidth_match) 263 | return (bitwidth_list, port_list) 264 | 265 | def insert_list(self, edit, name_list_to_insert, bitwidth_list_to_insert, insert_point): 266 | range_list = list(range(len(name_list_to_insert))) 267 | range_list.reverse() 268 | for i in range_list: 269 | if bitwidth_list_to_insert[i] is not None: 270 | self.view.insert(edit, insert_point, '.' + name_list_to_insert[ 271 | i] + '(' + name_list_to_insert[i] + bitwidth_list_to_insert[i] + ')') 272 | else: 273 | self.view.insert(edit, insert_point, '.' + name_list_to_insert[ 274 | i] + '(' + name_list_to_insert[i] + ')') 275 | self.view.insert(edit, insert_point, '\t\t\t') 276 | if i != 0: 277 | self.view.insert(edit, insert_point, ',\n') 278 | else: 279 | self.view.insert(edit, insert_point, '\n') 280 | 281 | def run(self, edit): 282 | file_name = self.view.file_name() 283 | check_file_ext(file_name) 284 | self.find_tag(file_name) 285 | for region in self.view.sel(): 286 | module_to_find = self.get_module_name(region) 287 | tag_file = self.find_tag(file_name) 288 | tag_handle = open(tag_file) 289 | module_file_handle = self.get_module_file_handle( 290 | module_to_find, tag_handle, tag_file) 291 | input_pattern = r'(?:\binput\b\s*(?:reg|wire)*\s*(?:signed)*\s*)(\[\S+\s*:\s*\S+\])*\s*(([,]*\s*\w+\s*)+)' 292 | output_pattern = r'(?:\boutput\b\s*(?:reg|wire)*\s*(?:signed)*\s*)(\[\S+\s*:\s*\S+\])*\s*(([,]*\s*\w+\s*)+)' 293 | inout_pattern = r'(?:\binout\b\s*(?:reg|wire)*\s*(?:signed)*\s*)(\[\S+\s*:\s*\S+\])*\s*(([,]*\s*\w+\s*)+)' 294 | insert_pattern = r"((?<=/\*\bautoinst\b\*/)[\d\D]*?(?=\);))" 295 | insert_mark = r"/*autoinst*/" 296 | input_bitwidth_list, input_name_list = self.get_list( 297 | input_pattern, module_file_handle, module_to_find) 298 | output_bitwidth_list, output_name_list = self.get_list( 299 | output_pattern, module_file_handle, module_to_find) 300 | inout_bitwidth_list, inout_name_list = self.get_list( 301 | inout_pattern, module_file_handle, module_to_find) 302 | insert_region = find_insert_region( 303 | self, insert_pattern, insert_mark, region.begin()) 304 | insert_point = insert_region.begin() 305 | self.view.erase(edit, insert_region) 306 | 307 | if len(input_name_list) > 0: 308 | self.insert_list( 309 | edit, input_name_list, input_bitwidth_list, insert_point) 310 | if len(output_name_list) > 0: 311 | if len(input_name_list) > 0: 312 | self.view.insert(edit, insert_point, ",") 313 | self.insert_list( 314 | edit, output_name_list, output_bitwidth_list, insert_point) 315 | if len(inout_name_list) > 0: 316 | if len(input_name_list) > 0 or len(output_name_list) > 0: 317 | self.view.insert(edit, insert_point, ",") 318 | self.insert_list( 319 | edit, inout_name_list, inout_bitwidth_list, insert_point) 320 | sublime.status_message("Instance successfully generated!") 321 | tag_handle.close() 322 | module_file_handle.close() 323 | 324 | 325 | class AddHeaderCommand(sublime_plugin.TextCommand): 326 | 327 | """add file header for verilog code""" 328 | 329 | def run(self, edit): 330 | file_name = self.view.file_name() 331 | check_file_ext(file_name) 332 | file_name_without_path = os.path.split(file_name)[1] 333 | plugin_settings = sublime.load_settings( 334 | "Verilog Automatic.sublime-settings") 335 | author = plugin_settings.get("Author") 336 | company = plugin_settings.get("Company") 337 | email = plugin_settings.get("Email") 338 | current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) 339 | self.view.insert(edit, 0, "\n//" + "=" * 98 + "\n") 340 | self.view.insert(edit, 0, "\n//") 341 | self.view.insert(edit, 0, "\n//") 342 | self.view.insert(edit, 0, "\n// Description" + " " * 3 + ": ") 343 | self.view.insert(edit, 0, "\n//") 344 | if email: 345 | self.view.insert(edit, 0, "\n// Email" + " " * 9 + ": " + email) 346 | if company: 347 | self.view.insert( 348 | edit, 0, "\n// Company" + " " * 7 + ": " + company) 349 | if author: 350 | self.view.insert(edit, 0, "\n// Author" + " " * 8 + ": " + author) 351 | self.view.insert(edit, 0, "\n// Revision" + " " * 6 + ": ") 352 | self.view.insert(edit, 0, "\n// Last Modified : " + current_time) 353 | self.view.insert( 354 | edit, 0, "\n// Created On" + " " * 4 + ": " + current_time) 355 | self.view.insert( 356 | edit, 0, "\n// Filename" + " " * 6 + ": " + file_name_without_path) 357 | self.view.insert(edit, 0, "//" + "=" * 98) 358 | sublime.status_message("File header successfully added !") 359 | 360 | 361 | class ChangeModifyTimeCommand(sublime_plugin.TextCommand): 362 | 363 | """change the last modified time""" 364 | 365 | def run(self, edit): 366 | modify_time_pattern = r"(?<=^// Last Modified : )[\d\D]*?$" 367 | insert_region = self.view.find(modify_time_pattern, 0) 368 | if (insert_region is None and sublime_version == 2) or (insert_region.begin() == -1 and sublime_version == 3): 369 | return 370 | else: 371 | insert_point = insert_region.begin() 372 | self.view.erase(edit, insert_region) 373 | current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) 374 | self.view.insert(edit, insert_point, current_time) 375 | 376 | 377 | class LastModifyListener(sublime_plugin.EventListener): 378 | 379 | def on_pre_save(self, view): 380 | if ('Verilog' in view.settings().get('syntax') or 'SystemVerilog' in view.settings().get('syntax')) and view.is_dirty(): 381 | view.run_command("change_modify_time") 382 | -------------------------------------------------------------------------------- /Verilog Automatic.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "Author":"", 3 | "Company":"", 4 | "Email":"" 5 | } 6 | --------------------------------------------------------------------------------