def find_image(tex_root, file_name, tex_file_name=None): ana = analysis.get_analysis(tex_root) base_path = ana.tex_base_path(tex_file_name) image_types = get_setting( "image_types", [ "png", "pdf", "jpg", "jpeg", "eps" ]) file_path = os.path.normpath( os.path.join(base_path, file_name)) _, extension = os.path.splitext(file_path) extension = extension[1:] # strip the leading point if not extension: for ext in image_types: test_path = file_path + "." + ext print("Test file: '{0}'".format(test_path)) if os.path.exists(test_path): extension = ext file_path = test_path print("Found file: '{0}'".format(test_path)) break if not os.path.exists(file_path): return None return file_path
def get_packages(self): packages = get_setting('cwl_list', [ "latex-document.cwl", "tex.cwl", "latex-dev.cwl", "latex-209.cwl", "latex-l2tabu.cwl", "latex-mathsymbols.cwl" ]) # autoload packages by scanning the document if get_setting('cwl_autoload', True): root = get_tex_root(sublime.active_window().active_view()) if root is not None: doc = analysis.get_analysis(root) # really, there should only be one documentclass packages.extend([ 'class-{0}'.format(documentclass.args) for documentclass in doc.filter_commands( 'documentclass', analysis.ONLY_PREAMBLE | analysis.ONLY_COMMANDS_WITH_ARGS) ]) packages.extend([ package.args for package in doc.filter_commands( 'usepackage', analysis.ONLY_PREAMBLE | analysis.ONLY_COMMANDS_WITH_ARGS) ]) # TODO - Attempt to read current buffer return packages
def make_compl(): ana = analysis.get_analysis(tex_root) if comp_type == "glo": comp = _get_glo_completions(ana, prefix, ac) elif comp_type == "acr": comp = _get_acr_completions(ana, prefix, ac) else: comp = [] return comp
def _find_bib_files(): # the final list of bib files result = [] # a list of candidates bib files to check resources = [] # load the analysis doc = analysis.get_analysis(root) # we use ALL_COMMANDS here as any flag will filter some command # we want to support flags = analysis.ALL_COMMANDS | analysis.ONLY_COMMANDS_WITH_ARGS for c in doc.filter_commands( _bibfile_filter, flags=flags ): # process the matching commands # \begin{refsection} / \newrefsection # resource is specified as an optional argument argument if ( c.command == 'begin' or c.command == 'newrefsection' ): # NB if the resource doesn't end with .bib, assume its a label # for a bibliography defined elsewhere or a non-.bib file # which we don't handle resources.extend([ s.strip() for s in (c.optargs or '').split(',') if s.endswith('.bib')]) # \bibliography / \nobibliography elif c.command in MULTI_BIBCOMMANDS: for s in c.args.split(','): s = s.strip() if not s: continue if not s.endswith('.bib'): s += '.bib' resources.append(s) # standard biblatex ocmmands else: # bib file must be followed by .bib if c.args.endswith('.bib'): resources.append(c.args) # extract absolute filepath for each bib file rootdir = os.path.dirname(root) for res in resources: # We join with rootdir, the dir of the master file candidate_file = os.path.normpath(os.path.join(rootdir, res)) # if the file doesn't exist, search the default tex paths if not os.path.exists(candidate_file): candidate_file = kpsewhich(res, 'mlbib') if candidate_file is not None and os.path.exists(candidate_file): result.append(candidate_file) # remove duplicates return list(set(result))
def _find_bib_files(): # the final list of bib files result = [] # a list of candidates bib files to check resources = [] # load the analysis doc = analysis.get_analysis(root) # we use ALL_COMMANDS here as any flag will filter some command # we want to support flags = analysis.ALL_COMMANDS | analysis.ONLY_COMMANDS_WITH_ARGS for c in doc.filter_commands(_bibfile_filter, flags=flags): # process the matching commands # \begin{refsection} / \newrefsection # resource is specified as an optional argument argument if (c.command == 'begin' or c.command == 'newrefsection'): # NB if the resource doesn't end with .bib, assume its a label # for a bibliography defined elsewhere or a non-.bib file # which we don't handle resources.extend([ s.strip() for s in (c.optargs or '').split(',') if s.endswith('.bib') ]) # \bibliography / \nobibliography elif c.command in MULTI_BIBCOMMANDS: for s in c.args.split(','): s = s.strip() if not s: continue if not s.endswith('.bib'): s += '.bib' resources.append(s) # standard biblatex commands else: # bib file must be followed by .bib if c.args.endswith('.bib'): resources.append(c.args) # extract absolute filepath for each bib file rootdir = os.path.dirname(root) for res in resources: # We join with rootdir, the dir of the master file candidate_file = os.path.normpath(os.path.join(rootdir, res)) # if the file doesn't exist, search the default tex paths if not os.path.exists(candidate_file): candidate_file = kpsewhich(res, 'mlbib') if candidate_file is not None and os.path.exists(candidate_file): result.append(candidate_file) # remove duplicates return list(set(result))
def _jumpto_cite(view, com_reg, pos): tex_root = get_tex_root(view) bib_key = _get_selected_arg(view, com_reg, pos) if tex_root is None or not bib_key: return message = "Scanning bibliography files for key '{0}'...".format(bib_key) print(message) sublime.status_message(message) base_dir = os.path.dirname(tex_root) ana = analysis.get_analysis(tex_root) bib_commands = ana.filter_commands( ["bibliography", "nobibliography", "addbibresource"]) for bib_command in bib_commands: for bib_file in jumpto_tex_file._split_bib_args(bib_command.args): if not os.path.splitext(bib_file)[1]: bib_file += ".bib" bib_file = os.path.join(base_dir, bib_file) try: file_content = utils.read_file_unix_endings(bib_file) start = file_content.find(bib_key) end = start + len(bib_key) # check that we found the entry and we are not inside a word if (start == -1 or file_content[start - 1:start].isalnum() or file_content[end:end + 1].isalnum()): continue region = sublime.Region(start, end) message = "Jumping to bibliography key '{0}'.".format(bib_key) print(message) sublime.status_message(message) utils.open_and_select_region(view, bib_file, region) return except Exception as e: print("Error occurred opening file {0}".format(bib_file)) print(e) continue message = "Entry '{0}' not found in bibliography.".format(bib_key) print(message) sublime.status_message(message)
def find_image(tex_root, file_name, tex_file_name=None): ana = analysis.get_analysis(tex_root) base_path = ana.tex_base_path(tex_file_name) image_types = get_setting("image_types", ["png", "pdf", "jpg", "jpeg", "eps"]) file_path = os.path.normpath(os.path.join(base_path, file_name)) _, extension = os.path.splitext(file_path) extension = extension[1:] # strip the leading point if not extension: for ext in image_types: test_path = file_path + "." + ext print("Test file: '{0}'".format(test_path)) if os.path.exists(test_path): extension = ext file_path = test_path print("Found file: '{0}'".format(test_path)) break if not os.path.exists(file_path): return None return file_path
def _opt_jumpto_self_def_command(view, com_reg): tex_root = get_tex_root(view) if tex_root is None: return False # check in the cache whether we should jump (is command self defined) newcommand_keywords = ["newcommand", "renewcommand"] command = "\\" + com_reg.group("command") cana = analysis.get_analysis(tex_root) new_commands = cana.filter_commands(newcommand_keywords) if command not in [c.args for c in new_commands]: message = "Command not defined (cached) '{0}'".format(command) print(message) return False message =\ "Scanning document for command definition of '{0}'".format(command) print(message) sublime.status_message(message) # analyze the document to retrieve the correct position of the # command definition ana = analysis.analyze_document(tex_root) new_commands = ana.filter_commands(newcommand_keywords) try: new_com_def = next(ifilter(lambda c: c.args == command, new_commands)) except: message = "Command not self defined '{0}'".format(command) print(message) return False file_name = new_com_def.file_name region = new_com_def.args_region message = "Jumping to definition of '{0}'".format(command) print(message) sublime.status_message(message) utils.open_and_select_region(view, file_name, region) return True
def get_packages(self): packages = get_setting('cwl_list', [ "latex-document.cwl", "tex.cwl", "latex-dev.cwl", "latex-209.cwl", "latex-l2tabu.cwl", "latex-mathsymbols.cwl" ]) # autoload packages by scanning the document if get_setting('cwl_autoload', True): root = get_tex_root(sublime.active_window().active_view()) if root is not None: doc = analysis.get_analysis(root) # really, there should only be one documentclass packages.extend([ 'class-{0}'.format(documentclass.args) for documentclass in doc.filter_commands( 'documentclass', analysis.ONLY_PREAMBLE | analysis.ONLY_COMMANDS_WITH_ARGS ) ]) packages.extend([ package.args for package in doc.filter_commands( 'usepackage', analysis.ONLY_PREAMBLE | analysis.ONLY_COMMANDS_WITH_ARGS ) ]) # TODO - Attempt to read current buffer return packages
def make_completions(): ana = analysis.get_analysis(tex_root) return _make_own_command_completion(ana, is_math)
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 _jumpto_tex_file(view, window, tex_root, file_name, auto_create_missing_folders, auto_insert_root): root_base_path, root_base_name = os.path.split(tex_root) ana = analysis.get_analysis(tex_root) base_path = ana.tex_base_path(view.file_name()) _, ext = os.path.splitext(file_name) if not ext: file_name += '.tex' # clean-up any directory manipulating components file_name = os.path.normpath(file_name) containing_folder, file_name = os.path.split(file_name) # allow absolute paths on \include or \input isabs = os.path.isabs(containing_folder) if not isabs: containing_folder = os.path.normpath( os.path.join(base_path, containing_folder)) # create the missing folder if auto_create_missing_folders and\ not os.path.exists(containing_folder): try: os.makedirs(containing_folder) except OSError: # most likely a permissions error print('Error occurred while creating path "{0}"'.format( containing_folder)) traceback.print_last() else: print('Created folder: "{0}"'.format(containing_folder)) if not os.path.exists(containing_folder): sublime.status_message("Cannot open tex file as folders are missing") return is_root_inserted = False full_new_path = os.path.join(containing_folder, file_name) if auto_insert_root and not os.path.exists(full_new_path): if isabs: root_path = tex_root else: root_path = os.path.join( os.path.relpath(root_base_path, containing_folder), root_base_name) # Use slashes consistent with TeX's usage if sublime.platform() == 'windows' and not isabs: root_path = root_path.replace('\\', '/') root_string = '%!TEX root = {0}\n'.format(root_path) try: with codecs.open(full_new_path, "w", "utf8")\ as new_file: new_file.write(root_string) is_root_inserted = True except OSError: print('An error occurred while creating file "{0}"'.format( file_name)) traceback.print_last() # open the file print("Open the file '{0}'".format(full_new_path)) # await opening and move cursor to end of the new view # (does not work on st2) if _ST3 and auto_insert_root and is_root_inserted: cursor_pos = len(root_string) new_region = sublime.Region(cursor_pos, cursor_pos) utils.open_and_select_region(view, full_new_path, new_region) else: window.open_file(full_new_path)
def make_completions(): ana = analysis.get_analysis(tex_root) return _make_own_env_completion(ana)
def find_labels_in_files(root, labels): doc = analysis.get_analysis(root) for command in doc.filter_commands('label'): labels.append(command.args)
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
def _jumpto_tex_file(view, window, tex_root, file_name, auto_create_missing_folders, auto_insert_root): root_base_path, root_base_name = os.path.split(tex_root) ana = analysis.get_analysis(tex_root) base_path = ana.tex_base_path(view.file_name()) _, ext = os.path.splitext(file_name) if not ext: file_name += '.tex' # clean-up any directory manipulating components file_name = os.path.normpath(file_name) containing_folder, file_name = os.path.split(file_name) # allow absolute paths on \include or \input isabs = os.path.isabs(containing_folder) if not isabs: containing_folder = os.path.normpath( os.path.join(base_path, containing_folder)) # create the missing folder if auto_create_missing_folders and\ not os.path.exists(containing_folder): try: os.makedirs(containing_folder) except OSError: # most likely a permissions error print('Error occurred while creating path "{0}"' .format(containing_folder)) traceback.print_last() else: print('Created folder: "{0}"'.format(containing_folder)) if not os.path.exists(containing_folder): sublime.status_message( "Cannot open tex file as folders are missing") return is_root_inserted = False full_new_path = os.path.join(containing_folder, file_name) if auto_insert_root and not os.path.exists(full_new_path): if isabs: root_path = tex_root else: root_path = os.path.join( os.path.relpath(root_base_path, containing_folder), root_base_name) # Use slashes consistent with TeX's usage if sublime.platform() == 'windows' and not isabs: root_path = root_path.replace('\\', '/') root_string = '%!TEX root = {0}\n'.format(root_path) try: with codecs.open(full_new_path, "w", "utf8")\ as new_file: new_file.write(root_string) is_root_inserted = True except OSError: print('An error occurred while creating file "{0}"' .format(file_name)) traceback.print_last() # open the file print("Open the file '{0}'".format(full_new_path)) # await opening and move cursor to end of the new view # (does not work on st2) if _ST3 and auto_insert_root and is_root_inserted: cursor_pos = len(root_string) new_region = sublime.Region(cursor_pos, cursor_pos) utils.open_and_select_region(view, full_new_path, new_region) else: window.open_file(full_new_path)