def run(self): # Retrieve root file and dirname. view = self.window.active_view() root_file = getTeXRoot.get_tex_root(view) if root_file is None: msg = \ 'Could not find TEX root. Please ensure that either you ' + \ 'have configured a TEX root in your project settings or ' + \ 'have a LaTeX document open.' sublime.status_message(msg) print(msg) return if not os.path.isfile(root_file): message = "Could not find TEX root {0}.".format(root_file) sublime.status_message(message) print(message) return # clear the cache try: cache.delete_local_cache(root_file) except: print('Error while trying to delete local cache') traceback.print_exc() aux_directory, aux_directory_setting = get_aux_directory( root_file, return_setting=True) output_directory, output_directory_setting = get_output_directory( root_file, return_setting=True) if aux_directory is not None: # we cannot delete the output directory on Windows in case # Sumatra is holding a reference to it if (sublime.platform() != 'windows' or aux_directory != output_directory): if aux_directory_setting.startswith('<<'): self._rmtree(aux_directory) else: self.delete_temp_files(aux_directory) if output_directory is not None: if output_directory_setting.startswith('<<'): # we cannot delete the output directory on Windows in case # Sumatra is holding a reference to it if sublime.platform() == 'windows': self._clear_dir(output_directory) else: self._rmtree(output_directory) else: self.delete_temp_files(output_directory) else: # if there is no output directory, we may need to clean files # in the main directory, even if aux_directory is used self.delete_temp_files(os.path.dirname(root_file)) sublime.status_message("Deleted temp files")
def parse_completions(view, line): # reverse line, copied from latex_cite_completions, very cool :) line = line[::-1] search = None # search dynamic entries dyn_entries, dyn_regex = _get_dyn_entries() if dyn_regex: search = dyn_regex.match(line) entries = dyn_entries # search static entries if no dynamic matches found if not search: search = TEX_INPUT_FILE_REGEX.match(line) entries = _fillall_entries # if no regex matched, cancel completions if not search: return "", [] try: # extract the first group and the prefix from the maching regex group, prefix = next((i, v) for i, v in enumerate(search.groups()) if v is not None) entry = entries[group] prefix = prefix[::-1] except Exception as e: print("Error occurred while extracting entry from matching group.") print(e) return "", [] # adjust the prefix (don't include commas) if "," in prefix: prefix = prefix[prefix.rindex(",") + 1:] completions = [] if entry["type"] == "input": root = getTeXRoot.get_tex_root(view) if root: output_directory = get_output_directory(root) aux_directory = get_aux_directory(root) completions = get_file_list( root, entry["extensions"], entry.get("strip_extensions", []), output_directory, aux_directory ) else: # file is unsaved completions = [] elif entry["type"] == "cached": cache = _get_cache() if cache is not None: completions = cache.get(entry["cache_name"]) else: print("Unknown entry type {0}.".format(entry["type"])) return prefix, completions
def parse_completions(view, line): # reverse line, copied from latex_cite_completions, very cool :) line = line[::-1] search = None # search dynamic entries dyn_entries, dyn_regex = _get_dyn_entries() if dyn_regex: search = dyn_regex.match(line) entries = dyn_entries # search static entries if no dynamic matches found if not search: search = TEX_INPUT_FILE_REGEX.match(line) entries = _fillall_entries # if no regex matched, cancel completions if not search: return "", [] try: # extract the first group and the prefix from the maching regex group, prefix = next( (i, v) for i, v in enumerate(search.groups()) if v is not None) entry = entries[group] prefix = prefix[::-1] except Exception as e: print("Error occurred while extracting entry from matching group.") print(e) return "", [] # adjust the prefix (don't include commas) if "," in prefix: prefix = prefix[prefix.rindex(",") + 1:] completions = [] if entry["type"] == "input": root = getTeXRoot.get_tex_root(view) if root: output_directory = get_output_directory(root) aux_directory = get_aux_directory(root) completions = get_file_list(root, entry["extensions"], entry.get("strip_extensions", []), output_directory, aux_directory) else: # file is unsaved completions = [] elif entry["type"] == "cached": cache = _get_cache() if cache is not None: completions = cache.get(entry["cache_name"]) else: print("Unknown entry type {0}.".format(entry["type"])) return prefix, completions
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 run(self, cmd="", file_regex="", path=""): # Try to handle killing with self.proc_lock: if self.proc: # if we are running, try to kill running process self.output("\n\n### Got request to terminate compilation ###") if sublime.platform() == 'windows': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call( 'taskkill /t /f /pid {pid}'.format(pid=self.proc.pid), startupinfo=startupinfo, shell=True ) else: os.killpg(self.proc.pid, signal.SIGTERM) self.proc = None return else: # either it's the first time we run, or else we have no running processes self.proc = None view = self.view = self.window.active_view() if view.is_dirty(): print ("saving...") view.run_command('save') # call this on view, not self.window if view.file_name() is None: sublime.error_message('Please save your file before attempting to build.') return self.file_name = getTeXRoot.get_tex_root(view) if not os.path.isfile(self.file_name): sublime.error_message(self.file_name + ": file not found.") return self.tex_base = get_jobname(view) tex_dir = os.path.dirname(self.file_name) if not is_tex_file(self.file_name): sublime.error_message("%s is not a TeX source file: cannot compile." % (os.path.basename(view.file_name()),)) return # Output panel: from exec.py if not hasattr(self, 'output_view'): self.output_view = self.window.get_output_panel("latextools") output_view_settings = self.output_view.settings() output_view_settings.set("result_file_regex", file_regex) output_view_settings.set("result_base_dir", tex_dir) output_view_settings.set("line_numbers", False) output_view_settings.set("gutter", False) output_view_settings.set("scroll_past_end", False) output_view_settings.set( "syntax", "Packages/LaTeXTools/LaTeXTools Console.hidden-tmLanguage" ) output_view_settings.set( "color_scheme", sublime.load_settings('Preferences.sublime-settings'). get('color_scheme') ) self.output_view.set_read_only(True) # Dumb, but required for the moment for the output panel to be picked # up as the result buffer self.window.get_output_panel("latextools") self.hide_panel_level = get_setting("hide_build_panel", "never") if self.hide_panel_level != "always": self.window.run_command("show_panel", {"panel": "output.latextools"}) self.plat = sublime.platform() if self.plat == "osx": self.encoding = "UTF-8" elif self.plat == "windows": self.encoding = getOEMCP() elif self.plat == "linux": self.encoding = "UTF-8" else: sublime.error_message("Platform as yet unsupported. Sorry!") return # Get platform settings, builder, and builder settings platform_settings = get_setting(self.plat, {}) builder_name = get_setting("builder", "traditional") self.display_bad_boxes = get_setting("display_bad_boxes", False) # This *must* exist, so if it doesn't, the user didn't migrate if builder_name is None: sublime.error_message("LaTeXTools: you need to migrate your preferences. See the README file for instructions.") self.window.run_command('hide_panel', {"panel": "output.latextools"}) return # Default to 'traditional' builder if builder_name in ['', 'default']: builder_name = 'traditional' # this is to convert old-style names (e.g. AReallyLongName) # to new style plugin names (a_really_long_name) builder_name = _classname_to_internal_name(builder_name) builder_settings = get_setting("builder_settings", {}) # parse root for any %!TEX directives tex_directives = parse_tex_directives( self.file_name, multi_values=['options'], key_maps={'ts-program': 'program'} ) # determine the engine engine = tex_directives.get('program', builder_settings.get("program", "pdflatex")) engine = engine.lower() # Sanity check: if "strange" engine, default to pdflatex (silently...) if engine not in [ 'pdflatex', "pdftex", 'xelatex', 'xetex', 'lualatex', 'luatex' ]: engine = 'pdflatex' options = builder_settings.get("options", []) if isinstance(options, strbase): options = [options] if 'options' in tex_directives: options.extend(tex_directives['options']) # filter out --aux-directory and --output-directory options which are # handled separately options = [opt for opt in options if ( not opt.startswith('--aux-directory') and not opt.startswith('--output-directory') and not opt.startswith('--jobname') )] self.aux_directory = get_aux_directory(self.file_name) self.output_directory = get_output_directory(self.file_name) # Read the env option (platform specific) builder_platform_settings = builder_settings.get(self.plat) if builder_platform_settings: self.env = builder_platform_settings.get("env", None) else: self.env = None # Now actually get the builder builder_path = get_setting("builder_path", "") # relative to ST packages dir! # Safety check: if we are using a built-in builder, disregard # builder_path, even if it was specified in the pref file if builder_name in ['simple', 'traditional', 'script', 'basic']: builder_path = None if builder_path: bld_path = os.path.join(sublime.packages_path(), builder_path) add_plugin_path(bld_path) try: builder = get_plugin('{0}_builder'.format(builder_name)) except NoSuchPluginException: sublime.error_message("Cannot find builder " + builder_name + ".\n" \ "Check your LaTeXTools Preferences") self.window.run_command('hide_panel', {"panel": "output.latextools"}) return print(repr(builder)) self.builder = builder( self.file_name, self.output, engine, options, self.aux_directory, self.output_directory, self.tex_base, tex_directives, builder_settings, platform_settings ) # Now get the tex binary path from prefs, change directory to # that of the tex root file, and run! self.path = platform_settings['texpath'] os.chdir(tex_dir) CmdThread(self).start() print(threading.active_count())
def run( self, file_regex="", program=None, builder=None, command=None, env=None, path=None, script_commands=None, update_phantoms_only=False, hide_phantoms_only=False, **kwargs ): if update_phantoms_only: if self.show_errors_inline: self.update_phantoms() return if hide_phantoms_only: self.hide_phantoms() return # Try to handle killing with self.proc_lock: if self.proc: # if we are running, try to kill running process self.output("\n\n### Got request to terminate compilation ###") try: if sublime.platform() == 'windows': execute_command( 'taskkill /t /f /pid {pid}'.format(pid=self.proc.pid), use_texpath=False ) else: os.killpg(self.proc.pid, signal.SIGTERM) except: print('Exception occurred while killing build') traceback.print_exc() self.proc = None return else: # either it's the first time we run, or else we have no running processes self.proc = None view = self.view = self.window.active_view() if _HAS_PHANTOMS: self.hide_phantoms() pref_settings = sublime.load_settings("Preferences.sublime-settings") self.show_errors_inline = pref_settings.get("show_errors_inline", True) if view.is_dirty(): print ("saving...") view.run_command('save') # call this on view, not self.window if view.file_name() is None: sublime.error_message('Please save your file before attempting to build.') return self.file_name = getTeXRoot.get_tex_root(view) if not os.path.isfile(self.file_name): sublime.error_message(self.file_name + ": file not found.") return self.tex_base = get_jobname(view) self.tex_dir = os.path.dirname(self.file_name) if not is_tex_file(self.file_name): sublime.error_message("%s is not a TeX source file: cannot compile." % (os.path.basename(view.file_name()),)) return # Output panel: from exec.py if not hasattr(self, 'output_view'): self.output_view = self.window.get_output_panel("latextools") output_view_settings = self.output_view.settings() output_view_settings.set("result_file_regex", file_regex) output_view_settings.set("result_base_dir", self.tex_dir) output_view_settings.set("line_numbers", False) output_view_settings.set("gutter", False) output_view_settings.set("scroll_past_end", False) if get_setting("highlight_build_panel", True): self.output_view.set_syntax_file( "Packages/LaTeXTools/LaTeXTools Console.hidden-tmLanguage" ) output_view_settings.set( "color_scheme", sublime.load_settings('Preferences.sublime-settings'). get('color_scheme') ) self.output_view.set_read_only(True) # Dumb, but required for the moment for the output panel to be picked # up as the result buffer self.window.get_output_panel("latextools") self.hide_panel_level = get_setting("hide_build_panel", "no_warnings") if self.hide_panel_level == "never": self.show_output_panel(force=True) self.plat = sublime.platform() if self.plat == "osx": self.encoding = "UTF-8" elif self.plat == "windows": self.encoding = getOEMCP() elif self.plat == "linux": self.encoding = "UTF-8" else: sublime.error_message("Platform as yet unsupported. Sorry!") return # Get platform settings, builder, and builder settings platform_settings = get_setting(self.plat, {}) self.display_bad_boxes = get_setting("display_bad_boxes", False) if builder is not None: builder_name = builder else: builder_name = get_setting("builder", "traditional") # Default to 'traditional' builder if builder_name in ['', 'default']: builder_name = 'traditional' # this is to convert old-style names (e.g. AReallyLongName) # to new style plugin names (a_really_long_name) builder_name = _classname_to_internal_name(builder_name) builder_settings = get_setting("builder_settings", {}) # override the command if command is not None: builder_settings.set("command", command) # parse root for any %!TEX directives tex_directives = parse_tex_directives( self.file_name, multi_values=['options'], key_maps={'ts-program': 'program'} ) # determine the engine if program is not None: engine = program else: engine = tex_directives.get( 'program', builder_settings.get("program", "pdflatex") ) engine = engine.lower() # Sanity check: if "strange" engine, default to pdflatex (silently...) if engine not in [ 'pdflatex', "pdftex", 'xelatex', 'xetex', 'lualatex', 'luatex' ]: engine = 'pdflatex' options = builder_settings.get("options", []) if isinstance(options, strbase): options = [options] if 'options' in tex_directives: options.extend(tex_directives['options']) # filter out --aux-directory and --output-directory options which are # handled separately options = [opt for opt in options if ( not opt.startswith('--aux-directory') and not opt.startswith('--output-directory') and not opt.startswith('--jobname') )] self.aux_directory = get_aux_directory(self.file_name) self.output_directory = get_output_directory(self.file_name) # Read the env option (platform specific) builder_platform_settings = builder_settings.get(self.plat, {}) if env is not None: self.env = env elif builder_platform_settings: self.env = builder_platform_settings.get("env", None) else: self.env = None # Safety check: if we are using a built-in builder, disregard # builder_path, even if it was specified in the pref file if builder_name in ['simple', 'traditional', 'script', 'basic']: builder_path = None else: # relative to ST packages dir! builder_path = get_setting("builder_path", "") if builder_path: bld_path = os.path.join(sublime.packages_path(), builder_path) add_plugin_path(bld_path) try: builder = get_plugin('{0}_builder'.format(builder_name)) except NoSuchPluginException: sublime.error_message( "Cannot find builder {0}.\n" "Check your LaTeXTools Preferences".format(builder_name) ) self.window.run_command('hide_panel', {"panel": "output.latextools"}) return if builder_name == 'script' and script_commands: builder_platform_settings['script_commands'] = script_commands builder_settings[self.plat] = builder_platform_settings print(repr(builder)) self.builder = builder( self.file_name, self.output, engine, options, self.aux_directory, self.output_directory, self.tex_base, tex_directives, builder_settings, platform_settings ) # Now get the tex binary path from prefs, change directory to # that of the tex root file, and run! if path is not None: self.path = path else: self.path = get_texpath() or os.environ['PATH'] thread = CmdThread(self) thread.start() print(threading.active_count()) # setup the progress indicator display_message_length = long( get_setting('build_finished_message_length', 2.0) * 1000 ) # NB CmdThread will change the success message self.progress_indicator = ProgressIndicator( thread, 'Building', 'Build failed', display_message_length=display_message_length )
def parse_completions(view, line): # reverse line, copied from latex_cite_completions, very cool :) line = line[::-1] search = None # search static entries first search = TEX_INPUT_FILE_REGEX.match(line) if search: entries = _fillall_entries # then search dynamic entries if no static entries match else: dyn_entries, dyn_regex = _get_dyn_entries() if dyn_regex: search = dyn_regex.match(line) entries = dyn_entries # if no regex matched, cancel completions if not search: return [] try: # extract the first group and the prefix from the maching regex group = next(i for i, v in enumerate(search.groups()) if v is not None) entry = entries[group] except Exception as e: print("Error occurred while extracting entry from matching group.") print(e) return [] completions = [] if entry["type"] == "input": root = getTeXRoot.get_tex_root(view) if root: ana = analysis.get_analysis(root) tex_base_path = ana.tex_base_path(view.file_name()) completions = [] sub = { "root": root, "base": tex_base_path } if "post_regex" in entry: m = re.search(entry["post_regex"], line[::-1]) if m: for i in range(1, len(m.groups()) + 1): sub["_{0}".format(i)] = m.group(i) if "folder" in entry: folders = [] for folder in entry["folder"].split(";"): import string temp = string.Template(folder) folders.append(temp.safe_substitute(sub)) else: folders = [tex_base_path] for base_path in folders: output_directory = get_output_directory(view) aux_directory = get_aux_directory(view) completions.extend(get_file_list( root, entry["extensions"], entry.get("strip_extensions", []), base_path=base_path, output_directory=output_directory, aux_directory=aux_directory )) else: # file is unsaved completions = [] elif entry["type"] == "cached": cache = _get_cache() if cache is not None: completions = cache.get(entry["cache_name"]) else: print("Unknown entry type {0}.".format(entry["type"])) if "post_process" in entry: fkt = globals().get( "_post_process_{0}".format(entry["post_process"]), None) if fkt: completions = fkt(completions) return completions
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 run(self, file_regex="", program=None, builder=None, command=None, env=None, path=None, script_commands=None, update_phantoms_only=False, hide_phantoms_only=False, **kwargs): if update_phantoms_only: if self.show_errors_inline: self.update_phantoms() return if hide_phantoms_only: self.hide_phantoms() return # Try to handle killing with self.proc_lock: if self.proc: # if we are running, try to kill running process self.output("\n\n### Got request to terminate compilation ###") try: if sublime.platform() == 'windows': execute_command('taskkill /t /f /pid {pid}'.format( pid=self.proc.pid), use_texpath=False) else: os.killpg(self.proc.pid, signal.SIGTERM) except: print('Exception occurred while killing build') traceback.print_exc() self.proc = None return else: # either it's the first time we run, or else we have no running processes self.proc = None view = self.view = self.window.active_view() if _HAS_PHANTOMS: self.hide_phantoms() pref_settings = sublime.load_settings( "Preferences.sublime-settings") self.show_errors_inline = pref_settings.get( "show_errors_inline", True) if view.is_dirty(): print("saving...") view.run_command('save') # call this on view, not self.window if view.file_name() is None: sublime.error_message( 'Please save your file before attempting to build.') return self.file_name = getTeXRoot.get_tex_root(view) if not os.path.isfile(self.file_name): sublime.error_message(self.file_name + ": file not found.") return self.tex_base = get_jobname(view) self.tex_dir = os.path.dirname(self.file_name) if not is_tex_file(self.file_name): sublime.error_message( "%s is not a TeX source file: cannot compile." % (os.path.basename(view.file_name()), )) return # Output panel: from exec.py if not hasattr(self, 'output_view'): self.output_view = self.window.get_output_panel("latextools") output_view_settings = self.output_view.settings() output_view_settings.set("result_file_regex", file_regex) output_view_settings.set("result_base_dir", self.tex_dir) output_view_settings.set("line_numbers", False) output_view_settings.set("gutter", False) output_view_settings.set("scroll_past_end", False) if get_setting("highlight_build_panel", True, view=view): self.output_view.set_syntax_file( "Packages/LaTeXTools/LaTeXTools Console.hidden-tmLanguage") output_view_settings.set( "color_scheme", sublime.load_settings('Preferences.sublime-settings').get( 'color_scheme')) self.output_view.set_read_only(True) # Dumb, but required for the moment for the output panel to be picked # up as the result buffer self.window.get_output_panel("latextools") self.hide_panel_level = get_setting("hide_build_panel", "no_warnings", view=view) if self.hide_panel_level == "never": self.show_output_panel(force=True) self.plat = sublime.platform() if self.plat == "osx": self.encoding = "UTF-8" elif self.plat == "windows": self.encoding = getOEMCP() elif self.plat == "linux": self.encoding = "UTF-8" else: sublime.error_message("Platform as yet unsupported. Sorry!") return # Get platform settings, builder, and builder settings platform_settings = get_setting(self.plat, {}, view=view) self.display_bad_boxes = get_setting("display_bad_boxes", False, view=view) if builder is not None: builder_name = builder else: builder_name = get_setting("builder", "traditional", view=view) # Default to 'traditional' builder if builder_name in ['', 'default']: builder_name = 'traditional' # this is to convert old-style names (e.g. AReallyLongName) # to new style plugin names (a_really_long_name) builder_name = _classname_to_internal_name(builder_name) builder_settings = get_setting("builder_settings", {}, view=view) # override the command if command is not None: builder_settings.set("command", command) # parse root for any %!TEX directives tex_directives = parse_tex_directives( self.file_name, multi_values=['options'], key_maps={'ts-program': 'program'}) # determine the engine if program is not None: engine = program else: engine = tex_directives.get( 'program', builder_settings.get("program", "pdflatex")) engine = engine.lower() # Sanity check: if "strange" engine, default to pdflatex (silently...) if engine not in [ 'pdflatex', "pdftex", 'xelatex', 'xetex', 'lualatex', 'luatex' ]: engine = 'pdflatex' options = builder_settings.get("options", []) if isinstance(options, strbase): options = [options] if 'options' in tex_directives: options.extend(tex_directives['options']) # filter out --aux-directory and --output-directory options which are # handled separately options = [ opt for opt in options if (not opt.startswith('--aux-directory') and not opt.startswith( '--output-directory') and not opt.startswith('--jobname')) ] self.aux_directory = get_aux_directory(view) self.output_directory = get_output_directory(view) # Read the env option (platform specific) builder_platform_settings = builder_settings.get(self.plat, {}) if env is not None: self.env = env elif builder_platform_settings: self.env = builder_platform_settings.get("env", None) else: self.env = None # Safety check: if we are using a built-in builder, disregard # builder_path, even if it was specified in the pref file if builder_name in ['simple', 'traditional', 'script', 'basic']: builder_path = None else: # relative to ST packages dir! builder_path = get_setting("builder_path", "", view=view) if builder_path: bld_path = os.path.join(sublime.packages_path(), builder_path) add_plugin_path(bld_path) try: builder = get_plugin('{0}_builder'.format(builder_name)) except NoSuchPluginException: try: builder = get_plugin(builder_name) except NoSuchPluginException: sublime.error_message( "Cannot find builder {0}.\n" "Check your LaTeXTools Preferences".format(builder_name)) self.window.run_command('hide_panel', {"panel": "output.latextools"}) return if builder_name == 'script' and script_commands: builder_platform_settings['script_commands'] = script_commands builder_settings[self.plat] = builder_platform_settings print(repr(builder)) self.builder = builder(self.file_name, self.output, engine, options, self.aux_directory, self.output_directory, self.tex_base, tex_directives, builder_settings, platform_settings) # Now get the tex binary path from prefs, change directory to # that of the tex root file, and run! if path is not None: self.path = path else: self.path = get_texpath() or os.environ['PATH'] thread = CmdThread(self) thread.start() print(threading.active_count()) # setup the progress indicator display_message_length = long( get_setting('build_finished_message_length', 2.0, view=view) * 1000) # NB CmdThread will change the success message self.progress_indicator = ProgressIndicator( thread, 'Building', 'Build failed', display_message_length=display_message_length)
def run(self): # Retrieve root file and dirname. view = self.window.active_view() root_file = getTeXRoot.get_tex_root(view) if root_file is None: msg = \ 'Could not find TEX root. Please ensure that either you ' + \ 'have configured a TEX root in your project settings or ' + \ 'have a LaTeX document open.' sublime.status_message(msg) print(msg) return if not os.path.isfile(root_file): message = "Could not find TEX root {0}.".format(root_file) sublime.status_message(message) print(message) return # clear the cache try: cache.delete_local_cache(root_file) except: print('Error while trying to delete local cache') traceback.print_exc() aux_directory, aux_directory_setting = get_aux_directory( root_file, return_setting=True ) output_directory, output_directory_setting = get_output_directory( root_file, return_setting=True ) if aux_directory is not None: # we cannot delete the output directory on Windows in case # Sumatra is holding a reference to it if ( sublime.platform() != 'windows' or aux_directory != output_directory ): if aux_directory_setting.startswith('<<'): self._rmtree(aux_directory) else: self.delete_temp_files(aux_directory) if output_directory is not None: if output_directory_setting.startswith('<<'): # we cannot delete the output directory on Windows in case # Sumatra is holding a reference to it if sublime.platform() == 'windows': self._clear_dir(output_directory) else: self._rmtree(output_directory) else: self.delete_temp_files(output_directory) else: # if there is no output directory, we may need to clean files # in the main directory, even if aux_directory is used self.delete_temp_files(os.path.dirname(root_file)) sublime.status_message("Deleted temp files")
def run(self, cmd="", file_regex="", path=""): # Try to handle killing with self.proc_lock: if self.proc: # if we are running, try to kill running process self.output("\n\n### Got request to terminate compilation ###") if sublime.platform() == 'windows': startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW subprocess.call( 'taskkill /t /f /pid {pid}'.format(pid=self.proc.pid), startupinfo=startupinfo, shell=True ) else: os.killpg(self.proc.pid, signal.SIGTERM) self.proc = None return else: # either it's the first time we run, or else we have no running processes self.proc = None view = self.view = self.window.active_view() if view.is_dirty(): print ("saving...") view.run_command('save') # call this on view, not self.window if view.file_name() is None: sublime.error_message('Please save your file before attempting to build.') return self.file_name = getTeXRoot.get_tex_root(view) if not os.path.isfile(self.file_name): sublime.error_message(self.file_name + ": file not found.") return self.tex_base = get_jobname(view) tex_dir = os.path.dirname(self.file_name) if not is_tex_file(self.file_name): sublime.error_message("%s is not a TeX source file: cannot compile." % (os.path.basename(view.file_name()),)) return # Output panel: from exec.py if not hasattr(self, 'output_view'): self.output_view = self.window.get_output_panel("exec") # Dumb, but required for the moment for the output panel to be picked # up as the result buffer self.window.get_output_panel("exec") self.output_view.settings().set("result_file_regex", "^([^:\n\r]*):([0-9]+):?([0-9]+)?:? (.*)$") # self.output_view.settings().set("result_line_regex", line_regex) self.output_view.settings().set("result_base_dir", tex_dir) self.window.run_command("show_panel", {"panel": "output.exec"}) self.output_view.settings().set("result_file_regex", file_regex) self.plat = sublime.platform() if self.plat == "osx": self.encoding = "UTF-8" elif self.plat == "windows": self.encoding = getOEMCP() elif self.plat == "linux": self.encoding = "UTF-8" else: sublime.error_message("Platform as yet unsupported. Sorry!") return # Get platform settings, builder, and builder settings platform_settings = get_setting(self.plat, {}) builder_name = get_setting("builder", "traditional") self.hide_panel_level = get_setting("hide_build_panel", "never") self.display_bad_boxes = get_setting("display_bad_boxes", False) # This *must* exist, so if it doesn't, the user didn't migrate if builder_name is None: sublime.error_message("LaTeXTools: you need to migrate your preferences. See the README file for instructions.") self.window.run_command('hide_panel', {"panel": "output.exec"}) return # Default to 'traditional' builder if builder_name in ['', 'default']: builder_name = 'traditional' # this is to convert old-style names (e.g. AReallyLongName) # to new style plugin names (a_really_long_name) builder_name = _classname_to_internal_name(builder_name) builder_settings = get_setting("builder_settings", {}) # parse root for any %!TEX directives tex_directives = parse_tex_directives( self.file_name, multi_values=['options'], key_maps={'ts-program': 'program'} ) # determine the engine engine = tex_directives.get('program', builder_settings.get("program", "pdflatex")) engine = engine.lower() # Sanity check: if "strange" engine, default to pdflatex (silently...) if engine not in [ 'pdflatex', "pdftex", 'xelatex', 'xetex', 'lualatex', 'luatex' ]: engine = 'pdflatex' options = builder_settings.get("options", []) if isinstance(options, strbase): options = [options] if 'options' in tex_directives: options.extend(tex_directives['options']) # filter out --aux-directory and --output-directory options which are # handled separately options = [opt for opt in options if ( not opt.startswith('--aux-directory') and not opt.startswith('--output-directory') and not opt.startswith('--jobname') )] self.aux_directory = get_aux_directory(self.file_name) self.output_directory = get_output_directory(self.file_name) # Read the env option (platform specific) builder_platform_settings = builder_settings.get(self.plat) if builder_platform_settings: self.env = builder_platform_settings.get("env", None) else: self.env = None # Now actually get the builder builder_path = get_setting("builder_path", "") # relative to ST packages dir! # Safety check: if we are using a built-in builder, disregard # builder_path, even if it was specified in the pref file if builder_name in ['simple', 'traditional', 'script', 'basic']: builder_path = None if builder_path: bld_path = os.path.join(sublime.packages_path(), builder_path) add_plugin_path(bld_path) try: builder = get_plugin('{0}_builder'.format(builder_name)) except NoSuchPluginException: sublime.error_message("Cannot find builder " + builder_name + ".\n" \ "Check your LaTeXTools Preferences") self.window.run_command('hide_panel', {"panel": "output.exec"}) return print(repr(builder)) self.builder = builder( self.file_name, self.output, engine, options, self.aux_directory, self.output_directory, self.tex_base, tex_directives, builder_settings, platform_settings ) # Now get the tex binary path from prefs, change directory to # that of the tex root file, and run! self.path = platform_settings['texpath'] os.chdir(tex_dir) CmdThread(self).start() print(threading.active_count())
def parse_completions(view, line): # reverse line, copied from latex_cite_completions, very cool :) line = line[::-1] search = None # search static entries first search = TEX_INPUT_FILE_REGEX.match(line) if search: entries = _fillall_entries # then search dynamic entries if no static entries match else: dyn_entries, dyn_regex = _get_dyn_entries() if dyn_regex: search = dyn_regex.match(line) entries = dyn_entries # if no regex matched, cancel completions if not search: return [] try: # extract the first group and the prefix from the maching regex group = next(i for i, v in enumerate(search.groups()) if v is not None) entry = entries[group] except Exception as e: print("Error occurred while extracting entry from matching group.") print(e) return [] completions = [] if entry["type"] == "input": root = getTeXRoot.get_tex_root(view) if root: ana = analysis.get_analysis(root) tex_base_path = ana.tex_base_path(view.file_name()) completions = [] sub = {"root": root, "base": tex_base_path} if "post_regex" in entry: m = re.search(entry["post_regex"], line[::-1]) if m: for i in range(1, len(m.groups()) + 1): sub["_{0}".format(i)] = m.group(i) if "folder" in entry: folders = [] for folder in entry["folder"].split(";"): import string temp = string.Template(folder) folders.append(temp.safe_substitute(sub)) else: folders = [tex_base_path] for base_path in folders: output_directory = get_output_directory(root) aux_directory = get_aux_directory(root) completions.extend( get_file_list(root, entry["extensions"], entry.get("strip_extensions", []), base_path=base_path, output_directory=output_directory, aux_directory=aux_directory)) else: # file is unsaved completions = [] elif entry["type"] == "cached": cache = _get_cache() if cache is not None: completions = cache.get(entry["cache_name"]) else: print("Unknown entry type {0}.".format(entry["type"])) if "post_process" in entry: fkt = globals().get("_post_process_{0}".format(entry["post_process"]), None) if fkt: completions = fkt(completions) return completions