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
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
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
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
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 _is_evince_running(self, pdf_file): try: return ( ('evince {0}'.format(pdf_file)) in check_output(['ps', 'xv'], use_texpath=False) ) except: return False
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
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 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)
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)
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)
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)
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)
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)