Skip to content

Commit

Permalink
Merge andruhon's fork to fix autocompletion bug alienhard#18
Browse files Browse the repository at this point in the history
  • Loading branch information
petermac- committed Mar 8, 2015
2 parents c1cf033 + b1d19a1 commit f8ba974
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 59 deletions.
34 changes: 34 additions & 0 deletions Main.sublime-menu
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[
{
"caption": "Preferences",
"mnemonic": "n",
"id": "preferences",
"children":
[
{
"caption": "Package Settings",
"mnemonic": "P",
"id": "package-settings",
"children":
[
{
"caption": "SublimeAllAutocomplete",
"children":
[
{
"command": "open_file",
"args": {"file": "${packages}/SublimeAllAutocomplete/SublimeAllAutocomplete.sublime-settings"},
"caption": "Settings – Default"
},
{
"command": "open_file",
"args": {"file": "${packages}/User/SublimeAllAutocomplete.sublime-settings"},
"caption": "Settings – User"
}
]
}
]
}
]
}
]
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,42 @@ Extends the default autocomplete to find matches in all open files.

By default Sublime only considers words found in the current file.

This is a fork of https://github.com/alienhard/SublimeAllAutocomplete/

This fork includes hack to fix SASS and CSS dash bug
https://github.com/alienhard/SublimeAllAutocomplete/issues/18/
http://sublimetext.userecho.com/topic/222861-/


Install
-------

If you have Package Control installed in Sublime just press ctrl+shift+p (Windows, Linux) or cmd+shift+p (OS X) to open the Command Pallete.
Start typing 'install' to select 'Package Control: Install Package', then search for AllAutocomplete and select it. That's it.

start typing "Package Control: Add Repository", press Enter and insert
https://github.com/andruhon/SublimeAllAutocomplete
press Enter, start typing "Package Control: Install Package", press Enter, start typing
"All Autocomplete" and select one with "https://github.com/andruhon/SublimeAllAutocomplete" URL

You can also install this package manually by entering the Packages directory of Sublime Text 2/3 and issuing on a terminal:

git clone https://github.com/alienhard/SublimeAllAutocomplete
git clone https://github.com/andruhon/SublimeAllAutocomplete


Configure
---------

Available options (with default values):
{
"apply_with_dash_hack_syntaxes": ["source.sass","source.css"],
"return_nothing_on_empty_prefix": true,
"do_not_search_in_current_view": false
}

You can override this settings in user AllAutocomplete.sublime-settings (preferences->package settings->SublimeAllAutoComplete->Settings-User)

You can also remove dash from "word_separators" option in syntax specific settings for CSS or SASS if you want to see all suggestions,
not only after pressing next dash. (Settings-More->Syntax Specific-User, when file of particular syntax is open)


LICENSE
Expand Down
192 changes: 135 additions & 57 deletions SublimeAllAutocomplete.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,81 +14,159 @@
MAX_WORDS_PER_VIEW = 100
MAX_FIX_TIME_SECS_PER_VIEW = 0.01

class AllAutocomplete(sublime_plugin.EventListener):
#Change this variable to True to se debug output
DEBUG = False

class SubLimeallautocomplete(sublime_plugin.EventListener):
#default settings
dash_hack_sytaxes = ["source.scss","source.sass","source.css"]
return_nothing_on_empty = True
not_search_in_current = True

def __init__(self):
if DEBUG: print("initializing Sublimeallautocomplete(SAA) plugin")

#Loading settings when view is activated
def on_activated(self,view):
if DEBUG: print("\nActivating SAA for view",view)
self.plugin_settings = sublime.load_settings('SublimeAllAutocomplete.sublime-settings')

dash_hack_sytaxes = self.plugin_settings.get('apply_with_dash_hack_syntaxes')
return_nothing_on_empty = self.plugin_settings.get('return_nothing_on_empty_prefix')
not_search_in_current = self.plugin_settings.get('do_not_search_in_current_view')
if DEBUG: print("SAA: user settings:\n dash_hack_sytaxes:{0}\n return_nothing_on_empty:{1}\n not_search_in_current:{2}".format(dash_hack_sytaxes,return_nothing_on_empty,not_search_in_current))

#using default settings
if dash_hack_sytaxes != None:
self.dash_hack_sytaxes = dash_hack_sytaxes

if return_nothing_on_empty != None:
self.return_nothing_on_empty = return_nothing_on_empty

if not_search_in_current != None:
self.not_search_in_current = not_search_in_current

if DEBUG: print("SAA: Merged settings:\n dash_hack_sytaxes:{0}\n return_nothing_on_empty:{1}\n not_search_in_current:{2}\n".format(self.dash_hack_sytaxes,self.return_nothing_on_empty,self.not_search_in_current))

def on_query_completions(self, view, prefix, locations):

if DEBUG: print("SAA: running completion query '{0}'".format(prefix))
words = []

# Limit number of views but always include the active view. This
# view goes first to prioritize matches close to cursor position.
other_views = [v for v in sublime.active_window().views() if v.id != view.id]
views = [view] + other_views
views = views[0:MAX_VIEWS]
if DEBUG: print("SAA: views to process {0}".format(views))

if self.return_nothing_on_empty:
if not prefix:
if DEBUG: print("SAA: returning nothing on empty query")
return words;

for v in views:
view_words = []
location = 0
# Hacking around dash auto-completion bug
# https://github.com/alienhard/Sublimeallautocomplete/issues/18

# Sublime probably already works fine with suggestions from current view
if self.not_search_in_current and v.id == view.id:
continue

if len(locations) > 0 and v.id == view.id:
view_words = v.extract_completions(prefix, locations[0])
location = locations[0]

if self.is_need_to_be_hacked(v, self.dash_hack_sytaxes):
# apply hack for css and sass only
view_words = self.extract_completions_wdash(v,prefix);
else:
view_words = v.extract_completions(prefix)
view_words = filter_words(view_words)
view_words = fix_truncation(v, view_words)
view_words = v.extract_completions(prefix, location)

view_words = self.filter_words(view_words)
view_words = self.fix_truncation(v, view_words)
words += view_words

words = without_duplicates(words)
words = self.without_duplicates(words)
if DEBUG: print("SAA: {0} words found".format(len(words)))

matches = [(w, w.replace('$', '\\$')) for w in words]
return matches

def filter_words(words):
words = words[0:MAX_WORDS_PER_VIEW]
return [w for w in words if MIN_WORD_SIZE <= len(w) <= MAX_WORD_SIZE]

# keeps first instance of every word and retains the original order
# (n^2 but should not be a problem as len(words) <= MAX_VIEWS*MAX_WORDS_PER_VIEW)
def without_duplicates(words):
result = []
for w in words:
if w not in result:
result.append(w)
return result


# Ugly workaround for truncation bug in Sublime when using view.extract_completions()
# in some types of files.
def fix_truncation(view, words):
fixed_words = []
start_time = time.time()

for i, w in enumerate(words):
#The word is truncated if and only if it cannot be found with a word boundary before and after

# this fails to match strings with trailing non-alpha chars, like
# 'foo?' or 'bar!', which are common for instance in Ruby.
match = view.find(r'\b' + re.escape(w) + r'\b', 0)
truncated = is_empty_match(match)
if truncated:
#Truncation is always by a single character, so we extend the word by one word character before a word boundary
extended_words = []
view.find_all(r'\b' + re.escape(w) + r'\w\b', 0, "$0", extended_words)
if len(extended_words) > 0:
fixed_words += extended_words
def is_need_to_be_hacked(self, v, dash_hack_sytaxes):
for syntax in dash_hack_sytaxes:
if v.scope_name(0).find(syntax) >= 0:
return True
return False

# extract auto-completions with dash
# see https://github.com/alienhard/Sublimeallautocomplete/issues/18
def extract_completions_wdash(self, v,prefix):
if DEBUG: print("SAA: extracting words with dashes")
word_regions = v.find_all(prefix,0)
words = []

for wr in word_regions:
word = v.substr(v.word(wr))
words.append(word)

if DEBUG: print("SAA: {0} dash-words found".format(len(words)))

return words

def filter_words(self, words):
words = words[0:MAX_WORDS_PER_VIEW]
return [w for w in words if MIN_WORD_SIZE <= len(w) <= MAX_WORD_SIZE]

# keeps first instance of every word and retains the original order
# (n^2 but should not be a problem as len(words) <= MAX_VIEWS*MAX_WORDS_PER_VIEW)
def without_duplicates(self, words):
if DEBUG: print("SAA: cleaning duplicates")
result = []
for w in words:
if w not in result:
result.append(w)
return result


# Ugly workaround for truncation bug in Sublime when using view.extract_completions()
# in some types of files.
def fix_truncation(self, view, words):
if DEBUG: print("SAA: fixing turncation")
fixed_words = []
start_time = time.time()

for i, w in enumerate(words):
#The word is truncated if and only if it cannot be found with a word boundary before and after

# this fails to match strings with trailing non-alpha chars, like
# 'foo?' or 'bar!', which are common for instance in Ruby.
match = view.find(r'\b' + re.escape(w) + r'\b', 0)
truncated = self.is_empty_match(match)
if truncated:
#Truncation is always by a single character, so we extend the word by one word character before a word boundary
extended_words = []
view.find_all(r'\b' + re.escape(w) + r'\w\b', 0, "$0", extended_words)
if len(extended_words) > 0:
fixed_words += extended_words
else:
# to compensate for the missing match problem mentioned above, just
# use the old word if we didn't find any extended matches
fixed_words.append(w)
else:
# to compensate for the missing match problem mentioned above, just
# use the old word if we didn't find any extended matches
#Pass through non-truncated words
fixed_words.append(w)

# if too much time is spent in here, bail out,
# and don't bother fixing the remaining words
if time.time() - start_time > MAX_FIX_TIME_SECS_PER_VIEW:
return fixed_words + words[i+1:]

return fixed_words

def is_empty_match(self, match):
if sublime.version() >= '3000':
return match.empty()
else:
#Pass through non-truncated words
fixed_words.append(w)

# if too much time is spent in here, bail out,
# and don't bother fixing the remaining words
if time.time() - start_time > MAX_FIX_TIME_SECS_PER_VIEW:
return fixed_words + words[i+1:]

return fixed_words

if sublime.version() >= '3000':
def is_empty_match(match):
return match.empty()
else:
def is_empty_match(match):
return match is None
return match is None
5 changes: 5 additions & 0 deletions SublimeAllAutocomplete.sublime-settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"apply_with_dash_hack_syntaxes": ["source.scss","source.sass","source.css"],
"return_nothing_on_empty_prefix": true,
"do_not_search_in_current_view": false
}

0 comments on commit f8ba974

Please sign in to comment.