示例#1
0
    def init_ghcmod_completions(self):
        # Init LANGUAGE completions
        self.language_completions = call_ghcmod_and_wait(['lang']).split('\n')
        log("Reading LANGUAGE completions from ghc-mod")

        # Init import module completion
        self.module_completions = call_ghcmod_and_wait(['list']).split('\n')
示例#2
0
 def run(self):
     while True:
         name, fn, args, kwargs = self.jobs.get()
         try:
             fn(*args, **kwargs)
         except Exception as e:
             log('worker: job {0} fails with {1}'.format(name, e), log_debug)
示例#3
0
 def run(self):
     while True:
         name, fn, args, kwargs = self.jobs.get()
         try:
             fn(*args, **kwargs)
         except Exception as e:
             log('worker: job {0} fails with {1}'.format(name, e),
                 log_debug)
示例#4
0
 def _refresh_all_module_info(self, cabal_dir):
     "Rebuild module information for all files under the specified directory."
     begin_time = time.clock()
     log('reinspecting project ({0})'.format(cabal_dir))
     # Process all files within the Cabal project:
     # TODO: Only process files within the .cabal file's "src" directory.
     files_in_dir = list_files_in_dir_recursively(cabal_dir)
     haskell_source_files = [x for x in files_in_dir if x.endswith('.hs')]
     for filename in haskell_source_files:
         self._refresh_module_info(filename)
     end_time = time.clock()
     log('total inspection time: {0} seconds'.format(end_time - begin_time))
示例#5
0
def mark_errors_in_views(errors):
    "Mark the regions in open views where errors were found."
    begin_time = time.clock()
    # Mark each diagnostic in each open view in all windows:
    for w in sublime.windows():
        for v in w.views():
            view_filename = v.file_name()
            # Unsaved files have no file name
            if view_filename is None:
                continue
            errors_in_view = filter(lambda x: are_paths_equal(view_filename, x.filename), errors)
            mark_errors_in_this_view(errors_in_view, v)
    end_time = time.clock()
    log("total time to mark {0} diagnostics: {1} seconds".format(len(errors), end_time - begin_time))
示例#6
0
def wait_ghcmod_and_parse(view, filename, msg, cmds_with_args, alter_messages_cb):
    sublime.set_timeout(lambda: hide_output(view), 0)

    parsed_messages = []

    file_dir = os.path.dirname(filename)

    all_cmds_successful = True
    all_cmds_outputs = []

    for (cmd, args) in cmds_with_args:
        stdout = call_ghcmod_and_wait(args, filename)

        # stdout contains NULL as line endings within one message
        # error_output_regex using indents to determine one message scope
        # Replace NULLs to indents
        out1 = stdout.replace('\0', '\n  ')
        
        # Hlint outputs Error instead Warning for tips
        # so lets replace them
        out = out1.replace('Error', 'Warning')

        success = len(out.strip()) == 0

        if not success:
            all_cmds_outputs.append(out)
            log(u"ghc-mod %s didn't exit with success on '%s'" % (u' '.join(cmd), filename))

        all_cmds_successful &= success

        parsed = parse_output_messages(file_dir, out)
        for p in parsed:
            parsed_messages.append((cmd, p))

    if alter_messages_cb:
        alter_messages_cb(parsed_messages)

    concated_messages = [m[1] for m in parsed_messages]

    # Set global error list
    set_global_error_messages(concated_messages)

    sublime.set_timeout(lambda: mark_messages_in_views(concated_messages), 0)

    output_text = (format_output_messages(concated_messages) if parsed_messages
                   else '\n'.join(all_cmds_outputs))

    exit_code = 0 if all_cmds_successful else 1

    show_output_result_text(view, msg, output_text, exit_code, file_dir)
示例#7
0
    def init_ghcmod_completions(self):

        if not get_setting('enable_ghc_mod'):
            return

        sublime.status_message('SublimeHaskell: Updating ghc_mod completions...')

        # Init LANGUAGE completions
        autocompletion.language_completions = call_ghcmod_and_wait(['lang']).splitlines()
        log("Reading LANGUAGE completions from ghc-mod")

        # Init import module completion
        autocompletion.module_completions = call_ghcmod_and_wait(['list']).splitlines()

        sublime.status_message('SublimeHaskell: Updating ghc_mod completions ' + u" \u2714")
示例#8
0
def run_build(view, project_name, project_dir, command, use_cabal_dev=None):
    global projects_being_built

    # Don't build if a build is already running for this project
    # We compare the project_name for simplicity (projects with same
    # names are of course possible, but unlikely, so we let them wait)
    if project_name in projects_being_built:
        print "SublimeHaskell: Not building '%s' because it is already being built" % project_name
        sublime.status_message('SublimeHaskell: Already building %s' % project_name)
        return
    # Set project as building
    projects_being_built.add(project_name)

    # Run cabal or cabal-dev
    if use_cabal_dev is None:
        use_cabal_dev = get_setting_async('use_cabal_dev')

    tool = cabal_tool[use_cabal_dev]
    config = cabal_command[command]

    # Title of tool: Cabal, Cabal-Dev
    tool_title = tool['message']
    # Title of action: Cleaning, Building, etc.
    action_title = config['message']
    # Extra arguments lambda
    extra_args = tool['extra']
    # Tool name: cabal, cabal-dev
    tool_name = tool['command']
    # Tool arguments (commands): build, clean, etc.
    tool_steps = config['steps']

    # Assemble command lines to run (possibly multiple steps)
    commands = [extra_args([tool_name] + step) for step in tool_steps]

    log('running build commands: {0}'.format(commands))

    def done_callback():
        # Set project as done being built so that it can be built again
        projects_being_built.remove(project_name)

    # Run them
    run_chain_build_thread(
        view,
        project_dir,
        tool_title + ': ' + action_title + ' ' + project_name,
        commands,
        on_done=done_callback)
示例#9
0
def mark_messages_in_views(errors):
    "Mark the regions in open views where errors were found."
    begin_time = time.clock()
    # Mark each diagnostic in each open view in all windows:
    for w in sublime.windows():
        for v in w.views():
            view_filename = v.file_name()
            # Unsaved files have no file name
            if view_filename is None:
                continue
            errors_in_view = list(
                filter(lambda x: are_paths_equal(view_filename, x.filename),
                       errors))
            mark_messages_in_view(errors_in_view, v)
    end_time = time.clock()
    log('total time to mark {0} diagnostics: {1} seconds'.format(
        len(errors), end_time - begin_time))
示例#10
0
    def _refresh_all_module_info(self, cabal_dir):
        "Rebuild module information for all files under the specified directory."
        begin_time = time.clock()
        log('reinspecting project ({0})'.format(cabal_dir))
        # Process all files within the Cabal project:
        # TODO: Only process files within the .cabal file's "src" directory.
        (project_name, cabal_file) = get_cabal_in_dir(cabal_dir)
        # set project and read cabal
        if cabal_file and project_name:
            self._refresh_project_info(cabal_dir, project_name, cabal_file)

        files_in_dir = list_files_in_dir_recursively(cabal_dir)
        haskell_source_files = [x for x in files_in_dir if x.endswith('.hs') and ('dist/build/autogen' not in x)]
        for filename in haskell_source_files:
            self._refresh_module_info(filename)
        end_time = time.clock()
        log('total inspection time: {0} seconds'.format(end_time - begin_time))
示例#11
0
def wait_ghcmod_and_parse(view, filename, msg, cmds_with_args, alter_messages_cb):
    sublime.set_timeout(lambda: hide_output(view), 0)

    parsed_messages = []

    file_dir = os.path.dirname(filename)

    all_cmds_successful = True
    all_cmds_outputs = []

    for (cmd, args) in cmds_with_args:
        stdout = call_ghcmod_and_wait(args, filename)

        # stdout contains NULL as line endings within one message
        # error_output_regex using indents to determine one message scope
        # Replace NULLs to indents
        out = stdout.replace('\0', '\n  ')

        success = len(out.strip()) == 0

        if not success:
            all_cmds_outputs.append(out)
            log(u"ghc-mod %s didn't exit with success on '%s'" % (u' '.join(cmd), filename))

        all_cmds_successful &= success

        parsed = parse_output_messages(file_dir, out)
        for p in parsed:
            parsed_messages.append((cmd, p))

    if alter_messages_cb:
        alter_messages_cb(parsed_messages)

    concated_messages = [m[1] for m in parsed_messages]

    # Set global error list
    set_global_error_messages(concated_messages)

    sublime.set_timeout(lambda: mark_messages_in_views(concated_messages), 0)

    output_text = (format_output_messages(concated_messages) if parsed_messages
                   else '\n'.join(all_cmds_outputs))

    exit_code = 0 if all_cmds_successful else 1

    show_output_result_text(view, msg, output_text, exit_code, file_dir)
示例#12
0
 def run(self, edit):
     log("SublimeHaskellNextError")
     v = self.view
     fn = v.file_name().encode("utf-8")
     line, column = v.rowcol(v.sel()[0].a)
     gotoline = -1
     if fn in ERRORS:
         for errLine in ERRORS[fn]:
             if errLine > line:
                 gotoline = errLine
                 break
         # No next line: Wrap around if possible
         if gotoline == -1 and len(ERRORS[fn]) > 0:
             gotoline = ERRORS[fn].keys()[0]
     if gotoline != -1:
         v.window().open_file("%s:%d" % (fn, gotoline), sublime.ENCODED_POSITION)
     else:
         sublime.status_message("No more errors or warnings!")
示例#13
0
 def run(self, edit):
     log("SublimeHaskellNextError")
     v = self.view
     fn = v.file_name().encode("utf-8")
     line, column = v.rowcol(v.sel()[0].a)
     line += 1
     gotoline = -1
     if fn in ERRORS:
         for errLine in sorted(ERRORS[fn].keys()):
             if errLine > line:
                 gotoline = errLine
                 break
         # No next line: Wrap around if possible
         if gotoline == -1 and len(ERRORS[fn]) > 0:
             gotoline = sorted(ERRORS[fn].keys())[0]
     if gotoline != -1:
         v.window().open_file("%s:%d" % (fn, gotoline),
                              sublime.ENCODED_POSITION)
     else:
         sublime.status_message("No more errors or warnings!")
示例#14
0
    def on_query_completions(self, view, prefix, locations):
        begin_time = time.clock()
        # Only suggest symbols if the current file is part of a Cabal project.
        # TODO: Only suggest symbols from within this project.

        cabal_dir = get_cabal_project_dir_of_view(view)
        if cabal_dir is not None:

            completions = self.get_special_completions(view, prefix, locations)

            if not completions:
                completions = self.inspector.get_completions(view.file_name())

            end_time = time.clock()
            log('time to get completions: {0} seconds'.format(end_time - begin_time))
            # 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
            return [ c for c in completions if NO_SPECIAL_CHARS_RE.match(c[0]) ]

        return []
示例#15
0
    def on_query_completions(self, view, prefix, locations):
        if not is_haskell_source(view):
            return []

        begin_time = time.clock()
        # Only suggest symbols if the current file is part of a Cabal project.
        # TODO: Only suggest symbols from within this project.

        completions = autocompletion.get_import_completions(view, prefix, locations)

        if not completions:
            completions = autocompletion.get_completions(view, prefix, locations)

        end_time = time.clock()
        log('time to get completions: {0} seconds'.format(end_time - begin_time))
        # 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])]
        if get_setting('inhibit_completions'):
            return (comp, sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
        return comp