Skip to content

Commit

Permalink
-strip out comments if some tried to add them to favorite_files.json
Browse files Browse the repository at this point in the history
-be forgiving of trailing commas in favorite_files.json
-autoload favorite_files.json if it has been detetected as modified
-Fix issue where canceling opening a file or canceling removing an entry, the event stil occurs
  • Loading branch information
facelessuser committed Mar 20, 2012
1 parent d92bdff commit 9d2625d
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 18 deletions.
40 changes: 22 additions & 18 deletions favorite_files.py
Expand Up @@ -6,17 +6,22 @@

import sublime
import sublime_plugin
from os.path import join, exists, normpath, basename
from os.path import join, exists, normpath, basename, getmtime
import json
from time import time
import sys

# Pull in included modules
lib = join(sublime.packages_path(), 'FavoriteFiles')
if not lib in sys.path:
sys.path.append(lib)
from lib.comments.json import sanitize_json

FILES = join(sublime.packages_path(), 'User', 'favorite_files.json')


class FileList:
files = {}
last_access = 0
max_time = 600

@classmethod
def get(cls, s):
Expand All @@ -38,10 +43,6 @@ def remove(cls, s):
if cls.exists(s):
del cls.files[s]

@classmethod
def load(cls):
cls.last_access = time()

@classmethod
def keys(cls):
return [x for x in cls.files]
Expand All @@ -54,7 +55,7 @@ def create_favorite_list(l, force=False):
j = json.dumps(l, sort_keys=True, indent=4, separators=(',', ': '))
with open(FILES, 'w') as f:
f.write(j + "\n")
FileList.last_access = time()
FileList.last_access = getmtime(FILES)
except:
sublime.error_message('Failed to create favorite_files.json!')
errors = True
Expand All @@ -66,12 +67,13 @@ def load_favorite_files(force=False):
if not exists(FILES):
if create_favorite_list({}, True):
errors = True
if not errors and (force or time() - FileList.last_access > FileList.max_time):
if not errors and (force or getmtime(FILES) != FileList.last_access):
try:
with open(FILES, "r") as f:
content = f.read()
# Allow C style comments and be forgiving of trailing commas
content = sanitize_json(f.read(), True)
file_list = json.loads(content)
FileList.last_access = time()
FileList.last_access = getmtime(FILES)
FileList.files = file_list
except:
errors = True
Expand All @@ -81,9 +83,10 @@ def load_favorite_files(force=False):

class SelectFavoriteFileCommand(sublime_plugin.WindowCommand):
def open_file(self, value):
f = FileList.get(self.files[value])
if f != None:
self.window.open_file(f)
if value >= 0:
f = FileList.get(self.files[value])
if f != None:
self.window.open_file(f)

def run(self):
if not load_favorite_files():
Expand Down Expand Up @@ -143,10 +146,11 @@ def run(self):

class RemoveFavoriteFileCommand(sublime_plugin.WindowCommand):
def remove(self, value):
key = self.files[value]
if FileList.exists(key):
FileList.remove(key)
create_favorite_list(FileList.files, True)
if value >= 0:
key = self.files[value]
if FileList.exists(key):
FileList.remove(key)
create_favorite_list(FileList.files, True)

def run(self):
if not load_favorite_files():
Expand Down
Empty file added lib/__init__.py
Empty file.
Empty file added lib/comments/__init__.py
Empty file.
66 changes: 66 additions & 0 deletions lib/comments/comments.py
@@ -0,0 +1,66 @@
'''
Favorite Files
Licensed under MIT
Copyright (c) 2012 Isaac Muse <isaacmuse@gmail.com>
'''

import re

# Comment types: lambda stripping function
comment_styles = {
"c": lambda text, save_newlines=True: strip_comments_by_regex(
# First group comments, second group non comments
r"""(/\*[^*]*\*+(?:[^/*][^*]*\*+)*/|\s*//(?:[^\r\n])*)|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|.[^/"']*)""",
text, save_newlines
),
"python": lambda text, save_newlines: strip_comments_by_regex(
# First group comments, second group non comments
r"""(\s*#(?:[^\r\n])*)|("{3}(?:\\.|[^\\])*"{3}|'{3}(?:\\.|[^\\])*'{3}|"(?:\\.|[^"\\])*"|'(?:\\.|[^'])*'|.[^#"']*)""",
text, save_newlines
)
}

# Additional styles that use the same style as others
comment_map = {
"json": "c", # Comments are not officially in the JSON spec, but if you strip them, you can use them
"trex": "c",
"cpp": "c"
}


def strip_comments_by_regex(expression, text, spare_newlines=False):
# If you want to remove comments, but keep the exact line_numbers
def filter_comments(group, spare_newlines=False):
if spare_newlines:
regex = re.compile(r"\r?\n", re.MULTILINE)
return ''.join([x[0] for x in regex.findall(group)])
else:
return ''

return (
''.join(
map(
lambda m: m.group(2) if m.group(2) else filter_comments(m.group(1), spare_newlines),
re.compile(expression, re.MULTILINE | re.DOTALL).finditer(text)
)
)
)


def strip_comments(style, text, save_newlines=False):
s = style.lower()
func = None

# Try to find specified comment, return none if cannot find
if s in comment_styles:
func = comment_styles[s]
# Look for alternate mappings for existing remove functions
elif s in comment_map:
if comment_map[s] in comment_styles:
func = comment_styles[comment_map[s]]

# Exit if no suitable function could be found
if func == None:
return None

return func(text, save_newlines)
45 changes: 45 additions & 0 deletions lib/comments/json.py
@@ -0,0 +1,45 @@
'''
Favorite Files
Licensed under MIT
Copyright (c) 2012 Isaac Muse <isaacmuse@gmail.com>
'''

import re
import comments


def strip_dangling_comments(text, save_newlines=False):
regex = re.compile(
# ([1st group] dangling commas) | ([8th group] everything else)
r"""((,([\s\r\n]*)(\]))|(,([\s\r\n]*)(\})))|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|.[^,"']*)""",
re.MULTILINE | re.DOTALL
)

def remove_comma(m, spare_newlines=False):
if spare_newlines:
if m.group(2):
# ,] -> ]
return m.group(3) + m.group(4)
else:
# ,} -> }
return m.group(6) + m.group(7)
else:
# ,] -> ] else ,} -> }
return m.group(4) if m.group(2) else m.group(7)

return (
''.join(
map(
lambda m: m.group(8) if m.group(8) else remove_comma(m, save_newlines),
regex.finditer(text)
)
)
)


def strip_comments(text, save_newlines):
return strip_comments('json', text, save_newlines)


def sanitize_json(text, save_newlines=False):
return strip_dangling_comments(comments.strip_comments('json', text, save_newlines), save_newlines)

0 comments on commit 9d2625d

Please sign in to comment.