def _get_tex_searchpath(file_type):
    if file_type is None:
        raise Exception('file_type must be set for _get_tex_searchpath')

    command = ['kpsewhich']
    command.append('--show-path={0}'.format(file_type))

    try:
        return check_output(command)
    except CalledProcessError as e:
        sublime.set_timeout(
            partial(
                sublime.error_message,
                'An error occurred while trying to run kpsewhich. '
                'Files in your TEXMF tree could not be accessed.'
            ),
            0
        )
        if e.output:
            print(e.output)
        traceback.print_exc()
    except OSError:
        sublime.set_timeout(
            partial(
                sublime.error_message,
                'Could not run kpsewhich. Please ensure that your texpath '
                'setting is configured correctly in your LaTeXTools '
                'settings.'
            ),
            0
        )
        traceback.print_exc()

    return None
Exemple #2
0
def kpsewhich(filename, file_format=None, notify_user_on_error=False):
    # build command
    command = ['kpsewhich']
    if file_format is not None:
        command.append('-format=%s' % (file_format))
    command.append(filename)

    try:
        return check_output(command)
    except CalledProcessError as e:
        if notify_user_on_error:
            sublime.error_message(
                'An error occurred while trying to run kpsewhich. '
                'Files in your TEXINPUTS could not be accessed.'
            )
            if e.output:
                print(e.output)
            traceback.print_exc()
    except OSError:
        if notify_user_on_error:
            sublime.error_message(
                'Could not run kpsewhich. Please ensure that your texpath '
                'setting is correct.'
            )
            traceback.print_exc()

    return None
Exemple #3
0
def kpsewhich(filename, file_format=None, notify_user_on_error=False):
    # build command
    command = ['kpsewhich']
    if file_format is not None:
        command.append('-format=%s' % (file_format))
    command.append(filename)

    try:
        return check_output(command)
    except CalledProcessError as e:
        if notify_user_on_error:
            sublime.error_message(
                'An error occurred while trying to run kpsewhich. '
                'Files in your TEXINPUTS could not be accessed.')
            if e.output:
                print(e.output)
            traceback.print_exc()
    except OSError:
        if notify_user_on_error:
            sublime.error_message(
                'Could not run kpsewhich. Please ensure that your texpath '
                'setting is correct.')
            traceback.print_exc()

    return None
Exemple #4
0
def _get_tex_searchpath(file_type):
    if file_type is None:
        raise Exception('file_type must be set for _get_tex_searchpath')

    command = ['kpsewhich']
    command.append('--show-path={0}'.format(file_type))

    try:
        return check_output(command)
    except CalledProcessError as e:
        sublime.set_timeout(
            partial(
                sublime.error_message,
                'An error occurred while trying to run kpsewhich. '
                'Files in your TEXMF tree could not be accessed.'), 0)
        if e.output:
            print(e.output)
        traceback.print_exc()
    except OSError:
        sublime.set_timeout(
            partial(
                sublime.error_message,
                'Could not run kpsewhich. Please ensure that your texpath '
                'setting is configured correctly in your LaTeXTools '
                'settings.'), 0)
        traceback.print_exc()

    return None
Exemple #5
0
    def run(self, edit, **args):
        tex_root = get_tex_root(self.view)

        if not os.path.exists(tex_root):
            sublime.error_message(
                'Tried to run TeXCount on non-existent file. Please ensure '
                'all files are saved before invoking TeXCount.')
            return

        sub_level = args.get('sub_level',
                             get_setting('word_count_sub_level', 'none'))

        if sub_level not in ['none', 'part', 'chapter', 'section']:
            sub_level = 'none'

        if sub_level == 'none':
            command = ['texcount', '-total', '-merge', '-utf8']
        else:
            command = ['texcount', '-merge', '-sub=' + sub_level, '-utf8']
        cwd = os.path.dirname(tex_root)
        command.append(os.path.basename(tex_root))

        try:
            result = check_output(command, cwd=cwd)
            res_split = result.splitlines()
            self.view.window().show_quick_panel(res_split[1:4] + res_split[9:],
                                                None)
        except CalledProcessError as e:
            sublime.error_message('Error while running TeXCount: {0}'.format(
                e.output or e))
        except OSError:
            sublime.error_message(
                'Could not run texcount. Please ensure that TeXcount is '
                'installed and that your texpath setting includes the path '
                'containing the TeXcount executable.')
Exemple #6
0
 def _is_evince_running(self, pdf_file):
     try:
         return (
             ('evince {0}'.format(pdf_file)) in
             check_output(['ps', 'xv'], use_texpath=False)
         )
     except:
         return False
Exemple #7
0
 def _get_chrome_dir(self, escaped=False):
     viewer_location = check_output([
         'osascript', '-e', 'POSIX path of '
         '(path to app id "com.google.Chrome")'
     ],
                                    use_texpath=False)
     viewer_location = viewer_location.replace(" ", "\\ ")
     if escaped:
         return "{viewer_location}Contents/MacOS/Google\\ Chrome".format(
             viewer_location=viewer_location)
     return "{viewer_location}Contents/MacOS/Google Chrome".format(
         viewer_location=viewer_location)
    def _get_zathura_pid(self, pdf_file):
        try:
            running_apps = check_output(['ps', 'xv'], use_texpath=False)
            for app in running_apps.splitlines():
                if 'zathura' not in app:
                    continue
                if pdf_file in app:
                    return app.lstrip().split(' ', 1)[0]
        except:
            pass

        return None
Exemple #9
0
    def _is_okular_running(self):
        try:
            running_apps = check_output(['ps', 'xv'], use_texpath=False)
            for app in running_apps.splitlines():
                if 'okular' not in app:
                    continue
                if '--unique' in app:
                    return True
        except:
            pass

        return False
    def _get_zathura_pid(self, pdf_file):
        try:
            running_apps = check_output(['ps', 'xv'], use_texpath=False)
            for app in running_apps.splitlines():
                if 'zathura' not in app:
                    continue
                if pdf_file in app:
                    return app.lstrip().split(' ', 1)[0]
        except:
            pass

        return None
Exemple #11
0
    def check_processes(st2_dir=None):
        if st2_dir is None or os.path.exists(st2_dir):
            for process in processes:
                try:
                    if st2_dir is not None:
                        process = os.path.join(st2_dir, process)

                    m = SUBLIME_VERSION.search(
                        check_output([process, '-v'], use_texpath=False))
                    if m and m.group(1) == version:
                        return process
                except:
                    pass

        return None
    def check_processes(st2_dir=None):
        if st2_dir is None or os.path.exists(st2_dir):
            for process in processes:
                try:
                    if st2_dir is not None:
                        process = os.path.join(st2_dir, process)

                    m = SUBLIME_VERSION.search(check_output(
                        [process, '-v'],
                        use_texpath=False
                    ))
                    if m and m.group(1) == version:
                        return process
                except:
                    pass

        return None
    def _focus_wmctrl(self, pid):
        window_id = None
        try:
            windows = check_output(['wmctrl', '-l', '-p'], use_texpath=False)
        except:
            pass
        else:
            pid = ' {0} '.format(pid)
            for window in windows.splitlines():
                if pid in window:
                    window_id = window.split(' ', 1)[0]
                    break

        if window_id is None:
            raise Exception('Cannot find window for Zathura')

        external_command(['wmctrl', '-a', window_id, '-i'], use_texpath=False)
Exemple #14
0
    def forward_sync(self, pdf_file, tex_file, line, col, **kwargs):
        keep_focus = kwargs.pop("keep_focus", True)
        path_to_skim = "/Applications/Skim.app"

        if not os.path.exists(path_to_skim):
            path_to_skim = check_output(
                ["osascript", "-e", 'POSIX path of (path to app id "net.sourceforge.skim-app.skim")'], use_texpath=False
            )

        command = [os.path.join(path_to_skim, "Contents", "SharedSupport", "displayline"), "-r"]

        if keep_focus:
            command.append("-g")

        command += [str(line), pdf_file, tex_file]

        external_command(command, use_texpath=False)
Exemple #15
0
    def run(self, edit, **args):
        tex_root = get_tex_root(self.view)

        if not os.path.exists(tex_root):
            sublime.error_message(
                'Tried to run TeXCount on non-existent file. Please ensure '
                'all files are saved before invoking TeXCount.'
            )
            return

        sub_level = args.get(
            'sub_level',
            get_setting(
                'word_count_sub_level',
                'none'
            )
        )

        if sub_level not in ['none', 'part', 'chapter', 'section']:
            sub_level = 'none'

        if sub_level == 'none':
            command = ['texcount', '-total', '-merge', '-utf8']
        else:
            command = ['texcount', '-merge', '-sub=' + sub_level, '-utf8']
        cwd = os.path.dirname(tex_root)
        command.append(os.path.basename(tex_root))

        try:
            result = check_output(command, cwd=cwd)
            res_split = result.splitlines()
            self.view.window().show_quick_panel(
                res_split[1:4] + res_split[9:], None
            )
        except CalledProcessError as e:
            sublime.error_message(
                'Error while running TeXCount: {0}'.format(e.output or e)
            )
        except OSError:
            sublime.error_message(
                'Could not run texcount. Please ensure that TeXcount is '
                'installed and that your texpath setting includes the path '
                'containing the TeXcount executable.'
            )
    def _focus_wmctrl(self, pid):
        window_id = None
        try:
            windows = check_output(
                ['wmctrl', '-l', '-p'], use_texpath=False
            )
        except:
            pass
        else:
            pid = ' {0} '.format(pid)
            for window in windows.splitlines():
                if pid in window:
                    window_id = window.split(' ', 1)[0]
                    break

        if window_id is None:
            raise Exception('Cannot find window for Zathura')

        external_command(['wmctrl', '-a', window_id, '-i'], use_texpath=False)
Exemple #17
0
 def _get_browser_filepath(self,
                           tex_line_no,
                           tex_col_no,
                           tex_filename,
                           pdf_filename,
                           zoom=100):
     try:
         relative_outputdir = os.path.relpath(
             get_output_directory(tex_filename),
             os.path.dirname(tex_filename))
         outputdir_command = ['-d', relative_outputdir]
     except Exception as e:
         print("ERROR GETTING 'output_directory'")
         print(e)
         outputdir_command = []
     synctex_loc = '{tex_line_no}:{tex_col_no}:{tex_filename}'.format(
         tex_line_no=tex_line_no,
         tex_col_no=tex_col_no,
         tex_filename=tex_filename)
     cmd = [
         '/Library/TeX/texbin/synctex', 'view', '-i', synctex_loc, '-o',
         pdf_filename
     ] + outputdir_command
     try:
         stdout = check_output(cmd)
         output_text = stdout.split("\n")
         page_no = next((e.lstrip('Page:')
                         for e in output_text if e.startswith('Page:')), 1)
         # page_no = int(page_no) + 1 #offset, see `synctex view help`
         col_no = next(
             (e.lstrip('x:') for e in output_text if e.startswith('x:')), 1)
         line_no = next(
             (e.lstrip('y:') for e in output_text if e.startswith('y:')), 1)
     except Exception as e:
         print("ERROR IN SYNCTEX")
         print(e)
         page_no = 1
         line_no = 1
         col_no = 0
     return "file://{pdf_filename}#page={page_no}&view=FitH,{line_no}".format(
         pdf_filename=pdf_filename, page_no=page_no, line_no=line_no)
Exemple #18
0
    def forward_sync(self, pdf_file, tex_file, line, col, **kwargs):
        keep_focus = kwargs.pop('keep_focus', True)
        path_to_skim = '/Applications/Skim.app'

        if not os.path.exists(path_to_skim):
            path_to_skim = check_output([
                'osascript', '-e',
                'POSIX path of (path to app id "net.sourceforge.skim-app.skim")'
            ],
                                        use_texpath=False)

        command = [
            os.path.join(path_to_skim, 'Contents', 'SharedSupport',
                         'displayline'), '-r'
        ]

        if keep_focus:
            command.append('-g')

        command += [str(line), pdf_file, tex_file]

        external_command(command, use_texpath=False)
Exemple #19
0
def get_sublime_exe():
    '''
    Utility function to get the full path to the currently executing
    Sublime instance.
    '''
    processes = ['subl', 'sublime_text']

    def check_processes(st2_dir=None):
        if st2_dir is None or os.path.exists(st2_dir):
            for process in processes:
                try:
                    if st2_dir is not None:
                        process = os.path.join(st2_dir, process)

                    m = SUBLIME_VERSION.search(
                        check_output([process, '-v'], use_texpath=False))
                    if m and m.group(1) == version:
                        return process
                except:
                    pass

        return None

    platform = sublime.platform()

    plat_settings = get_setting(platform, {})
    sublime_executable = plat_settings.get('sublime_executable', None)

    if sublime_executable:
        return sublime_executable

    # we cache the results of the other checks, if possible
    if hasattr(get_sublime_exe, 'result'):
        return get_sublime_exe.result

    # are we on ST3
    if hasattr(sublime, 'executable_path'):
        get_sublime_exe.result = sublime.executable_path()
        # on osx, the executable does not function the same as subl
        if platform == 'osx':
            get_sublime_exe.result = os.path.normpath(
                os.path.join(os.path.dirname(get_sublime_exe.result), '..',
                             'SharedSupport', 'bin', 'subl'))
        # on linux, it is preferable to use subl if it points to the
        # correct version see issue #710 for a case where this is useful
        elif (platform == 'linux'
              and not get_sublime_exe.result.endswith('subl')):
            subl = which('subl')
            if subl is not None:
                try:
                    m = SUBLIME_VERSION.search(
                        check_output([subl, '-v'], use_texpath=False))

                    if m and m.group(1) == sublime.version():
                        get_sublime_exe.result = subl
                except:
                    pass

        return get_sublime_exe.result
    # in ST2 on Windows the Python executable is actually "sublime_text"
    elif platform == 'windows' and sys.executable != 'python' and \
            os.path.isabs(sys.executable):
        get_sublime_exe.result = sys.executable
        return get_sublime_exe.result

    # guess-work for ST2
    version = sublime.version()

    # hope its on the path
    result = check_processes()
    if result is not None:
        get_sublime_exe.result = result
        return result

    # guess the default location
    if platform == 'windows':
        st2_dir = os.path.expandvars('%PROGRAMFILES%\\Sublime Text 2')
        result = check_processes(st2_dir)
        if result is not None:
            get_sublime_exe.result = result
            return result
    elif platform == 'linux':
        for path in [
                '$HOME/bin', '$HOME/sublime_text_2', '$HOME/sublime_text',
                '/opt/sublime_text_2', '/opt/sublime_text', '/usr/local/bin',
                '/usr/bin'
        ]:
            st2_dir = os.path.expandvars(path)
            result = check_processes(st2_dir)
            if result is not None:
                get_sublime_exe.result = result
                return result
    else:
        st2_dir = '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin'
        result = check_processes(st2_dir)
        if result is not None:
            get_sublime_exe.result = result
            return result
        try:
            folder = check_output(
                ['mdfind', '"kMDItemCFBundleIdentifier == com.sublimetext.2"'],
                use_texpath=False)

            st2_dir = os.path.join(folder, 'Contents', 'SharedSupport', 'bin')
            result = check_processes(st2_dir)
            if result is not None:
                get_sublime_exe.result = result
                return result
        except:
            pass

    print('Cannot determine the path to your Sublime installation. Please '
          'set the "sublime_executable" setting in your settings for your '
          'platform.')

    return None
def get_sublime_exe():
    '''
    Utility function to get the full path to the currently executing
    Sublime instance.
    '''
    processes = ['subl', 'sublime_text']

    def check_processes(st2_dir=None):
        if st2_dir is None or os.path.exists(st2_dir):
            for process in processes:
                try:
                    if st2_dir is not None:
                        process = os.path.join(st2_dir, process)

                    m = SUBLIME_VERSION.search(check_output(
                        [process, '-v'],
                        use_texpath=False
                    ))
                    if m and m.group(1) == version:
                        return process
                except:
                    pass

        return None

    platform = sublime.platform()

    plat_settings = get_setting(platform, {})
    sublime_executable = plat_settings.get('sublime_executable', None)

    if sublime_executable:
        return sublime_executable

    # we cache the results of the other checks, if possible
    if hasattr(get_sublime_exe, 'result'):
        return get_sublime_exe.result

    # are we on ST3
    if hasattr(sublime, 'executable_path'):
        get_sublime_exe.result = sublime.executable_path()
        # on osx, the executable does not function the same as subl
        if platform == 'osx':
            get_sublime_exe.result = os.path.normpath(
                os.path.join(
                    os.path.dirname(get_sublime_exe.result),
                    '..',
                    'SharedSupport',
                    'bin',
                    'subl'
                )
            )
        # on linux, it is preferable to use subl if it points to the
        # correct version see issue #710 for a case where this is useful
        elif (
            platform == 'linux' and
            not get_sublime_exe.result.endswith('subl')
        ):
            subl = which('subl')
            if subl is not None:
                try:
                    m = SUBLIME_VERSION.search(check_output(
                        [subl, '-v'],
                        use_texpath=False
                    ))

                    if m and m.group(1) == sublime.version():
                        get_sublime_exe.result = subl
                except:
                    pass

        return get_sublime_exe.result
    # in ST2 on Windows the Python executable is actually "sublime_text"
    elif platform == 'windows' and sys.executable != 'python' and \
            os.path.isabs(sys.executable):
        get_sublime_exe.result = sys.executable
        return get_sublime_exe.result

    # guess-work for ST2
    version = sublime.version()

    # hope its on the path
    result = check_processes()
    if result is not None:
        get_sublime_exe.result = result
        return result

    # guess the default location
    if platform == 'windows':
        st2_dir = os.path.expandvars('%PROGRAMFILES%\\Sublime Text 2')
        result = check_processes(st2_dir)
        if result is not None:
            get_sublime_exe.result = result
            return result
    elif platform == 'linux':
        for path in [
            '$HOME/bin',
            '$HOME/sublime_text_2',
            '$HOME/sublime_text',
            '/opt/sublime_text_2',
            '/opt/sublime_text',
            '/usr/local/bin',
            '/usr/bin'
        ]:
            st2_dir = os.path.expandvars(path)
            result = check_processes(st2_dir)
            if result is not None:
                get_sublime_exe.result = result
                return result
    else:
        st2_dir = '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin'
        result = check_processes(st2_dir)
        if result is not None:
            get_sublime_exe.result = result
            return result
        try:
            folder = check_output(
                ['mdfind', '"kMDItemCFBundleIdentifier == com.sublimetext.2"'],
                use_texpath=False
            )

            st2_dir = os.path.join(folder, 'Contents', 'SharedSupport', 'bin')
            result = check_processes(st2_dir)
            if result is not None:
                    get_sublime_exe.result = result
                    return result
        except:
            pass

    print(
        'Cannot determine the path to your Sublime installation. Please '
        'set the "sublime_executable" setting in your settings for your '
        'platform.'
    )

    return None
    def _on_main_thread(self, results):
        builder_name = get_setting(
            'builder', 'traditional', view=self.view
        )

        if builder_name in ['', 'default']:
            builder_name = 'traditional'

        builder_settings = get_setting('builder_settings', view=self.view)
        builder_path = get_setting('builder_path', view=self.view)

        if builder_name in ['simple', 'traditional', 'script']:
            builder_path = None
        else:
            bld_path = os.path.join(sublime.packages_path(), builder_path)
            add_plugin_path(bld_path)

        builder_name = _classname_to_internal_name(builder_name)

        try:
            get_plugin('{0}_builder'.format(builder_name))
            builder_available = True
        except NoSuchPluginException:
            traceback.print_exc()
            builder_available = False

        results.append([
            [u'Builder', u'Status'],
            [
                builder_name,
                u'available' if builder_available else u'missing'
            ]
        ])

        if builder_path:
            results.append([[u'Builder Path'], [builder_path]])

        if builder_settings is not None:
            table = [[u'Builder Setting', u'Value']]
            for key in sorted(builder_settings.keys()):
                value = builder_settings[key]
                table.append([key, value])
            results.append(table)

        # is current view a TeX file?
        view = self.view
        if view.score_selector(0, 'text.tex.latex') != 0:
            tex_root = get_tex_root(view)
            tex_directives = parse_tex_directives(
                tex_root,
                multi_values=['options'],
                key_maps={'ts-program': 'program'}
            )

            results.append([[u'TeX Root'], [tex_root]])

            results.append([
                [u'LaTeX Engine'],
                [
                    tex_directives.get(
                        'program',
                        get_setting(
                            'program', 'pdflatex', self.view
                        )
                    )
                ]
            ])

            table = [[u'LaTeX Output Setting', u'Value']]
            output_directory = get_output_directory(view)
            if output_directory:
                table.append(
                    ['output_directory', output_directory]
                )
            aux_directory = get_aux_directory(view)
            if aux_directory:
                table.append(['aux_directory', aux_directory])
            jobname = get_jobname(view)
            if jobname and jobname != os.path.splitext(
                os.path.basename(tex_root)
            )[0]:
                table.append(['jobname', jobname])

            if len(table) > 1:
                results.append(table)

            options = get_setting('builder_settings', {}, self.view).\
                get('options', [])

            if isinstance(options, strbase):
                options = [options]

            options.extend(tex_directives.get('options', []))

            if len(options) > 0:
                table = [[u'LaTeX Options']]
                for option in options:
                    table.append([option])

                results.append(table)

        default_viewer = DEFAULT_VIEWERS.get(sublime.platform(), None)
        viewer_name = get_setting('viewer', default_viewer)
        if viewer_name in ['', 'default']:
            viewer_name = default_viewer

        try:
            viewer_plugin = get_plugin(viewer_name + '_viewer')
            viewer_available = True
        except NoSuchPluginException:
            viewer_available = False

        viewer_location = 'N/A'
        if viewer_available:
            if viewer_name == 'command':
                # assume the command viewer is always valid
                viewer_location = 'N/A'
            elif viewer_name in ('evince', 'okular', 'zathura'):
                viewer_location = which(viewer_name)
                viewer_available = bool(viewer_location)
            elif viewer_name == 'preview':
                viewer_location = '/Applications/Preview.app'

                if not os.path.exists(viewer_location):
                    try:
                        viewer_location = check_output([
                            'osascript',
                            '-e',
                            'POSIX path of '
                            '(path to app id "com.apple.Preview")'
                        ], use_texpath=False)
                    except subprocess.CalledProcessError:
                        viewer_location = None

                viewer_available = False \
                    if not viewer_location else os.path.exists(viewer_location)
            elif viewer_name == 'skim':
                viewer_location = '/Applications/Skim.app'

                if not os.path.exists(viewer_location):
                    try:
                        viewer_location = check_output([
                            'osascript',
                            '-e',
                            'POSIX path of '
                            '(path to app id "net.sourceforge.skim-app.skim")'
                        ], use_texpath=False)
                    except subprocess.CalledProcessError:
                        viewer_location = None

                viewer_available = False \
                    if not viewer_location else os.path.exists(viewer_location)
            elif viewer_name == 'sumatra':
                sumatra_exe = get_setting('viewer_settings', {}).\
                    get('sumatra', get_setting('windows', {}).
                        get('sumatra', 'SumatraPDF.exe')) or \
                    'SumatraPDF.exe'

                viewer_location = which(sumatra_exe)
                if not bool(viewer_location):
                    viewer_location = viewer_plugin()._find_sumatra_exe()
                    viewer_available = bool(viewer_location)

        if not viewer_available:
            viewer_location = 'N/A'

        results.append([
            [u'Viewer', u'Status', u'Location'],
            [
                viewer_name,
                u'available' if viewer_available else u'missing',
                viewer_location
            ]
        ])

        if callable(self.on_done):
            self.on_done(results)
def kpsewhich(file):
    try:
        return check_output(['kpsewhich', file])
    except Exception:
        return None
    def _on_main_thread(self, results):
        builder_name = get_setting('builder', 'traditional', view=self.view)

        if builder_name in ['', 'default']:
            builder_name = 'traditional'

        builder_settings = get_setting('builder_settings', view=self.view)
        builder_path = get_setting('builder_path', view=self.view)

        if builder_name in ['simple', 'traditional', 'script']:
            builder_path = None
        else:
            bld_path = os.path.join(sublime.packages_path(), builder_path)
            add_plugin_path(bld_path)

        builder_name = _classname_to_internal_name(builder_name)

        try:
            get_plugin('{0}_builder'.format(builder_name))
            builder_available = True
        except NoSuchPluginException:
            traceback.print_exc()
            builder_available = False

        results.append(
            [[u'Builder', u'Status'],
             [builder_name,
              u'available' if builder_available else u'missing']])

        if builder_path:
            results.append([[u'Builder Path'], [builder_path]])

        if builder_settings is not None:
            table = [[u'Builder Setting', u'Value']]
            for key in sorted(builder_settings.keys()):
                value = builder_settings[key]
                table.append([key, value])
            results.append(table)

        # is current view a TeX file?
        view = self.view
        if view.score_selector(0, 'text.tex.latex') != 0:
            tex_root = get_tex_root(view)
            tex_directives = parse_tex_directives(
                tex_root,
                multi_values=['options'],
                key_maps={'ts-program': 'program'})

            results.append([[u'TeX Root'], [tex_root]])

            results.append([[u'LaTeX Engine'],
                            [
                                tex_directives.get(
                                    'program',
                                    get_setting('program', 'pdflatex',
                                                self.view))
                            ]])

            table = [[u'LaTeX Output Setting', u'Value']]
            output_directory = get_output_directory(tex_root)
            if output_directory:
                table.append(['output_directory', output_directory])
            aux_directory = get_aux_directory(tex_root)
            if aux_directory:
                table.append(['aux_directory', aux_directory])
            jobname = get_jobname(tex_root)
            if jobname and jobname != os.path.splitext(
                    os.path.basename(tex_root))[0]:
                table.append(['jobname', jobname])

            if len(table) > 1:
                results.append(table)

            options = get_setting('builder_settings', {}, self.view).\
                get('options', [])
            options.extend(tex_directives.get('options', []))

            if len(options) > 0:
                table = [[u'LaTeX Options']]
                for option in options:
                    table.append([option])

                results.append(table)

        default_viewer = DEFAULT_VIEWERS.get(sublime.platform(), None)
        viewer_name = get_setting('viewer', default_viewer)
        if viewer_name in ['', 'default']:
            viewer_name = default_viewer

        try:
            viewer_plugin = get_plugin(viewer_name + '_viewer')
            viewer_available = True
        except NoSuchPluginException:
            viewer_available = False

        viewer_location = 'N/A'
        if viewer_available:
            if viewer_name == 'command':
                # assume the command viewer is always valid
                viewer_location = 'N/A'
            elif viewer_name in ('evince', 'okular', 'zathura'):
                viewer_location = which(viewer_name)
                viewer_available = bool(viewer_location)
            elif viewer_name == 'preview':
                viewer_location = '/Applications/Preview.app'

                if not os.path.exists(viewer_location):
                    try:
                        viewer_location = check_output([
                            'osascript', '-e', 'POSIX path of '
                            '(path to app id "com.apple.Preview")'
                        ],
                                                       use_texpath=False)
                    except subprocess.CalledProcessError:
                        viewer_location = None

                viewer_available = False \
                    if not viewer_location else os.path.exists(viewer_location)
            elif viewer_name == 'skim':
                viewer_location = '/Applications/Skim.app'

                if not os.path.exists(viewer_location):
                    try:
                        viewer_location = check_output([
                            'osascript', '-e', 'POSIX path of '
                            '(path to app id "net.sourceforge.skim-app.skim")'
                        ],
                                                       use_texpath=False)
                    except subprocess.CalledProcessError:
                        viewer_location = None

                viewer_available = False \
                    if not viewer_location else os.path.exists(viewer_location)
            elif viewer_name == 'sumatra':
                sumatra_exe = get_setting('viewer_settings', {}).\
                    get('sumatra', get_setting('windows', {}).
                        get('sumatra', 'SumatraPDF.exe')) or \
                    'SumatraPDF.exe'

                viewer_location = which(sumatra_exe)
                if not bool(viewer_location):
                    viewer_location = viewer_plugin()._find_sumatra_exe()
                    viewer_available = bool(viewer_location)

        if not viewer_available:
            viewer_location = 'N/A'

        results.append([[u'Viewer', u'Status', u'Location'],
                        [
                            viewer_name,
                            u'available' if viewer_available else u'missing',
                            viewer_location
                        ]])

        if callable(self.on_done):
            self.on_done(results)
def kpsewhich(file):
    try:
        return check_output(['kpsewhich', file])
    except Exception:
        return None