def on_query_context(self, view, key, _operator, _operand, _matchall): if Settings.COMPONENT_DEBUG.event_viewer: print('{0} key = {1}.'.format( type(self).__name__ + '.on_query_context', key)) retval = None if key == 'haskell_autofix': retval = view.settings().get('autofix') elif key == 'auto_completion_popup': retval = Settings.PLUGIN.auto_completion_popup elif key == 'haskell_source': retval = Common.is_haskell_source(view) elif key == 'haskell_source_or_repl': retval = Common.is_haskell_source(view) or Common.is_haskell_repl( view) elif key == 'haskell_repl': retval = Common.is_haskell_repl(view) elif key == 'haskell_symbol_info': retval = Common.is_haskell_symbol_info(view) elif key == 'cabal_source': retval = Common.is_cabal_source(view) elif key == 'scanned_source': retval = self.is_scanned_source(view) elif key == 'in_project': retval = self.is_in_project(view) elif key == "is_module_completion" or key == "is_import_completion": # Completion context is the only branch here where a backend is needed. retval = False with self.backend_mgr: project_dir, project_name = Common.locate_cabal_project_from_view( view) region = view.sel()[0] if region.a == region.b: word_region = view.word(region) preline = Common.get_line_contents_before_region( view, word_region) preline += self.COMPLETION_CHARS[key] qsymbol = Common.get_qualified_symbol(preline) if qsymbol.module: mod_completions = self.autocompleter.get_current_module_completions( project_name, project_dir) if qsymbol.is_import_list: retval = qsymbol.module in mod_completions else: retval = [ m for m in mod_completions if m.startswith(qsymbol.module) ] != [] return retval
def on_selection_modified(self, view): if Common.is_haskell_source(view) and view.file_name(): srcfile = view.file_name() if SourceHaskellTypeCache().has( srcfile) and SourceHaskellTypeCache().shown(srcfile): view.run_command('sublime_haskell_show_all_types', {'filename': srcfile})
def on_hover(self, view, point, hover_zone): # Note: view.file_name() is not set in certain views, such as the "Haskell Show Types Panel". Avoid # generating lookup errors, which are logged in the console window (for better or worse.) if Common.is_haskell_source(view) and view.file_name(): # Ensure that we never block the Python main thread. info_pop = InfoPop.SublimeHaskellHoverPopup(view, view.file_name(), point, hover_zone) Utils.run_async('SublimeHaskellPopup.on_hover', info_pop.do_hover)
def activated_worker(): with self.backend_mgr: self.assoc_to_project(view, filename) project_name = Common.locate_cabal_project_from_view(view)[1] if Common.is_haskell_source(view): self.autocompleter.generate_completions_cache( project_name, filename)
def on_load(self, view): filename = view.file_name() if filename is None or not Common.is_inspected_source(view): return if Settings.COMPONENT_DEBUG.event_viewer: print('{0} is_inspected_source {1}.'.format( type(self).__name__ + ".on_load", filename)) self.assoc_to_project(view, filename) project_name = Common.locate_cabal_project_from_view(view)[1] self.rescan_source(project_name, filename) if Common.is_haskell_source(view): if Settings.COMPONENT_DEBUG.event_viewer: print('{0} is_haskell_source {1}.'.format( type(self).__name__ + ".on_load", filename)) view.settings().set('translate_tabs_to_spaces', True) if Settings.PLUGIN.use_improved_syntax: name = os.path.basename(filename.lower()) if Settings.PLUGIN.use_improved_syntax and ( name.endswith(".hs") or name.endswith(".hsc")): view.settings().set( 'syntax', 'Packages/SublimeHaskell/Syntaxes/Haskell-SublimeHaskell.tmLanguage' )
def get_projects(): if hsdev.agent_connected(): folders = sublime.active_window().folders() view_files = [ v.file_name() for v in sublime.active_window().views() if (Common.is_haskell_source(v) or Common.is_cabal_source(v)) and v.file_name() ] def npath(path): return os.path.normcase(os.path.normpath(path)) def childof(path, prefix): return npath(path).startswith(npath(prefix)) return dict((info['name'], info) for info in filter( lambda p: any([childof(p['path'], f) for f in folders]) or any( [childof(src, p['path']) for src in view_files]), ( hsdev.client.list_projects() or []))) else: folder_files = [src for f in sublime.active_window().folders() for src in Common.list_files_in_dir_recursively(f) \ if os.path.splitext(src)[1] in [".hs", ".cabal"] ] view_files = [ v.file_name() for v in sublime.active_window().views() if (Common.is_haskell_source(v) or Common.is_cabal_source(v)) and v.file_name() ] src_files = list( map(lambda p: os.path.normcase(os.path.normpath(p)), folder_files + view_files)) active_projects = [] while src_files: src = src_files.pop() proj_dir, proj_name = Common.get_cabal_project_dir_and_name_of_file( src) if proj_dir: active_projects.append((proj_name, proj_dir)) src_files = [ f for f in src_files if not f.startswith(proj_dir) ] return dict((name, { 'name': name, 'path': path }) for name, path in active_projects)
def on_modified(self, view): filename = view.file_name() if filename is None or not Common.is_haskell_source(view): return if Settings.COMPONENT_DEBUG.event_viewer: print('{0} invoked.'.format(type(self).__name__ + ".on_modified")) if Settings.PLUGIN.lint_check_fly: Utils.run_async('fly check', self.fly, view) self.type_cache.remove(filename)
def on_query_completions(self, view, prefix, locations): # Defer starting the backend until as late as possible... if Settings.COMPONENT_DEBUG.event_viewer: print('{0} invoked (prefix: {1}).'.format(type(self).__name__ + '.on_query_completions', prefix)) if not Common.is_haskell_source(view): return [] completions = None with self.backend_mgr: begin_time = time.clock() # Only suggest symbols if the current file is part of a Cabal project. filename = view.file_name() line_contents = Common.get_line_contents(view, locations[0]) project_name = Common.locate_cabal_project_from_view(view)[1] completion_flags = sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS curselector = view.scope_name(locations[0]) if self.LANGUAGE_RE.search(line_contents): completions = self.autocompleter.get_lang_completions(project_name) elif self.OPTIONS_GHC_RE.search(line_contents): completions = self.autocompleter.get_flag_completions(project_name) elif 'meta.import.haskell' in curselector: # Inside an import: Complete the imported module name: completions = self.autocompleter.get_import_completions(project_name, filename, locations, line_contents) elif 'meta.declaration.exports.haskell' in curselector: # Export list export_module = Autocomplete.EXPORT_MODULE_RE.search(line_contents) if export_module: # qsymbol = Common.get_qualified_symbol_at_region(view, view.sel()[0]) # TODO: Implement pass else: # Add current file's completions: completions = self.autocompleter.get_completions(view, locations) if not Settings.PLUGIN.inhibit_completions: completion_flags = 0 end_time = time.clock() Logging.log('time to get completions: {0} seconds'.format(end_time - begin_time), Logging.LOG_INFO) # Don't put completions with special characters (?, !, ==, etc.) # into completion because that wipes all default Sublime completions: # See http://www.sublimetext.com/forum/viewtopic.php?t=8659 # TODO: work around this # comp = [c for c in completions if NO_SPECIAL_CHARS_RE.match(c[0].split('\t')[0])] # if Settings.PLUGIN.inhibit_completions and len(comp) != 0: # return (comp, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS) # return comp return (completions, completion_flags) # if completions else []
def get_projects(self): folders = sublime.active_window().folders() view_files = [v.file_name() for v in sublime.active_window().views() if (Common.is_haskell_source(v) or Common.is_cabal_source(v)) and v.file_name()] def childof(path, prefix): return Utils.normalize_path(path).startswith(Utils.normalize_path(prefix)) def relevant_project(proj): return any([childof(proj['path'], f) for f in folders]) or any([childof(src, proj['path']) for src in view_files]) projects = BackendMgr.active_backend().list_projects() or [] return dict((info['name'], info) for info in projects if relevant_project(info))
def on_post_save(self, view): filename = view.file_name() if filename is not None and Common.is_inspected_source(view): if Settings.COMPONENT_DEBUG.event_viewer: print('{0} invoked.'.format(type(self).__name__ + ".on_post_save")) if Common.is_haskell_source(view): self.type_cache.remove(filename) self.trigger_build(view) if Settings.PLUGIN.prettify_on_save: if Settings.PLUGIN.prettify_executable == 'stylish-haskell': view.run_command('sublime_haskell_stylish') elif Settings.PLUGIN.prettify_executable == 'hindent': view.run_command('sublime_haskell_hindent') # Ensure that the source scan happens after trigger_build -- the inspector is active, so the SublimeHaskell # commands that we try to execute end up being disabled. project_name = Common.locate_cabal_project_from_view(view)[1] Utils.run_async('rescan source {0}/{1}'.format(project_name, filename), self.rescan_source, project_name, filename)
def is_visible(self): return Common.is_haskell_symbol_info(self.view) or \ Common.is_haskell_source(self.view) or \ Common.is_haskell_repl(self.view)
def on_modified(self, view): lint_check_fly = Settings.PLUGIN.lint_check_fly if lint_check_fly and Common.is_haskell_source( view) and view.file_name(): self.fly_agent.fly(view)
def on_hover(self, view, point, hover_zone): if not Common.is_haskell_source(view): return self.view = view self.current_file_name = self.view.file_name() # If the column is needed: (line, column) = self.view.rowcol(point) [remove subscript] line = self.view.rowcol(point)[0] self.decl = None self.typed_expr = None if hover_zone == sublime.HOVER_TEXT: qsymbol = Common.get_qualified_symbol_at_point(self.view, point) module_word = qsymbol.module ident = qsymbol.name if ident is None and module_word: # TODO: Any ideas for popup about module? pass if ident: self.whois_name = qsymbol.qualified_name() self.full_name = qsymbol.full_name() # Try get type of hovered symbol self.point = point self.typed_expr = None if types.FILE_TYPES.has(self.current_file_name): self.typed_expr = self.get_type( types.FILE_TYPES.get(self.current_file_name)) else: types.get_types(self.current_file_name, self.on_types) # Try whois self.suggest_import = False self.decl = Utils.head_of( hsdev.client.whois(self.whois_name, self.current_file_name)) if not self.decl: self.suggest_import = True self.decl = Utils.head_of( hsdev.client.lookup(self.full_name, self.current_file_name)) self.create_symbol_popup() elif hover_zone == sublime.HOVER_GUTTER: self.view = view self.current_file_name = self.view.file_name() errs = list( filter(lambda e: e.region.start.line == line, parseoutput.errors_for_view(self.view))) if errs: popup_parts = [ SUBHASK_STYLES.gen_style( self.view.settings().get('color_scheme')) ] for err in errs: msg = UnicodeOpers.use_unicode_operators( symbols.escape_text(err.message)) # Decorate first word with style decors = { 'Error': 'error', 'Warning': 'warning', 'Hint': 'hint' } for dec, dec_style in decors.items(): msg = msg.replace( dec, u'<span class="{0}">{1}</span>'.format( dec_style, dec)) popup_parts.append(u'<p>{0}</p>'.format(msg)) if err.correction is not None: popup_parts.append(err.correction.popup()) popup_text = u''.join(popup_parts) self.view.show_popup(popup_text, sublime.HIDE_ON_MOUSE_MOVE_AWAY, point, 600, 600, self.on_navigate, self.on_hide)
def is_visible(self): return Common.is_haskell_source(self.view) and super().is_visible()
def is_enabled(self): return Common.is_haskell_source( self.view) and self.view.file_name() is not None
def is_enabled(self): return Common.is_haskell_source(self.view) and \ self.view.file_name() is not None and \ FILE_TYPES.has(self.view.file_name()) and \ FILE_TYPES.shown(self.view.file_name())
def is_enabled(self): return Common.is_haskell_source(self.view) or Common.is_haskell_repl(self.view) or \ (Common.is_haskell_symbol_info(self.view) and self.view.settings().get('location'))
def is_enabled(self): return Common.is_haskell_source(self.view) and \ self.view.file_name() is not None and \ SourceHaskellTypeCache().has(self.view.file_name()) and \ SourceHaskellTypeCache().shown(self.view.file_name())
def on_selection_modified(self, view): if TOGGLE_SYMBOL_INFO and Common.is_haskell_source(view) and view.file_name(): view.run_command('sublime_haskell_symbol_info', {'no_browse': True})
def is_visible(self): return Common.is_haskell_source(self.view) or Common.is_haskell_repl(self.view)
def on_selection_modified(self, view): if Common.is_haskell_source(view) and \ view.file_name() and FILE_TYPES.has(view.file_name()) and \ FILE_TYPES.shown(view.file_name()): view.run_command('sublime_haskell_show_all_types', {'filename': view.file_name()})
def is_enabled(self): return (self.view.settings().get('package') is not None) or \ Common.is_haskell_source(self.view) or \ Common.is_haskell_repl(self.view)
def is_enabled(self): return Common.is_haskell_source(None)