Skip to content

Commit 5e164be

Browse files
authored
Merge pull request #83 from qkdreyer/fix-70
Fixes #70
2 parents 44f9038 + 61b25f5 commit 5e164be

2 files changed

Lines changed: 196 additions & 76 deletions

File tree

FileHeader.py

Lines changed: 174 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# -*- coding: utf-8 -*-
22
# @Author: Lime
33
# @Date: 2013-10-28 13:39:48
4-
# @Last Modified by: Lime
5-
# @Last Modified time: 2016-03-06 10:23:52
4+
# @Last Modified by: qkdreyer
5+
# @Last Modified time: 2017-08-14 16:48:32
66

77
import os
88
import sys
@@ -28,6 +28,66 @@
2828
BODY_PATH = os.path.join(PLUGIN_PATH, 'template/body')
2929
INSTALLED_PLGIN_PATH = os.path.abspath(os.path.dirname(__file__))
3030

31+
FILE_SUFFIX_MAPPING = {
32+
"as": "ActionScript",
33+
"scpt": "AppleScript",
34+
"asp": "ASP",
35+
"aspx": "ASP",
36+
"bat": "Batch File",
37+
"cmd": "Batch File",
38+
"c": "C",
39+
"cs": "C#",
40+
"cpp": "C++",
41+
"clj": "Clojure",
42+
"css": "CSS",
43+
"D": "D",
44+
"erl": "Erlang",
45+
"go": "Go",
46+
"groovy": "Groovy",
47+
"hs": "Haskell",
48+
"htm": "HTML",
49+
"html": "HTML",
50+
"java": "Java",
51+
"js": "JavaScript",
52+
"tex": "LaTeX",
53+
"lsp": "Lisp",
54+
"lua": "Lua",
55+
"md": "Markdown",
56+
"mat": "Matlab",
57+
"m": "Objective-C",
58+
"ml": "OCaml",
59+
"p": "Pascal",
60+
"pl": "Perl",
61+
"php": "PHP",
62+
"py": "Python",
63+
"R": "R",
64+
"rst": "RestructuredText",
65+
"rb": "Ruby",
66+
"scala": "Scala",
67+
"scss": "SCSS",
68+
"sh": "ShellScript",
69+
"sql": "SQL",
70+
"tcl": "TCL",
71+
"txt": "Text",
72+
"xml": "XML"
73+
}
74+
75+
HEADER_PREFIX_MAPPING = {
76+
"PHP": "<?php\n\n"
77+
}
78+
79+
EXTENSION_EQUIVALENCE = {
80+
"blade.php": "html"
81+
}
82+
83+
LANGUAGE_SYNTAX_MAPPING = {
84+
'Graphviz': 'DOT',
85+
'RestructuredText': 'reStructuredText',
86+
'ShellScript': 'Shell-Unix-Generic',
87+
'TCL': 'Tcl',
88+
'Text': 'Plain text'
89+
}
90+
3191
IS_ST3 = sublime.version() >= '3'
3292

3393
sys.path.insert(0, PLUGIN_PATH)
@@ -85,6 +145,12 @@ def getOutputError(cmd):
85145
stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate())
86146

87147

148+
def View():
149+
'''Get current active window view'''
150+
151+
return Window().active_view()
152+
153+
88154
def Window():
89155
'''Get current active window'''
90156

@@ -160,7 +226,7 @@ def get_user():
160226
def get_project_name():
161227
'''Get project name'''
162228

163-
project_data = sublime.active_window().project_data()
229+
project_data = Window().project_data()
164230
project = os.path.basename(
165231
project_data['folders'][0]['path']) if project_data else None
166232

@@ -170,7 +236,7 @@ def get_project_name():
170236
def get_dir_path():
171237
'''Get current file dir path'''
172238

173-
view, path = Window().active_view(), None
239+
view, path = View(), None
174240
if view:
175241
file_name = view.file_name()
176242
if file_name is not None:
@@ -285,8 +351,10 @@ def get_syntax_type(name):
285351
'''Judge `syntax_type` according to to `name`'''
286352

287353
syntax_type = Settings().get('syntax_when_not_match')
288-
file_suffix_mapping = Settings().get('file_suffix_mapping')
289-
extension_equivalence = Settings().get('extension_equivalence')
354+
file_suffix_mapping = merge_defaults_with_settings(
355+
FILE_SUFFIX_MAPPING, 'file_suffix_mapping')
356+
extension_equivalence = merge_defaults_with_settings(
357+
EXTENSION_EQUIVALENCE, 'extension_equivalence')
290358

291359
if name is not None:
292360
name = name.split('.')
@@ -312,19 +380,69 @@ def get_syntax_type(name):
312380
def get_syntax_file(syntax_type):
313381
'''Get syntax file path'''
314382

315-
lang2tmL = {
316-
'Graphviz': 'DOT',
317-
'RestructuredText': 'reStructuredText',
318-
'ShellScript': 'Shell-Unix-Generic',
319-
'TCL': 'Tcl',
320-
'Text': 'Plain text',
321-
}
322-
383+
# weird workaround
323384
if syntax_type == 'C':
324385
syntax_type = 'C++'
325386

387+
lang2tmL = merge_defaults_with_settings(
388+
LANGUAGE_SYNTAX_MAPPING, 'language_syntax_mapping')
326389
tmL = lang2tmL.get(syntax_type, syntax_type)
327-
return 'Packages/%s/%s.tmLanguage' % (syntax_type, tmL)
390+
391+
if not '.' in tmL:
392+
tmL += '.tmLanguage'
393+
394+
return 'Packages/%s/%s' % (syntax_type, tmL)
395+
396+
397+
def get_content_index(haystack, needle):
398+
'''Get the right needle position in haystack'''
399+
pos = haystack.find(needle)
400+
return pos + len(needle) if pos >= 0 else 0
401+
402+
403+
def get_header_prefix(syntax_type, default=''):
404+
'''Get the header prefix'''
405+
header_prefix_mapping = merge_defaults_with_settings(
406+
HEADER_PREFIX_MAPPING, 'header_prefix_mapping')
407+
try:
408+
return header_prefix_mapping.get(syntax_type, default)
409+
except KeyError:
410+
return default
411+
412+
413+
def get_header_content(syntax_type, path=None, file=None):
414+
'''Get the correctly computed header content'''
415+
header_prefix = get_header_prefix(syntax_type)
416+
content = '' if isinstance(
417+
file, str) and header_prefix in file else header_prefix
418+
return content + render_template(syntax_type, 'header', {'path': path})
419+
420+
421+
def get_file_content(file, syntax_type, header):
422+
'''Get the correctly computed file content'''
423+
header_prefix = get_header_prefix(syntax_type)
424+
file_index = get_content_index(file, header_prefix)
425+
return file[0:file_index] + header + file[file_index:]
426+
427+
428+
def template_header_exists(file, syntax_type):
429+
'''Return whether template header has been compiled in file'''
430+
template_header = get_template_part(syntax_type, 'header').strip()
431+
regex = r'\\{\\{[a-z\\_]+\\}\\}'
432+
return re.search(re.sub(regex, '.*', re.escape(template_header)), file)
433+
434+
435+
def merge_dicts(*dicts):
436+
'''Merge any number of dicts into a new dict'''
437+
result = {}
438+
for dict in dicts:
439+
result.update(dict)
440+
return result
441+
442+
443+
def merge_defaults_with_settings(default, setting_name):
444+
'''Merge default dict with package settings'''
445+
return merge_dicts(default, Settings().get(setting_name, {}))
328446

329447

330448
def block(view, callback, *args, **kwargs):
@@ -347,7 +465,7 @@ def new_file(self, path, syntax_type):
347465
sublime.error_message('File exists!')
348466
return
349467

350-
header = render_template(syntax_type, options={'path': path})
468+
header = get_header_content(syntax_type, path)
351469

352470
try:
353471
with open(path, 'w+') as f:
@@ -357,18 +475,19 @@ def new_file(self, path, syntax_type):
357475
sublime.error_message(str(e))
358476
return
359477

360-
new_file = Window().open_file(path)
478+
view = Window().open_file(path)
479+
file_syntax = get_syntax_file(syntax_type)
361480

362-
try:
363-
block(new_file,
364-
new_file.set_syntax_file, get_syntax_file(syntax_type))
365-
except:
366-
pass
481+
if os.path.exists(file_syntax) and os.path.isfile(file_syntax):
482+
try:
483+
block(view, view.set_syntax_file, file_syntax)
484+
except:
485+
pass
367486

368-
block(new_file, new_file.show, 0)
487+
block(view, view.show, 0)
369488

370489
def new_view(self, syntax_type, name):
371-
header = render_template(syntax_type)
490+
header = get_header_content(syntax_type)
372491
new_file = Window().new_file()
373492
new_file.set_name(name)
374493
new_file.run_command('insert', {'characters': header})
@@ -422,14 +541,17 @@ def __init__(self, path):
422541

423542
def run(self):
424543
syntax_type = get_syntax_type(self.path)
425-
header = render_template(syntax_type, 'header', {'path': self.path})
426544

427545
try:
428546
with open(self.path, 'r') as f:
429-
contents = header + f.read()
547+
file = f.read()
430548

431-
with open(self.path, 'w') as f:
432-
f.write(contents)
549+
if not template_header_exists(file, syntax_type):
550+
header_content = get_header_content(
551+
syntax_type, self.path, file)
552+
contents = get_file_content(file, syntax_type, header_content)
553+
with open(self.path, 'w') as f:
554+
f.write(contents)
433555

434556
except Exception as e:
435557
sublime.error_message(str(e))
@@ -448,8 +570,15 @@ def run(self, edit, path, part=None):
448570
c_time = pickle.loads(str(c_time))
449571
options.update({'c_time': c_time})
450572

451-
header = render_template(syntax_type, part, options)
452-
self.view.insert(edit, 0, header)
573+
view = View()
574+
view_content = view.substr(sublime.Region(0, view.size()))
575+
576+
if not template_header_exists(view_content, syntax_type):
577+
header_content = get_header_content(
578+
syntax_type, path, view_content)
579+
header_prefix = get_header_prefix(syntax_type)
580+
view_index = get_content_index(view_content, header_prefix)
581+
self.view.insert(edit, view_index, header_content)
453582

454583

455584
class FileHeaderAddHeaderCommand(sublime_plugin.WindowCommand):
@@ -509,7 +638,6 @@ def add(self, path):
509638

510639
whether_open_file = Settings().get(
511640
'open_file_when_add_header_to_directory')
512-
513641
if whether_open_file:
514642
modified_file = Window().open_file(path)
515643
block(modified_file, modified_file.run_command,
@@ -548,7 +676,7 @@ def run(self, paths=[]):
548676
initial_text = os.path.abspath(paths[0])
549677
else:
550678
try:
551-
initial_text = Window().active_view().file_name()
679+
initial_text = View().file_name() or 'untitled'
552680
except:
553681
pass
554682

@@ -672,8 +800,21 @@ def on_text_command(self, view, command_name, args):
672800
view.run_command('undo')
673801

674802
def on_pre_save(self, view):
803+
enable_add_template_on_save = Settings().get(
804+
'enable_add_template_on_save', False)
805+
file_name = view.file_name()
806+
807+
if isinstance(enable_add_template_on_save, str):
808+
search = re.search(enable_add_template_on_save, file_name)
809+
enable_add_template_on_save = search != None
810+
811+
if enable_add_template_on_save:
812+
block(view, view.run_command,
813+
'add_file_header', {'path': file_name})
814+
675815
if view.id() in FileHeaderListener.new_view_id:
676-
self.insert_template(view, False)
816+
if not enable_add_template_on_save:
817+
self.insert_template(view, False)
677818
index = FileHeaderListener.new_view_id.index(view.id())
678819
del FileHeaderListener.new_view_id[index]
679820
else:

0 commit comments

Comments
 (0)