% File: latex.sl -*- mode: SLang; mode: fold -*- % % Copyright (c) % until 2003 Guido Gonzato (as Latex4Jed) % 2003--2007 Jörg Sommer % $Id: latex.sl 205 2007-09-08 13:38:06Z joerg $ % % -*- This file is part of Jörg's LaTeX Mode (JLM) -*- % % Description: In this file are all functions for composing, viewing, % printing and any related problem. All what have to do % with an external program and a latex file. % % License: This program is free software; you can redistribute it and/or % modify it under the terms of the GNU General Public License as % published by the Free Software Foundation; either version 2 of % the License, or (at your option) any later version. % % This program is distributed in the hope that it will be % useful, but WITHOUT ANY WARRANTY; without even the implied % warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR % PURPOSE. See the GNU General Public License for more details. %!Fix me -- TODO: % font_resize(n): n variable machen % indent line in Verbatim environment like comments % use replace_chars() % right, left bei | % g\bigl( ... ) % \{ confuses indention % auto-sizing of braces, e.g. "( ()" + ")" -> "\big( () \big)" % customization stuff % move to comment.sl % preview of equations with UTF-8 % dialog for open subfiles (\input, \include) if (length(where("latex" == _get_namespaces()))) use_namespace("latex"); else implements("latex"); #ifnexists profile_on % profiling does not work with stack check enabled. autoload("Global->enable_stack_check", "stkcheck"); try { enable_stack_check(); } catch OpenError: {} % stkcheck not found in the path #endif static variable MODE="LaTeX"; define debug_msg(msg) { #if (BATCH) message(msg); #else whatbuf(); setbuf("*traceback*"); eob(); variable x = make_printable_string(string(msg)); insert( substr(x, 2, strlen(x) - 2) ); newline(); setbuf( () ); #endif } define debug_pos() { variable arg; if (_NARGS) arg = string( () ); else arg = ""; debug_msg("line = $what_line, col = "$ + string(what_column()) + "; $arg"$); } define debug_print_buf() { push_spot(); bob(); push_mark(); eob(); message( bufsubstr() ); pop_spot(); } public variable Key_Enter = "\r", Key_Space = " "; foreach ("latex_external->" + ["bibtex", "clearup", "compose", "makeindex", "mrproper", "pop_log_file", "print", "select_master_file", "cust_view", "view", "jump_to_master_buffer", "show_bibtex_log", "show_mkidx_log"]) { autoload((), "latex_external.sl"); } foreach ("latex_conv->" + ["colon", "german_lat1", "german_utf8", "native_lat1", "native_utf8", "ltx209_ltx2e"]) { autoload((), "latex_conv.sl"); } foreach ("latex->" + ["pst_update_pic_size", "pst_move_points"]) { autoload((), "latex_pst.sl"); } foreach ("latex->typo_" + ["abbrev", "dots", "german_decimal_point", "hyphen", "percent", "slash"]) { autoload((), "latex_typo.sl"); } #if (_jed_version < 9919) require("x-keydefs"); require("read_with_description"); #else require("x-keydefs", "Global"); require("read_with_description", "Global"); #endif %!%+ %\variable{String_Type LaTeX_Template_Dir} %\synopsis{Directories of template files} %\description % You can insert text blocks via Mode->Templates or ^ct. These blocks % are read from a file that is placed in a directory in this comma % separated list. % % The default is Jed_Home_Directory/latex-templ %\seealso{templ_insert()} %!%- custom_variable("LaTeX_Template_Dir", path_concat(Jed_Home_Directory, "latex-templ")); %!%+ %\variable{String_Type LaTeX_Default_Packages} %\synopsis{List of packages to insert when a template will be inserted} %\description % You can insert text blocks via Mode->Templates or ^ct. These blocks can % include the special sequences %:default:pkgs:% that is replaced by a list % of \\usepackage commands with the packages given with this variable. % % The default is "inputenc:fontenc:babel:fixltx2e:microtype". %\seealso{templ_insert(), insert_pkgs()} %!%- % http://homepage.ruhr-uni-bochum.de/Georg.Verweyen/latexfuerword.html custom_variable("LaTeX_Default_Packages", "inputenc:babel:fontenc:fixltx2e:microtype"); %!%+ %\variable{String_Type LaTeX_Default_Class_Options} %\synopsis{Default class options for a template} %\description % You can insert text blocks via Mode->Templates or ^ct. These blocks can % include one of the special sequences %:default:classopt:,% or % %:default:classopt:[% that is replaced by the content of this variable. % % The default is "draft". %\seealso{templ_insert()} %!%- custom_variable("LaTeX_Default_Class_Options", "draft"); %!%+ %\variable{Integer_Type LaTeX_Auto_Space_After_Commands} %\synopsis{Insert a space after a command, if a letter is inserted} %\description % If this variable is unequal 0 and you insert a command with % cmd_insert() which have no arguments the cursor is placed after this % command. If you then enter a letter, a space is inserted, because would % treat LaTeX this as part of command which is normally an error. % % The default is 1, which means to insert a space, if necessary. %\seealso{templ_insert()} %!%- custom_variable("LaTeX_Auto_Space_After_Commands", 1); %!%+ %\variable{Integer_Type LaTeX_Indent_First} %\synopsis{Defines the amount of spaces used for first indention level} %\description % Defines the default indention in all environments and open braces. % % \begin{xyz} % text indented by LaTeX_Indent_First % \cmd{foo% indented by LaTeX_Indent_First % bar} indented a second time by LaTeX_Indent_First % \end{xyz} % % The default is 2. %\seealso{LaTeX_Indent_Continued} %\seealso{LaTeX_Indent_Item} %!%- custom_variable("LaTeX_Indent_First", 2); %!%+ %\variable{Integer_Type LaTeX_Indent_Continued} %\synopsis{Defines the amount of spaces added for each deeper indention level} %\description % Some environments like table, array, align or gather don't allow empty % lines to structure the LaTeX code. JLM tries to detect the end of line % in the output and helps structuring the code in this way that all text % in the same line in the output, but on different lines in the code is % indented deeper than the first line. % % \begin{tabular}{l} % text this line is indented by LaTeX_Indent_First spaces % continued l. LaTeX_Indent_First + LaTeX_Indent_Continued % third line\\ LaTeX_Indent_First + LaTeX_Indent_Continued % text LaTeX_Indent_First % \end{tabular} % % The default is 3. %\seealso{LaTeX_Indent_First} %\seealso{LaTeX_Indent_Item} %!%- custom_variable("LaTeX_Indent_Continued", 3); %!%+ %\variable{Integer_Type LaTeX_Indent_Item} %\synopsis{Defines the amount of spaces used to indent \item} %\description % \begin{itemize} % \item indented by LaTeX_Indent_Item % text indented by LaTeX_Indent_First % \end{itemize} % % The default is 1. %\seealso{LaTeX_Indent_Continued} %\seealso{LaTeX_Indent_First} %!%- custom_variable("LaTeX_Indent_Item", 1); %!%+ %\variable{Integer_Type LaTeX_Register_New} %\synopsis{Ask the user about informations for new environments/commands} %\description % When a environment or command is inserted with *_prompt and % it is not known, the user is prompted for the missing informations % like number of arguments, needed packages and a description. % % The default is 1. %!%- custom_variable("LaTeX_Register_New", 1); %!%+ %\variable{String_Type LaTeX_File_New} %\synopsis{Name of a file, where options of new cmds, envs and pkgs are saved} %\description % When a command, environment or package is inserted with *_prompt and % this variable is a non-empty string, it is used as the name of a file % where a command is appended to save the new data. Later, you can load % this file, with evalfile(), to import your config. % % The default is NULL. %\seealso{LaTeX_Register_New} %!%- custom_variable("LaTeX_File_New", NULL); %!%+ %\variable{Integer_Type LaTeX_Typo_Active} %\synopsis{Enables/Disables typographic functions} %\description % Setting this variable to 0 disables all typographic functions. They % might be work for you language or do silly things, so you don't want % to use them. Every value different from 0 enables the functions. % % The default is 1. %!%- custom_variable("LaTeX_Typo_Active", 1); %!%+ %\variable{Integer_Type LaTeX_Typo_Word_Size} %\synopsis{Defines the lowest number of characters in a word} %\description % Some typographic functions, like typo_slash(), do different things % depending on the leading/following number of characters is more or % less than \var{LaTeX_Typo_Word_Size}. The typo_slash() function, e.g., % do not replace the / by \slash{} if the number of characters before % the / is not at least \var{LaTeX_Typo_Word_Size}. % % The default is 4. %!%- custom_variable("LaTeX_Typo_Word_Size", 4); %%%%%%%%%% % % Declarations needed somewhere before the definition % static define array_edit_column_format() { throw NotImplementedError; } static define boenv() { throw NotImplementedError; } static define bsearch_matching_brace() { throw NotImplementedError; } static define cmd_insert() { throw NotImplementedError; } static define cmd_parse_args() { throw NotImplementedError; } static define env_name() { throw NotImplementedError; } static define eoenv() { throw NotImplementedError; } private define pkg_find() { throw NotImplementedError; } static define is_escaped() { throw NotImplementedError; } static define texdoc() { throw NotImplementedError; } %%%%%%%%%% % % Some constants % static variable TeX_Command_Chars = "a-zA-Z@*"; %%%%%%%%%% % % Tools % static define is_commented() { % When parse_to_point() says inside a string we can't trust him. The X in % the following text is not inside of a comment for parse_to_point() % $\alpha % X % \beta$ % But parse_to_point() has no informations (define_syntax()) about % strings, so this should not be a problem. return parse_to_point() == -2; } private define bocomment() { !if ( is_commented() ) return 0; while ( andelse {bfind_char('%')} {is_commented()} ); return 1; } private define chop_star(str) { if (andelse {str != NULL} {str[-1] == '*'}) return str[[:-2]]; else return str; } static define is_escaped() { variable pnt = _get_point(); bskip_chars("\\"); variable pnt2 = _get_point(); _set_point(pnt); return (pnt - pnt2) mod 2 == 1; } private define trim() { skip_white(); push_mark(); bskip_white(); if ( looking_at_char(' ') and is_escaped() ) () = right(1); del_region(); } static variable verbatim_commands = "bibitem,cite,href,include,includegraphics,input,label,nolinkurl,ref,url"; static variable verbatim_environments = "verbatim,Verbatim"; static define is_verbatim() { if ( is_commented() ) return 1; variable start_mark = create_user_mark(); try { bsearch_matching_brace(); push_mark(); bskip_chars(TeX_Command_Chars); if ( blooking_at("\\") ) { if ( is_list_element(verbatim_commands, bufsubstr(), ',') ) return 1; } else pop_mark(0); } catch DataError; finally goto_user_mark(start_mark); try { if ( bfind("\\verb") ) { () = right(5); what_char(); () = right(1); if ( ffind_char( () ) ) () = right(1); else return 1; if (create_user_mark() > start_mark) return 1; } } finally goto_user_mark(start_mark); variable e_name = env_name(); if ( andelse {e_name != NULL} {is_list_element(verbatim_environments, __tmp(e_name), ',')} ) return 1; return 0; } private variable math_environments = "gather,align,flalign,alignat,multline"; private variable anti_math_commands = "text,mbox,intertext,label,raisebox,footnote,makebox"; static define is_math() { if ( is_verbatim() ) return 0; push_spot(); try { variable math_open = 0, math_seen = 0; forever { bskip_chars("^{}$_^[]"); !if ( left(1) ) % bobp() == TRUE return math_open; variable is_bracket = what_char() == '[' or what_char() == ']'; if ( orelse {bocomment()} {is_escaped() != is_bracket} ) continue; switch ( what_char() ) { case '$': math_open = not math_open; math_seen = 1; } { case '^' or case '_': return not math_open; } { case '{': if (math_seen) return math_open; % This is for \raisebox, because the text is in the % second argument while ( left(1) and looking_at_char('}') ) bsearch_matching_brace(); () = right(1); push_mark(); bskip_chars(TeX_Command_Chars); variable cmd_name = bufsubstr(); () = left(1); if ( looking_at_char('\\') and is_list_element(anti_math_commands, cmd_name, ',') ) return 0; } { case '}': bsearch_matching_brace(); push_mark(); bskip_chars(TeX_Command_Chars); variable cmd = chop_star( bufsubstr() ); () = left(1); if ( looking_at_char('\\') ) { switch (cmd) { case "begin": () = right(7); push_mark(); () = ffind_char('}'); variable e_name = bufsubstr(); if (e_name == "document") return math_open; if ( is_list_element(math_environments, chop_star(e_name), ',') ) return 1; if ( is_list_element(verbatim_environments, chop_star(e_name), ',') ) return 0; if (math_seen) return math_open; () = left(strlen(e_name) + 7); } { case "end": () = right(5); push_mark(); () = ffind_char('}'); if ( is_list_element("document,"+math_environments, chop_star(bufsubstr()), ',') ) return math_open; () = bfind("\\end"); boenv(); } { is_list_element("chapter,section,subsection,subsubsection,paragraph", cmd, ','): return math_open; } { is_list_element("frac,overline,underbrace", cmd, ','): % cmd_list[cmd].math return not math_open; } } else () = right(1); } { case '[': return 1; } { case ']': return math_open; } } } finally pop_spot(); } private define str_compress_tex(str) { variable a_str = bstring_to_array(str), ins = -1, i; for (i=0; i < length(a_str); ++i) { switch (a_str[i]) { case '%': % "%.*\n[ \t]*" -> "" if (ins < 0) ins = i; do ++i; while (andelse {i < length(a_str)} {a_str[i] != '\n'}); do ++i; while (andelse {i < length(a_str)} {a_str[i] == '\t' or a_str[i] == ' '}); --i; continue; } { case '\n': % "\n[ \t]*" -> " " if (ins < 0) ins = i; do ++i; while (andelse {i < length(a_str)} {a_str[i] == '\t' or a_str[i] == ' '}); a_str[ins] = ' '; ++ins; --i; continue; } { case '\\': % escape seqences \% and \ if (ins >= 0) { a_str[ins] = a_str[i]; ++ins; ++i; if (i >= length(a_str)) break; } } { case ' ' or case '\t': variable old_i = i; while (andelse {i+1 < length(a_str)} {a_str[i+1] == '\t' or a_str[i+1] == ' '}) ++i; if (i - old_i > 0 and ins < 0) ins = old_i; } if (ins >= 0) { a_str[ins] = a_str[i]; ++ins; } } if (ins == -1) return str; else return unpack("s$ins"$, array_to_bstring(a_str)); } static define fsearch_matching_brace() { if ( is_commented() ) throw UsageError, "Starting inside of a comment is not possible"; variable start_mark = create_user_mark(), open_lbraces = list_new(); if ( looking_at_char('}') ) return; forever { () = right(1); skip_chars("^{}"); !if ( looking_at_char('{') or looking_at_char('}') ) break; if ( is_commented() ) { eol(); continue; } if ( is_escaped() ) continue; switch ( what_char() ) { case '{': list_append(open_lbraces, [what_line, what_column()], -1); } { case '}': if (length(open_lbraces) == 0) return; list_delete(open_lbraces, -1); } } goto_user_mark(start_mark); if (length(open_lbraces) > 0) throw DataError, "No matching } found for { in line " + string(open_lbraces[-1][0]) + " column " + string(open_lbraces[-1][1]); else throw DataError, "No matching } found"; } static define bsearch_matching_brace() { if ( is_commented() ) throw UsageError, "Starting inside of a comment is not possible"; variable start_mark = create_user_mark(), open_rbraces = list_new(); forever { bskip_chars("^{}"); !if ( left(1) ) % bobp() == TRUE break; if ( orelse {bocomment()} {is_escaped()} ) continue; switch ( what_char() ) { case '{': if (length(open_rbraces) == 0) return; list_delete(open_rbraces, -1); push_mark(); bskip_chars(TeX_Command_Chars); variable cmd = chop_star(bufsubstr()); if ( andelse {strlen(cmd) > 0} {blooking_at("\\")} ) { () = left(1); if (cmd == "end") boenv(); else if ( is_list_element("begin,section,chapter,subsection,subsubsection,paragraph", cmd, ',') ) break; } } { case '}': list_append(open_rbraces, [what_line, what_column()], -1); } } goto_user_mark(start_mark); if (length(open_rbraces) > 0) throw DataError, "No matching } found for { in line " + string(open_rbraces[-1][0]) + " column " + string(open_rbraces[-1][1]); else throw DataError, "No matching } found"; } static define search_not_commented(func, arg, skip) { forever { variable ret = @func(arg); !if ( andelse {ret} {is_commented()} ) return ret; () = right(skip); } } private define make_sorted_desc_list(list) { variable compl = {}, keys = assoc_get_keys(list); foreach ( keys[array_sort(keys)] ) { variable key = (); list_append(compl, list[key], -1); } return compl; } %%%%%%%%%% % % Stuff for \documentclass[]{} % private define doc_find() { bob(); !if ( search_not_commented(&fsearch, "\\documentclass", 1) ) throw DataError, "Your document misses a \\documentclass"; () = right(14); % skip \documentclass } private define doc_options_class() { variable old_buf = whatbuf(); latex_external->jump_to_master_buffer(); push_spot(); try { doc_find(); variable args, class; (args,class) = cmd_parse_args(1,1); if (length(args) == 0) return ("", class[0]); else return (str_delete_chars(args[0], "\\s"), class[0]); } finally { pop_spot(); setbuf(old_buf); } } %%%%%%%%%% % % Package stuff % typedef struct { options, desc, texdoc, hook, compl } Pkg_Type; private variable pkg_list = Assoc_Type[Pkg_Type]; static define pkg_register(name, opt, desc, texdoc, hook) { try { % This is a tricky way to check if all variables are strings () = _typeof([name, desc, texdoc, opt, ""]); } catch TypeMismatchError: { throw InvalidParmError, "One of the given arguments has invalid type"; } if (strlen(name) == 0) throw InvalidParmError, "name can not be empty"; if (hook != NULL and typeof(hook) != Ref_Type) throw InvalidParmError, "The argument hook must be a reference or NULL"; variable tmp; if ( assoc_key_exists(pkg_list, name) ) tmp = pkg_list[name]; else { tmp = @Pkg_Type; pkg_list[name] = tmp; } tmp.compl = name; tmp.options = opt; tmp.desc = desc; tmp.texdoc = texdoc; tmp.hook = hook; } private define pkg_hook_autoloaded_by_powerdot(name) { doc_options_class(); exch; pop; if ( () == "powerdot" ) return 1; return pkg_find(name); } private define pkg_hook_babel(name) { if ( pkg_find(name) ) return 1; variable mark = create_user_mark(); doc_find(); push_spot(); variable class; (,class) = cmd_parse_args(1,1); pop_spot(); if ( class[0] == "powerdot" ) % babel must be loaded before \documentclass, otherwise hyperref % (loaded by powerdot) didn't know it. () = left(14); else % suggest the point that pkg_find() suggested goto_user_mark(mark); return 0; } pkg_register("amsmath", "", "The main package for mathematical stuff", "amsldoc", NULL); pkg_register("amssymb", "", "Symbols from AMS-Math", "", NULL); pkg_register("avant", "", "Sets Avant Garde as default sans serif font", "psnfss2e", NULL); private variable _lang = getenv("LANG"), _babel_opt = ""; if (_lang != NULL and _lang != "C") { switch (_lang[[0:1]]) { case "de": _babel_opt = "ngerman"; } { case "it": _babel_opt = "italian"; } { case "en": _babel_opt = "english"; } } pkg_register("babel", _babel_opt, "Provides local hyphenation", "", &pkg_hook_babel()); __uninitialize(&_lang); __uninitialize(&_babel_opt); pkg_register("bookman", "", "Sets Bookman (roman), Avant Garde (sans serif) and Courier (typewriter) as default font", "psnfss2e", NULL); pkg_register("chancery", "", "Sets Zapf Chancery as default roman font", "psnfss2e", NULL); pkg_register("charter", "", "Sets Charter as default roman font", "psnfss2e", NULL); pkg_register("courier", "", "Sets Courier as default typewriter font", "psnfss2e", NULL); pkg_register("eulervm", "euler-digits", "Sets Euler fonts as default math font", "", NULL); pkg_register("fontenc", "T1", "", "", NULL); pkg_register("graphicx", "final", "Package for graphics", "graphics", NULL); pkg_register("helvet", "scaled=.92", "Sets Helvetica as default sans serif font", "psnfss2e", NULL); pkg_register("hyperref", "draft=false,colorlinks,urlcolor=blue,breaklinks", "", "hyperref/manual", &pkg_hook_autoloaded_by_powerdot()); #if (_slang_utf8_ok) pkg_register("inputenc", "utf8", "Provides direct input of non-ascii characters", "", NULL); #else pkg_register("inputenc", "latin1", "Provides direct input of non-ascii characters", "", NULL); #endif pkg_register("lmodern", "", "Sets Latin Modern as default font", "", NULL); pkg_register("mathpazo", "osf,slantedGreek", "Sets Adobe Palatino as default roman font", "psnfss2e", NULL); pkg_register("mathptmx", "", "Sets Times as default roman font", "psnfss2e", NULL); pkg_register("newcent", "", "Sets New Century Schoolbook (roman), Avant Garde (sans serif) and Courier (typewriter) as default font", "psnfss2e", NULL); pkg_register("pstricks", "", "Draws PS graphics with LaTeX commands", "pstricks-doc", &pkg_hook_autoloaded_by_powerdot()); pkg_register("suetterl", "", "Provides Suetterlin kind font (use \textsuetterlin and \suetterlin)", "", NULL); pkg_register("type1ec", "", "Sets Computer Modern super as default font", "", NULL); pkg_register("xcolor", "", "Colors for LaTeX", "", &pkg_hook_autoloaded_by_powerdot()); private define pkg_find(name) { eob(); variable after_last_pkg = create_user_mark(); bob(); while ( re_fsearch("\\[buR][es][geq][ipu]"R) ) % Fixme: PCRE \\(begin|(Require|use)package) { if ( is_commented() ) { eol(); continue; } if ( looking_at("\\begin{document}") ) { goto_user_mark(after_last_pkg); return 0; } variable is_usepackage = 0; if ( looking_at("\\usepackage") ) { is_usepackage = 1; () = right(11); } else if ( looking_at("\\RequirePackage") ) () = right(15); else { () = right(1); continue; } variable mark_before_args = create_user_mark(); variable p; (, p) = cmd_parse_args(1, 1); if ( is_list_element(str_delete_chars(p[0], "\\s"), name, ',') ) { goto_user_mark(mark_before_args); return 1; } if (is_usepackage) % If this wasn't the expected package, move the mark behind the % \usepackage command move_user_mark(after_last_pkg); } throw DataError, "no \\begin{document} found"; } private define pkg_insert() { variable opt; if (_NARGS >= 2) opt = (); variable name = (); if (name == "") return; variable old_buf = whatbuf(); latex_external->jump_to_master_buffer(); push_spot(); try { variable hook = NULL; if ( assoc_key_exists(pkg_list, name) ) hook = pkg_list[name].hook; if (hook != NULL) { if ( @hook(name) ) return; } else if ( pkg_find(name) ) return; if ( eobp() ) % pkg_find() or the hook didn't found any \usepackage { doc_find(); (,) = cmd_parse_args(1,1); !if ( down(1) ) newline(); } else { forever { push_spot(); skip_white(); looking_at_char('%'); pop_spot(); !if ( () ) break; () = down(1); } if ( bolp() ) % We are not in the line with the last \usepackage and % skipped a comment () = up(1); } push_spot(); bsearch("\\documentclass"); pop_spot(); if ( () ) % after \documentclass insert("\n\\usepackage"); else % before \documentclass insert("\n\\RequirePackage"); if ( __is_initialized(&opt) ) { if (opt != "") insert("[$opt]"$); } else if ( assoc_key_exists(pkg_list, name) ) { opt = pkg_list[name].options; if (opt != "") insert("[$opt]"$); } insert("{$name}"$); !if ( eolp() ) newline(); } finally { pop_spot(); setbuf(old_buf); } } private define insert_pkgs(str) { if (str == "") return; foreach ( strchop(str, ':', 0) ) { variable pkg = (), pos = is_substr(pkg, ","), opt; if (pos) pkg_insert(substr(pkg, 1, pos-1), substr(pkg, pos+1, strlen(pkg)) ); else pkg_insert(pkg); } } static define pkg_prompt() { try { variable pkg = read_with_description("Select a package:", "", "", make_sorted_desc_list(pkg_list)); if (pkg == "") return; variable options, new_pkg = not assoc_key_exists(pkg_list, pkg); if (new_pkg) options = ""; else options = pkg_list[pkg].options; options = read_mini("Options:", "", options); pkg_insert(pkg, options); if (andelse {new_pkg} {LaTeX_File_New != NULL} {strlen(LaTeX_File_New) > 0}) { variable desc = read_mini("A description for the new package:", "", ""); variable fp = fopen(LaTeX_File_New, "a"); () = fprintf(fp, "latex->pkg_register(\"%- 21s \"%s\"R, \"%s\"R, \"\", NULL);\n", pkg + "\",", options, desc); () = fclose(fp); } message("\\usepackage{$pkg} inserted."$); } catch UserBreakError; } static define pkg_loaded(pkg) { variable old_buf = whatbuf(); latex_external->jump_to_master_buffer(); push_spot(); try { variable hook = NULL; if ( assoc_key_exists(pkg_list, pkg) ) hook = pkg_list[pkg].hook; if (hook != NULL) return @hook(pkg); else return pkg_find(pkg); } finally { pop_spot(); setbuf(old_buf); } } private define pkg_options(pkg) { variable old_buf = whatbuf(); latex_external->jump_to_master_buffer(); push_spot(); try { variable hook = NULL; if ( assoc_key_exists(pkg_list, pkg) ) hook = pkg_list[pkg].hook; if (hook != NULL) { !if ( @hook(pkg) ) throw InternalError, "Package $pkg not found"$; } else !if ( pkg_find(pkg) ) throw InternalError, "Package $pkg not found"$; variable args; (args,) = cmd_parse_args(1, 0); if (length(args) == 0) return ""; else return args[0]; } finally { pop_spot(); setbuf(old_buf); } } static define pkg_help() { try { variable pkg; if (_NARGS) { pkg = (); if ( is_substr(pkg, ":") ) pkg = strchop(pkg, ':', 0)[0]; } else { pkg = read_with_description("Help for which package:", "", "", make_sorted_desc_list(pkg_list)); if (pkg == "") return; } variable help; if ( assoc_key_exists(pkg_list, pkg) ) { help = pkg_list[pkg].texdoc; if (strlen(help) == 0) help = pkg; } else help = pkg; texdoc(help); } catch UserBreakError; } %%%%%%%%%% % % All about indentation % %!%+ %\function{env_name_indent} %\synopsis{Gets the name and the indention of the current environment} %\usage{(String_Type name, Integer_type indent) env_name_indent()} %\description % This function returns the name of the environment the editing point is in % and the count of characters before \begin{...} in this line. If it isn't % within a environment, name is NULL and the value of indent is undefined. % %\seealso{boenv(), env_name()} %!%- %\usage{(String_Type name, Integer_type indent) env_name_indent([Integer_Type])} % If the optional parameter is unequal to zero to editing point is moved % there. private define env_name_indent() { push_spot(); try { variable name = env_name(1); return (name, what_column()-1); } finally pop_spot(); } private define bsearch_command_indent() { variable backslash_mark, start_mark = create_user_mark(); forever { !if ( bsearch_char('\\') ) error("Unknown case: opening brace, but no \\"); backslash_mark = create_user_mark(); % fix me! % \framebox[.8\textwidth]{ variable found = orelse {find_matching_delimiter('{') != 1} {create_user_mark() > start_mark}; goto_user_mark(backslash_mark); if (found) % start_mark is the opening brace for the command at % backslash_mark break; % else % the found backslash is inside of {} which are closed before % start_mark } return what_column()-1; } private define calc_indention(env_name, line) { if (line != NULL) { line = strtrim_beg(line); foreach ( [ {"\\item", LaTeX_Indent_Item}, {"\\intertext{", LaTeX_Indent_First}, {"\\bibitem{", LaTeX_Indent_Item}, {"\\end{", 0}] ) { variable tmp = (); if (strncmp(line, tmp[0], strlen(tmp[0])) == 0) return tmp[1]; } } switch ( chop_star(env_name) ) { case "document" or case "verbatim" or case "Verbatim": return 0; } { case "gather" or case "align" or case "tabular" or case "tabularx": () = up(1); variable indent = LaTeX_Indent_First; !if ( orelse {blooking_at("\\\\")} {blooking_at("\\hline")} {bfind("\\intertext{")} {bfind("\\begin{"+env_name+"}")} % first line after \begin ) indent += LaTeX_Indent_Continued; () = down(1); return indent; } { case NULL: return 0; } return LaTeX_Indent_First; } private define newline_indent_hook() { variable indent, start_mark = create_user_mark(), name, env_mark; () = bocomment(); name = env_name(1); if (name == NULL) { % we are outside of \begin{document} indent = 0; env_mark = NULL; } else { indent = what_column()-1; env_mark = create_user_mark(); goto_user_mark(start_mark); } if (andelse {find_matching_delimiter('}') == 1} {orelse {env_mark == NULL} {create_user_mark() > env_mark} }) { % we are inside of braces name = "{"; indent = what_column()-1; bskip_white(); !if (bolp()) indent = bsearch_command_indent(); } goto_user_mark(start_mark); trim(); newline(); indent += calc_indention(name, NULL); whitespace(indent); } private define indent_hook() { variable mark = create_user_mark(); bol(); trim(); if (eolp()) mark = NULL; % catch the case of a line with only whitespaces variable start_mark = create_user_mark(); variable indent; switch ( what_char() ) { case '}': if (find_matching_delimiter('}') != 1) error("No opening '{' found"); indent = what_column()-1; bskip_white(); !if (bolp()) % if opening brace is behind a command \...{ indent = bsearch_command_indent(); } { case '{' and up(1) and left(1) and looking_at_char('%'): indent = bsearch_command_indent() + LaTeX_Indent_First; ()=right(1); skip_word_chars(); skip_chars("%"); !if (eolp()) % indent to the level of the command end indent = what_column()-1; } % This looks somewhat tricky, but we only handle cases where the % previous line is a comment. But we must move the editing point for % this so we must reset it. { case '%' and up(1) and is_commented() or (goto_user_mark(start_mark),0): ()=up(1); () = bfind_char('%'); indent = what_column()-1; } { variable line = line_as_string(); bol(); variable env_mark, e_name, e_indent; e_name = env_name(1); if (e_name == NULL) { % we are outside of \begin{document} e_indent = 0; env_mark = NULL; } else { e_indent = what_column()-1; env_mark = create_user_mark(); goto_user_mark(start_mark); } variable name; if (andelse {find_matching_delimiter('}') == 1} {orelse {env_mark == NULL} {create_user_mark() > env_mark} }) { % we are inside of braces name = "{"; %! Fix me! indent = what_column()-1; bskip_white(); !if (bolp()) { % { is not the begin of a line indent = bsearch_command_indent(); bskip_white(); !if (bolp()) { % the command isn't the start of the line indent = e_indent; name = e_name; } } } else { indent = e_indent; name = e_name; } goto_user_mark(start_mark); indent += calc_indention(name, line); } goto_user_mark(start_mark); whitespace(indent); if (mark != NULL) goto_user_mark(mark); } private define wrap_hook() { variable mark = create_user_mark(); ()=up(1); !if ( is_commented() ) { goto_user_mark(mark); indent_hook(); return; } % The wrap happened in a comment, so continue the comment () = bfind_char('%'); variable indent = what_column()-1; () = right(1); skip_white(); variable inner_indent = what_column() - indent - 2; () = down(1); whitespace(indent); insert_char('%'); whitespace(inner_indent); goto_user_mark(mark); } private define wrapok_hook() { push_spot(); variable e_n; try { () = bocomment(); e_n = env_name(); } finally pop_spot(); if ( andelse {e_n != NULL} {is_list_element("verbatim,Verbatim", e_n, ',')} ) return 0; push_spot(); try { bskip_chars("^ \t"); bskip_chars(" \t%"); return not bolp(); } finally pop_spot(); } static define indent_region() { variable start_mark = create_user_mark(); check_region(0); variable end_mark = create_user_mark(); pop_mark(1); variable beg_mark = create_user_mark(); variable env_stack = {}; variable level; do { level = struct { name, indent }; try level.name = env_name(1); catch AnyError: break; if (level.name == NULL) level.indent = 0; else level.indent = what_column()-1; list_insert(env_stack, level, 0); } while (level.name != NULL); goto_user_mark(beg_mark); level = list_pop(env_stack, -1); () = up(1); while (down(1) and create_user_mark() < end_mark) { bol(); trim(); if ( eolp() ) continue; variable line = line_as_string(); bol(); variable this_line_indention = level.indent + calc_indention(level.name, line); whitespace(this_line_indention); while ( andelse {ffind_char('\\')} {not is_commented()} ) { () = right(1); if ( looking_at("begin{") ) { () = right(6); list_append(env_stack, level, -1); level = struct { name, indent }; push_mark(); () = ffind_char('}'); level.name = bufsubstr(); level.indent = this_line_indention; } else { if ( looking_at("end{") ) { () = right(4); if ( looking_at(level.name+"}") ) level = list_pop(env_stack, -1); else throw ApplicationError, "Expected \\end{"+level.name+"}"; } } } } goto_user_mark(start_mark); } %%%%%%%%%% % % Completion in environments % typedef struct { pre_nl, post_nl } nl_completion_type; private variable nl_completion = Assoc_Type[nl_completion_type]; static define set_nl_completion(env, pre, post) { if ( typeof(env) != String_Type ) throw InvalidParmError, "env must be a string"; if ( pre != NULL and typeof(pre) != String_Type ) throw InvalidParmError, "pre must be a string or NULL"; if ( post != NULL and typeof(post) != String_Type ) throw InvalidParmError, "post must be a string or NULL"; if ( assoc_key_exists(nl_completion, env) ) { if (pre == NULL and post == NULL) assoc_delete_key(nl_completion, env); else { if (pre != NULL) nl_completion[env].pre_nl = pre; if (post != NULL) nl_completion[env].post_nl = post; } } else { if (pre == NULL) pre = ""; if (post == NULL) post = ""; nl_completion[env] = @nl_completion_type; nl_completion[env].pre_nl = pre; nl_completion[env].post_nl = post; } } set_nl_completion("align", "\\\\", ""); set_nl_completion("array", "\\\\", ""); set_nl_completion("cases", "\\\\", ""); set_nl_completion("compactdesc", "", "\\item[]"); set_nl_completion("compactenum", "", "\\item "); set_nl_completion("compactitem", "", "\\item "); set_nl_completion("description", "", "\\item[]"); set_nl_completion("enumerate", "", "\\item "); set_nl_completion("flalign", "\\\\", ""); set_nl_completion("gather", "\\\\", ""); set_nl_completion("itemize", "", "\\item "); set_nl_completion("pmatrix", "\\\\", ""); set_nl_completion("tabular", "\\\\", ""); set_nl_completion("tabularx", "\\\\", ""); set_nl_completion("thebibliography", "", "\\bibitem{}"); static define newline_with_completion() { if ( is_commented() ) { variable mark = create_user_mark(); bol(); skip_chars(" \t%"); % new line become a comment, too bol(); ()=ffind_char('%'); variable indent = what_column()-1; () = right(1); skip_white(); variable inner_indent = 0; !if (eolp()) inner_indent = what_column() - indent - 2; goto_user_mark(mark); newline(); trim(); whitespace(indent); insert_char('%'); whitespace(inner_indent); return; } variable name; (name, indent) = env_name_indent(); name = chop_star(name); variable compl; if ( assoc_key_exists(nl_completion, name) ) compl = nl_completion[name]; else { compl = @nl_completion_type; compl.pre_nl = ""; compl.post_nl = ""; } switch (name) { andelse {case "tabular" or case "tabularx"} {blooking_at("---")}: () = left(3); () = replace_chars(3, "\\hline"); } { push_spot(); variable stop_str = strtrim(compl.post_nl); if (stop_str == "") stop_str = strtrim(compl.pre_nl); variable skip_chars = "^$(){}[]" + substr(stop_str, 1, 1); variable close_stack = list_new(), open_stack = list_new(); forever { bskip_chars(skip_chars); () = left(1); if ( looking_at(stop_str) ) break; variable ch = what_char(), counterpart, alt_counterpart = ""; switch (ch) { case ')' or case ']' or case '}': if ( andelse {ch == '}'} {is_escaped()} ) ch = "\\}"; else ch = char(ch); list_append(close_stack, ch, -1); continue; } { case '\\': if ( looking_at("\\end") ) boenv(); else if ( looking_at("\\begin") ) break; continue; } { case '$': if ( is_escaped() ) { bskip_chars("\\"); continue; } else { if (length(close_stack) == 0) { list_append(close_stack, "$", -1); } else if (close_stack[-1] == "$") list_delete(close_stack, -1); continue; } } { case '(': counterpart = ")"; alt_counterpart = "]"; } { case '[': counterpart = "]"; alt_counterpart = ")"; } { case '{': if ( is_escaped() ) counterpart = "\\}"; else counterpart = "}"; } if (andelse {length(close_stack) != 0} {close_stack[-1] == "$"}) { list_append(open_stack, "$", -1); list_delete(close_stack, -1); } if (length(close_stack) == 0) list_append(open_stack, counterpart, -1); else { if (close_stack[-1] == counterpart or close_stack[-1] == alt_counterpart) list_delete(close_stack, -1); else list_append(open_stack, counterpart, -1); } } pop_spot(); if (andelse {length(close_stack) != 0} {close_stack[-1] == "$"}) list_append(open_stack, "$", -1); while (length(open_stack) > 0) { variable looking_for = list_pop(open_stack, 0); if ( looking_at(looking_for) ) () = right( strlen(looking_for) ); else insert(looking_for); } insert( compl.pre_nl ); } trim(); newline(); whitespace( indent + calc_indention(name, compl.post_nl) ); insert( compl.post_nl ); if ( andelse {strlen(compl.post_nl) > 0} {is_substr("]}", char(compl.post_nl[-1]))} ) () = left(1); } %%%%%%%%%% % % Environemts -- all between \begin{} and \end{} % typedef struct { args, desc, deps, hook, compl } Env_Type; private variable env_list = Assoc_Type[Env_Type]; static define env_register(name, args, desc, deps, hook) { try { % This is a tricky way to check if all variables are strings () = _typeof([name, desc, ""]); } catch TypeMismatchError: { throw InvalidParmError, "One of the given arguments has invalid type"; } if (strlen(name) == 0) throw InvalidParmError, "name can not be empty"; if (typeof(args) != Integer_Type) throw InvalidParmError, "The argument args must be an integer"; if (typeof(deps) != String_Type and typeof(deps) != Ref_Type) throw InvalidParmError, "The argument deps must be a string or a reference"; if (hook != NULL and typeof(hook) != Ref_Type) throw InvalidParmError, "The argument hook must be a reference or NULL"; variable tmp; if ( assoc_key_exists(env_list, name) ) tmp = env_list[name]; else { tmp = @Env_Type; env_list[name] = tmp; } tmp.compl = name; tmp.args = args; tmp.deps = deps; tmp.desc = desc; tmp.hook = hook; } private define env_hook_Verbatim(name, mark_after_begin) { variable indent = what_column() - 1; if (indent > 0) { push_spot(); goto_user_mark(mark_after_begin); insert("[gobble=$indent]"$); pop_spot(); } } private define env_hook_star_label(name, mark_after_begin) { if (name[-1] != '*') cmd_insert("label"); } private define env_hook_array_format(name, mark_after_begin) { eoenv(); () = left(1); array_edit_column_format(); } private define env_hook_gmatrix(name, mark_after_begin) { variable type = char(get_mini_response("Which type do you want? (p) {b} [B] |v| ||V|| ")); if ( is_substr("pbBvV", type) ) { push_spot(); goto_user_mark(mark_after_begin); insert("[$type]"$); pop_spot(); } } env_register("abstract", 0, "", "", NULL); env_register("align", 0, "Math environment with alignment", "amsmath", &env_hook_star_label()); env_register("array", 1, "", "", &env_hook_array_format()); env_register("bmatrix", 0, "", "amsmath", NULL); env_register("Bmatrix", 0, "", "amsmath", NULL); env_register("cases", 0, "", "amsmath", NULL); env_register("center", 0, "", "", NULL); env_register("compactdesc", 0, "", "paralist", NULL); env_register("compactenum", 0, "", "paralist", NULL); env_register("compactitem", 0, "", "paralist", NULL); env_register("description", 0, "", "paralist", NULL); % fixme: deps as hook % env_register("displaymath", 0, "", "", NULL); env_register("enumerate", 0, "", "paralist", NULL); % fixme: deps as hook env_register("figure", 0, "", "", NULL); env_register("flushleft", 0, "", "", NULL); env_register("flushright", 0, "", "", NULL); env_register("gather", 0, "", "amsmath", &env_hook_star_label()); env_register("gmatrix", 0, "", "gauss", &env_hook_gmatrix()); env_register("itemize", 0, "", "paralist", NULL); % fixme: deps as hook env_register("list", 0, "", "", NULL); env_register("longtable", 1, "", "longtable", &env_hook_array_format()); env_register("matrix", 0, "", "amsmath", NULL); env_register("minipage", 1, "", "", NULL); env_register("picture", 0, "", "", NULL); env_register("pmatrix", 0, "", "amsmath", NULL); env_register("proof", 0, "", "", NULL); env_register("pspicture", 0, "A PSTricks picture", "pstricks", NULL); env_register("quotation", 0, "", "", NULL); env_register("quote", 0, "", "", NULL); env_register("smallmatrix", 0, "", "amsmath", NULL); env_register("tabbing", 0, "", "", NULL); env_register("table", 0, "", "", NULL); env_register("tabular", 1, "", "", &env_hook_array_format()); env_register("tabularx", 2, "", "tabularx", NULL); % Fixme: hook = array_edit_column_format() env_register("thebibliography", 1, "", "", NULL); env_register("theorem", 0, "", "", NULL); env_register("titlepage", 0, "", "", NULL); env_register("verbatim", 0, "", "", NULL); env_register("Verbatim", 0, "", "fancyvrb", &env_hook_Verbatim()); env_register("verse", 0, "", "", NULL); env_register("vmatrix", 0, "", "amsmath", NULL); env_register("Vmatrix", 0, "", "amsmath", NULL); private define env_lookup() { variable default; if (_NARGS >= 2) default = (); variable name = (); if (strlen(name) > 0) { if ( assoc_key_exists(env_list, name) ) return env_list[name]; if (name[-1] == '*') name = chop_star(name); else name = name + "*"; if ( assoc_key_exists(env_list, name) ) return env_list[name]; } if (_NARGS >= 2) return default; else throw InternalError, "Environment $name not found and no default given"$; } %!%+ %\function{boenv} %\synopsis{Go to the beginning of the environment} %\usage{Integer_Type boenv()} %\description % This function searches for the beginning of the environment the editing % point is in. If it finds a "\begin{...}" it moves the editing point to the % begin of "\begin{...}" and returns 1. If no environment beginning is % found (maybe the editing point is before \begin{document}) the editing % point isn't moved and 0 is returned. %!%- static define boenv() { if ( is_commented() ) throw UsageError, "Starting inside of a comment is not possible"; variable start_mark = create_user_mark(), open_ends = list_new(); while ( re_bsearch("\\[be][en][gd][i{]"R) ) %! Fixme: PCRE: \\(begin|end)\{ { if ( bocomment() ) continue; if ( looking_at("\\begin{" ) ) { if (length(open_ends) == 0) return; list_delete(open_ends, -1); } else if ( looking_at("\\end{") ) list_append(open_ends, [what_line, what_column()], -1); } goto_user_mark(start_mark); if (length(open_ends) > 0) throw DataError, "No matching \\begin found for \\end in line " + string(open_ends[-1][0]) + " column " + string(open_ends[-1][1]); else throw DataError, "No matching \\begin found"; } %!%+ %\function{eoenv} %\synopsis{Go to the end of the environment} %\usage{Integer_Type eoenv()} %\description % This function searches for the end of the environment the editing % point is in. If it finds a "\end{...}" it moves the editing point to the % begin of "\end{...}" and returns 1. If no environment end is % found (maybe the editing point is before \begin{document}) the editing % point isn't moved and 0 is returned. %!%- static define eoenv() { if ( is_commented() ) throw UsageError, "Starting inside of a comment is not possible"; variable start_mark = create_user_mark(), open_begins = list_new(); if ( looking_at("\\begin{") ) () = right(1); while ( re_fsearch("\\[be][en][gd][i{]"R) ) %! Fixme: PCRE: \\(begin|end)\{ { if ( is_commented() ) { eol(); continue; } if ( looking_at("\\end{" ) ) { if (length(open_begins) == 0) return; list_delete(open_begins, -1); } else if ( looking_at("\\begin{") ) list_append(open_begins, [what_line, what_column], -1); () = right(1); } goto_user_mark(start_mark); if (length(open_begins) > 0) throw DataError, "No matching \\end found for \\begin in line " + string(open_begins[-1][0]) + " column " + string(open_begins[-1][1]); else throw DataError, "No matching \\end found"; } %!%+ %\function{env_name} %\synopsis{Gets the name of the current environment} %\usage{String_Type env_name([Integer_Type])} %\description % This function returns the name of the environment the editing point is in. % If it isn't within an environment, NULL is returned. % % If the optional parameter is unequal to zero the editing point is placed % at the beginning. % %\seealso{boenv()} %!%- static define env_name() { variable stay_there = 0, spot = create_user_mark(); if (_NARGS) stay_there = (); try boenv(); catch DataError: % No \begin found return NULL; () = right(7); % skip \begin{ push_mark(); if ( ffind_char('}') ) { variable name = bufsubstr(); () = left(strlen(name) + 7); % \begin{$name} !if (stay_there) goto_user_mark(spot); return name; } else { pop_mark(1); goto_user_mark(spot); throw DataError, "malformed \\begin{}"; } } static define env_close () { variable mark = create_user_mark(); bskip_white(); variable e_name; if ( bolp() ) { trim(); variable e_indent; (e_name, e_indent) = env_name_indent(); whitespace(e_indent); } else { goto_user_mark(mark); e_name = env_name(); } if (e_name == NULL) throw UsageError, "Not within an environment"; insert("\\end{$e_name}"$); } static define env_insert() { variable def_args; if (_NARGS >= 2) def_args = (); else def_args = String_Type[0]; variable name = (); variable env_data = env_lookup(name, NULL); if (env_data == NULL) { env_data = @Env_Type; env_data.args = 0; env_data.deps = ""; env_data.hook = NULL; } if (typeof(env_data.deps) == String_Type) insert_pkgs(env_data.deps); else (@env_data.deps)(name); variable body; if ( dupmark() ) { body = bufsubstr(); del_region(); } variable mark = create_user_mark(); bskip_white(); variable in_one_line = not bolp(); if (in_one_line) goto_user_mark(mark); else { indent_line(); skip_white(); } insert("\\begin{$name}"$); variable point_after_begin = create_user_mark(); if (length(def_args) > 0) insert("{" + strjoin(def_args, "}{") + "}"); variable point_after_insertion; if (env_data.args - length(def_args) > 0) { insert_char('{'); point_after_insertion = create_user_mark(); loop (env_data.args - length(def_args) - 1) insert("}{"); insert_char('}'); } if (in_one_line) { if ( __is_initialized(&body) ) insert(body); !if ( __is_initialized(&point_after_insertion) ) point_after_insertion = create_user_mark(); } else { newline(); if ( __is_initialized(&body) ) { push_mark(); insert(body); !if ( __is_initialized(&point_after_insertion) ) point_after_insertion = create_user_mark(); !if ( bolp() ) newline(); indent_region(); } else { variable compl; if ( assoc_key_exists(nl_completion, chop_star(name)) ) { compl = nl_completion[chop_star(name)].post_nl; insert(compl); } indent_line(); !if ( __is_initialized(&point_after_insertion) ) { if (andelse {__is_initialized(&compl)} {strlen(compl) != 0}) { is_substr("]}", substr(compl, strlen(compl), 1)); dup(); if ( () ) () = left(1); point_after_insertion = create_user_mark(); if ( () ) () = right(1); } else point_after_insertion = create_user_mark(); } newline(); } } env_close(); !if (in_one_line or eolp()) newline(); goto_user_mark(point_after_insertion); if (env_data.hook != NULL) (@env_data.hook)(name, point_after_begin); } private variable env_last_env = ""; static define env_prompt() { try { env_last_env = read_with_description("Select an environment:", env_last_env, "", make_sorted_desc_list(env_list)); if (env_last_env == "") return; variable env_data = env_lookup(env_last_env, NULL), desc; if (env_data != NULL) desc = env_data.desc; else if (LaTeX_Register_New) { variable args, deps; args = integer( read_mini("How much arguments this environment " + "have?", "0", "") ); desc = read_mini("A description for the new environment:", "", ""); deps = read_mini("Colon separated list of packages needed for " + "this environment:", "", ""); env_register(env_last_env, args, desc, deps, NULL); if (andelse {LaTeX_File_New != NULL} {strlen(LaTeX_File_New) > 0}) { variable fp = fopen(LaTeX_File_New, "a"); () = fprintf(fp, "latex->env_register(\"%- 21s %u, \"%s\"R, \"%s\", NULL);\n", env_last_env + "\",", args, desc, deps); () = fclose(fp); } } env_insert(env_last_env); message(desc); } catch UserBreakError; } static define env_rename() { variable spot = create_user_mark(); try { variable old_name = env_name(1); if (old_name == NULL) throw UsageError, "You aren't within an environment"; variable new_name = read_with_description("Rename environment:", old_name, "", make_sorted_desc_list(env_list)); if (new_name == old_name) return; variable env_data = env_lookup(new_name, NULL); if (env_data == NULL and LaTeX_Register_New) { variable args, desc, deps; args = integer( read_mini("How much arguments this environment " + "have?", "0", "") ); desc = read_mini("A description for the new environment:", "", ""); deps = read_mini("Colon separated list of packages needed for " + "this environment:", "", ""); env_register(new_name, args, desc, deps, NULL); if (andelse {LaTeX_File_New != NULL} {strlen(LaTeX_File_New) > 0}) { variable fp = fopen(LaTeX_File_New, "a"); () = fprintf(fp, "latex->env_register(\"%- 21s %u, \"%s\"R, \"%s\", NULL);\n", new_name + "\",", args, desc, deps); () = fclose(fp); } env_data = env_lookup(new_name); } if (env_data != NULL) { if (typeof(env_data.deps) == String_Type) insert_pkgs(env_data.deps); else (@env_data.deps)(new_name); } () = right(7); () = replace_chars(strlen(old_name), new_name); goto_user_mark(spot); eoenv(); () = right(5); () = replace_chars(strlen(old_name), new_name); } catch UserBreakError; finally goto_user_mark(spot); } static define env_help() { try { variable env; if (_NARGS) env = (); else { env = env_name(); if (env == NULL) env = ""; env = read_with_description("Help for which environment:", env, "", make_sorted_desc_list(env_list)); if (env == "") return; } variable env_data = env_lookup(env, NULL), help; if (env_data != NULL) { help = env_data.deps; if (typeof(help) != String_Type) __uninitialize(&help); } if (andelse {__is_initialized(&help)} {strlen(help) != 0}) pkg_help(help); else throw UsageError, "No information found about how to get help"; } catch UserBreakError; } %%%%%%%%%% % % Command stuff, e.g. \foo[]{} % typedef struct { args, desc, deps, hook, math, compl } Cmd_Type; private variable cmd_list = Assoc_Type[Cmd_Type]; % compl: the name of the command, e.g. the string after the backslash; the % name compl makes it easier to pass the struct to read_with_description() % args: how many arguments the command has? % need_math: is it a command for a mathematical environment? % desc: a description of the command % deps: which packages the command depend on (colon separated list) % hook: NULL or a reference to a function that gets called after inserting the % command from inside the first brace or after the command if the % command has no arguments % Call the function with the name of the command and a mark of the % point after the command. static define cmd_register(name, args, need_math, desc, deps, hook) { try { % This is a tricky way to check if all variables are strings () = _typeof([name, desc, deps, ""]); } catch TypeMismatchError: { throw InvalidParmError, "One of the given arguments has invalid type"; } if (strlen(name) == 0) throw InvalidParmError, "name can not be empty"; if (typeof(args) != Integer_Type or typeof(need_math) != Integer_Type) throw InvalidParmError, "The arguments args and need_math must be integers"; if (hook != NULL and typeof(hook) != Ref_Type) throw InvalidParmError, "The argument hook must be a reference or NULL"; variable tmp; if ( assoc_key_exists(cmd_list, name) ) tmp = cmd_list[name]; else { tmp = @Cmd_Type; cmd_list[name] = tmp; } tmp.compl = name; tmp.args = args; tmp.math = need_math; tmp.deps = deps; tmp.desc = desc; tmp.hook = hook; } () = evalfile("latex_cmds", current_namespace()); private define cmd_lookup() { variable default; if (_NARGS >= 2) default = (); variable name = (); if (strlen(name) > 0) { if ( assoc_key_exists(cmd_list, name) ) return cmd_list[name]; if (name[-1] == '*') name = chop_star(name); else name = name + "*"; if ( assoc_key_exists(cmd_list, name) ) return cmd_list[name]; } if (_NARGS >= 2) return default; else throw InternalError, "Command \\$name not found and no default given"$; } private define insert_space_after_cmd_hook(fun); private define insert_space_after_cmd_hook(fun) { if (andelse {typeof(fun) == String_Type} {fun == "self_insert_cmd"} { ('A' <= LAST_CHAR and LAST_CHAR <= 'Z') or ('a' <= LAST_CHAR and LAST_CHAR <= 'z') }) insert_char(' '); remove_from_hook("_jed_before_key_hooks", &insert_space_after_cmd_hook()); } static define cmd_insert() { variable prefix = prefix_argument(0); variable def_args, ins_pkg; if (_NARGS >= 3) def_args = (); else def_args = String_Type[0]; if (_NARGS >= 2) ins_pkg = (); else ins_pkg = 1; variable name = (); variable cmd_data = cmd_lookup(name, NULL); if (cmd_data == NULL) { insert_char('\\'); insert(name); loop (prefix) insert("[]"); if (prefix != 0) () = left(2 * prefix - 1); return; } if (ins_pkg) insert_pkgs(cmd_data.deps); else !if ( orelse {cmd_data.deps == ""} {pkg_loaded(cmd_data.deps)} ) throw ApplicationError, "The depencies \"" + cmd_data.deps + "\" for the command \"$name\" aren't satisfied"$; if ( andelse {cmd_data.args != 0} {dupmark()} ) { def_args = [def_args, bufsubstr()]; del_region(); } variable behind_insertion; if (andelse {cmd_data.math} {not is_math()} ) { !if ( blooking_at("$") ) insert("$$"); behind_insertion = create_user_mark(); () = left(1); } insert_char('\\'); insert(name); push_spot(); variable next_point; if (prefix) { insert_char('['); next_point = create_user_mark(); loop (prefix - 1) insert("]["); insert_char(']'); } if (length(def_args) > 0) insert("{" + strjoin(def_args, "}{") + "}"); loop (cmd_data.args - length(def_args)) insert("{}"); !if ( __is_initialized(&behind_insertion) ) behind_insertion = create_user_mark(); !if ( __is_initialized(&next_point) ) { if (cmd_data.args - length(def_args) > 0) { () = left(2 * (cmd_data.args - length(def_args)) - 1); next_point = create_user_mark(); } else next_point = behind_insertion; } pop_spot(); if (cmd_data.hook == NULL) goto_user_mark(next_point); else (@cmd_data.hook)(name, behind_insertion); if (LaTeX_Auto_Space_After_Commands) { () = left(1); variable ch = what_char(); () = right(1); if ( ('A' <= ch and ch <= 'Z') or ('a' <= ch and ch <= 'z') ) add_to_hook("_jed_before_key_hooks", &insert_space_after_cmd_hook()); } } private variable cmd_last_cmd = ""; static define cmd_prompt() { try { cmd_last_cmd = read_with_description("Select a command:", cmd_last_cmd, "", make_sorted_desc_list(cmd_list)); if (cmd_last_cmd == "") return; variable cmd_data = cmd_lookup(cmd_last_cmd, NULL), desc; if (cmd_data != NULL) desc = cmd_data.desc; else if (LaTeX_Register_New) { variable args, math, deps; args = integer( read_mini("How much arguments this command " + "have?", "0", "") ); variable dflt; math = int(is_math()); if (math) dflt = "Y/n"; else dflt = "y/N"; switch ( get_mini_response("Is this a mathematic command? (" + dflt + ") ") ) { case 7: throw UserBreakError; } { case 'Y' or case 'y': math = 1; } { case 'N' or case 'n': math = 0; } % Fixme: This should be read_with_description() with the % SYNOPSIS as description variable hook_as_string = read_string_with_completion("Name of a hook (leave if empty for none)", "", strjoin("latex->" + _apropos("latex", "cmd_hook", 3), ",")); variable hook = __get_reference(hook_as_string); if ( __is_callable(hook) ) hook_as_string = "&" + hook_as_string + "()"; else { hook = NULL; hook_as_string = "NULL"; } desc = read_mini("A description for the new command:", "", ""); deps = read_mini("Colon separated list of packages needed for " + "this command:", "", ""); cmd_register(cmd_last_cmd, args, math, desc, deps, hook); if (andelse {LaTeX_File_New != NULL} {strlen(LaTeX_File_New) > 0}) { variable fp = fopen(LaTeX_File_New, "a"); () = fprintf(fp, "latex->cmd_register(\"%- 21s %u, %u, \"%s\"R, \"%s\", %s);\n", cmd_last_cmd + "\",", args, math, desc, deps, hook_as_string); () = fclose(fp); } } cmd_insert(cmd_last_cmd); message(desc); } catch UserBreakError; } static define cmd_parse_args(opt_args, req_args) { skip_chars(" \n\t"); variable o_args = list_new(); while ( andelse {opt_args > 0} {looking_at_char('[')} ) { push_mark(); try { forever { () = right(1); skip_chars("^{]"); !if ( looking_at_char('{') or looking_at_char(']') ) throw DataError, "No matching ] found"; if ( is_escaped() ) continue; if ( looking_at_char(']') ) { list_append(o_args, str_compress_tex( substr(bufsubstr(), 2, -1) ), -1); push_mark(); break; } else fsearch_matching_brace(); } } finally { pop_mark(0); } () = right(1); skip_chars(" \n\t"); --opt_args; } variable r_args = list_new(); while (req_args > 0) { switch ( what_char() ) { case '{': () = right(1); push_mark(); try { fsearch_matching_brace(); list_append(r_args, str_compress_tex(bufsubstr()), -1); --req_args; push_mark(); } finally pop_mark(0); () = right(1); } { case '\\': push_mark(); () = right(1); skip_chars(TeX_Command_Chars); list_append(r_args, bufsubstr(), -1); --req_args; } { case '%': () = down(1); skip_white(); } { case ' ' or case '\n' or case '\t': skip_chars(" \n\t"); } { list_append(r_args, char( what_char() ), -1); --req_args; () = right(1); } } return (o_args, r_args); } static define cmd_help() { try { variable cmd; if (_NARGS) cmd = (); else { push_spot(); bskip_chars(TeX_Command_Chars); push_mark(); skip_chars(TeX_Command_Chars); cmd = bufsubstr(); pop_spot(); cmd = read_with_description("Help for which command:", cmd, "", make_sorted_desc_list(cmd_list)); if (cmd == "") return; } variable cmd_data = cmd_lookup(cmd, NULL), help; if (cmd_data != NULL) { help = cmd_data.deps; if (typeof(help) != String_Type) __uninitialize(&help); } if (andelse {__is_initialized(&help)} {strlen(help) != 0}) pkg_help(help); else throw UsageError, "No information found about how to get help"; } catch UserBreakError; } %!%+ % Check if the editing point stays on a command. In this case return the % command, otherwise NULL %!%- static define is_command() { !if ( re_looking_at("\\[$TeX_Command_Chars]"R$) ) { !if ( re_looking_at("[$TeX_Command_Chars]"$) ) return NULL; variable mark = create_user_mark(); bskip_chars(TeX_Command_Chars); !if ( andelse {left(1)} {looking_at_char('\\')} ) { goto_user_mark(mark); return NULL; } } push_spot(); push_mark(); () = right(1); skip_chars(TeX_Command_Chars); bufsubstr(); pop_spot(); return (); } %%%%%%%%%% % % All about fonts % static define font_resize(decrease) { variable sizes="tiny,scriptsize,footnotesize,small,normalsize,large,Large,LARGE,huge,Huge"; variable start_mark = create_user_mark(), is_region = markp(); if (is_region) { check_region(0); exchange_point_and_mark(); } else if (orelse {looking_at_char('\\')} {bfind_char('\\')} ) ()=right(1); variable mark = create_user_mark(); push_mark(); skip_word_chars(); variable pos = is_list_element(sizes, bufsubstr(), ','); if ( pos ) { if (decrease) pos -= 2; if (pos == -1 or pos == 10) { goto_user_mark(start_mark); error("Font resizing not possible"); } push_mark(); goto_user_mark(mark); del_region(); } else { if (is_region) insert_char('{'); else % Maybe bfind_char doesn't find the correct \ - don't write there, it % might be wrong goto_user_mark(start_mark); insert_char('\\'); if (decrease) pos = 3; % small else pos = 5; % large } insert( string(extract_element(sizes, pos, ',')) ); mark = create_user_mark(); skip_non_word_chars(); if ( mark == create_user_mark() and not eolp() ) insert_char(' '); goto_user_mark(start_mark); if (is_region) insert_char('}'); } static define font_cmd() { try #ifexists jmini_prompt_string cmd_insert( jmini_prompt_string("Select a font command:", "", "", ["bfseries", "emph", "itshape", "mathbf", "mathcal", "mathit", "mathnormal", "mathrm", "mathsf", "mathtt", "mdseries", "normalfont", "rmfamily", "scshape", "sffamily", "slshape", "textbf", "textit", "textmd", "textnormal", "textrm", "textsc", "textsf", "textsl", "texttt", "textup", "ttfamily", "upshape"]) ); #else cmd_insert( read_with_completion("textrm,rmfamily,textit,"+ "itshape,emph,textmd,mdseries,textbf,bfseries,textup,"+ "upshape,textsl,slshape,textsf,sffamily,textsc,"+ "scshape,texttt,ttfamily,textnormal,normalfont,mathrm"+ "mathbf,mathsf,mathtt,mathit,mathnormal,mathcal", "Select a font command:", "", "", 's') ); #endif catch UserBreakError: {} } static define templ_insert(file) { push_mark(); narrow_to_region(); try { !if ( insert_file(file) ) return; bob(); if ( fsearch("%:default:classopt:") ) { push_mark(); () = right(19); if ( looking_at(",%") ) { () = right(2); del_region(); if ( strlen(LaTeX_Default_Class_Options) ) insert("," + LaTeX_Default_Class_Options); } else { if ( looking_at("[%") ) { () = right(2); del_region(); if ( strlen(LaTeX_Default_Class_Options) ) insert("[" + LaTeX_Default_Class_Options + "]"); } else pop_mark(1); } } if ( bol_fsearch("%:default:pkgs:%\n") ) { % set a marker for insert_pkgs where it should place the packages % if no other packages are present () = replace_chars(16, "\\usepackage{JLM marker}"); bol(); insert_pkgs(LaTeX_Default_Packages); deln(24); % delete the marker line (with \n) } bob(); if ( fsearch("%:start:%") ) deln(9); } finally widen_region(); } %%%%%%%%%% % % All about arrays like tabular or matrix % private define array_what_column() { variable start = create_user_mark(), num = 1; forever { bskip_chars("^&}\\"); !if ( left(1) ) % == bobp() break; if ( looking_at_char('&') and not is_escaped() ) { ++num; continue; } if ( looking_at_char('}') and not is_escaped() ) { bsearch_matching_brace(); continue; } if ( looking_at("\\end") ) { boenv(); continue; } if ( looking_at("\\multicolumn") ) { push_spot(); () = right(13); push_mark(); skip_chars("0-9"); num += integer( bufsubstr() ); pop_spot(); continue; } if ( orelse {looking_at("\\\\")} {looking_at("\\begin")} ) % This must be the begin of the array environment break; } goto_user_mark(start); return num; } private variable array_columns = Assoc_Type[Integer_Type, 0]; array_columns["align"] = 20; array_columns["array"] = -1; array_columns["bmatrix"] = 10; % [ matrix ] array_columns["Bmatrix"] = 10; % \{ matrix \} array_columns["cases"] = 2; array_columns["longtable"] = -1; array_columns["matrix"] = 10; array_columns["pmatrix"] = 10; % ( matrix ) array_columns["smallmatrix"] = 10; % \footnotesize matrix array_columns["tabular"] = -1; array_columns["tabular*"] = -2; array_columns["tabularx"] = -2; array_columns["vmatrix"] = 10; % | matrix | array_columns["Vmatrix"] = 10; % || matrix || static define array_new_cell() { variable start = create_user_mark(); variable e_name = env_name(1); variable num_cols; if ( assoc_key_exists(array_columns, e_name) ) num_cols = array_columns[e_name]; else num_cols = array_columns[ chop_star(e_name) ]; if (num_cols < 0) { () = right(strlen(e_name) + 8); % \begin{$e_name} (,) = cmd_parse_args(1, -num_cols - 1); !if ( looking_at_char('{') ) { goto_user_mark(start); throw InternalError; } () = right(1); num_cols = 0; variable factor = 1, factors = {}; forever { variable point = _get_point(); skip_chars("a-zA-Z"); num_cols += factor * (_get_point() - point); switch ( what_char() ) { case '}': if (length(factors) == 0) break; factor = list_pop(factors); } { case '*': list_append(factors, factor, -1); () = right(2); push_mark(); skip_chars("0-9"); factor *= integer( bufsubstr() ); () = right(1); } () = right(1); if ( looking_at_char('{') ) { fsearch_matching_brace(); () = right(1); } } } goto_user_mark(start); if (array_what_column() < num_cols) insert("& "); else { insert("\\\\\n"); indent_line(); } } static define array_next_cell() { forever { skip_chars("^&{\\"); if ( eobp() ) % This is very curious, better we do nothing return; if ( andelse {looking_at_char('&')} {not is_escaped()} ) { () = right(1); return; } if ( looking_at("\\\\") ) { () = right(2); skip_chars(" \t\n"); if ( looking_at("\\hline") ) { () = right(6); skip_chars(" \t\n"); } if ( looking_at("\\end") ) { bskip_chars(" \t"); if ( bolp() ) () = left(1); } return; } if ( looking_at("\\end") ) { bskip_chars(" \t"); if ( bolp() ) () = left(1); array_new_cell(); return; } if ( looking_at("\\begin") ) { eoenv(); () = ffind_char('}'); continue; } if ( andelse {looking_at_char('{')} {not is_escaped()} ) { fsearch_matching_brace(); continue; } % this must be the begin of a command () = right(1); } } static define array_prev_cell() { forever { bskip_chars("^&}\\"); !if ( left(1) ) % == bobp() break; if ( andelse {looking_at_char('&')} {not is_escaped()} ) break; if ( andelse {looking_at_char('}')} {not is_escaped()} ) { bsearch_matching_brace(); continue; } if ( looking_at("\\end") ) { boenv(); continue; } if ( looking_at("\\begin") ) { % This must be the begin of the array environment () = right(6); do { fsearch_matching_brace(); () = right(1); } while ( looking_at_char('{') ); break; } if ( looking_at("\\\\") ) break; } } static define array_edit_column_format() { variable start = create_user_mark(); variable e_name = env_name(1); variable num_cols; if ( assoc_key_exists(array_columns, e_name) ) num_cols = array_columns[e_name]; else num_cols = array_columns[ chop_star(e_name) ]; if (num_cols >= 0) { goto_user_mark(start); throw UsageError, "environment has no column definition"; } () = right(strlen(e_name) + 8); % \begin{$e_name} variable col; (,col) = cmd_parse_args(1, -num_cols); col = col[-1]; try { variable col_len = strlen(col); col = read_mini("Column format:", "", col); if (col == "") return; () = left(col_len + 1); % $col} () = replace_chars(col_len, col); } catch UserBreakError; finally { goto_user_mark(start); } } %%%%%%%%%% % % Label % private variable label_insert_mark = NULL; static define label_insert_at_mark() { if (label_insert_mark == NULL) { label_insert_mark = create_user_mark(); message("Now go to the point where you want to set the label and hit ^Clm again"); } else { cmd_insert("label"); if (andelse {left(1)} {looking_at_char('}')}) { push_mark(); ()=bfind_char('{'); ()=right(1); variable label = bufsubstr(); goto_user_mark(label_insert_mark); if ( pkg_loaded("hyperref") ) "\\autoref{"; else if ( andelse {label[[0:1]] == "eq"} {pkg_loaded("amsmath")} ) "\\eqref{"; else "\\ref{"; insert(() + label + "}"); } label_insert_mark = NULL; } } static define label_ref() { if ( pkg_loaded("hyperref") ) cmd_insert("autoref"); else cmd_insert("ref"); } %%%%%%%%%% % % Folding % static define fold(f_lvl); static define fold(f_lvl) { variable start_mark = create_user_mark(); try { while (f_lvl < 0) { variable mark = create_user_mark(); switch ( env_name(1) ) { case NULL: throw UsageError, "There's no level below the file level"; } { case "document": goto_user_mark(mark); break; } ++f_lvl; } if (f_lvl < 0) { throw NotImplementedError; forever { !if ( search_not_commented(&re_bsearch, "\\[cs][heu][acb][pts]"R, 0) ) % Fixme: PCRE { break; } if ( looking_at("\\chapter") ) f_lvl += 2; else if ( looking_at("\\section") ) f_lvl += 3; else if ( looking_at("\\subsection") ) f_lvl += 4; else if ( looking_at("\\subsubsection") ) f_lvl += 5; else continue; } if (f_lvl < 0) throw UsageError, "There's no level below the file level"; switch (f_lvl) { case 1: "\\begin{document}"; } { case 2: "\\chapter" or "\\section"; } { case 1: "\\begin{document}"; } } variable first_line, level; switch ( env_name(1) ) { case "document": variable beg_doc_mark = create_user_mark(), start_level; variable level_names = ["chapter", "section", "subsection", "subsubsection"]; while (length(level_names) > 0) { if ( fsearch("\\" + level_names[0]) ) break; level_names = level_names[[1:]]; } % add the file level (0) and the begin--end{document} level (1) #if (_slang_version < 20007) level_names = ["\\file-level", "\\doc-level", level_names]; #else level_names = [NULL, NULL, level_names]; #endif goto_user_mark(start_mark); forever { if ( not search_not_commented(&re_bsearch, "\\[cs][heu][acb][pts]"R, 0) or % Fixme: PCRE create_user_mark() < beg_doc_mark) { goto_user_mark(beg_doc_mark); start_level = 1; () = right(1); break; } () = right(1); push_mark(); skip_chars(TeX_Command_Chars); start_level = wherefirst(level_names == chop_star( bufsubstr() )); if (start_level != NULL) { (,) = cmd_parse_args(1,1); break; } } f_lvl += start_level; if (f_lvl == 1) % folding level 1 is easy { () = down(1); push_mark(); eoenv(); () = up(1); set_region_hidden(1); return; } if (start_level == f_lvl) % if we start on the fold level, we must start with a mark { () = down(1); push_mark(); first_line = what_line; } level = start_level; forever { !if ( search_not_commented(&re_fsearch, "\\[cseb][heun][acbdg][ptsi{]"R, 1) ) % Fixme: PCRE eob(); variable last_level = level; () = right(1); if ( looking_at("begin{") ) ++level; else if ( looking_at("end{document}") or eobp() ) level = 0; else if ( looking_at("end{") ) { --level; if (f_lvl == level) % this is not a barrier like \section that stops % and starts a folding region continue; } else { push_mark(); skip_chars(TeX_Command_Chars); level = wherefirst(level_names == chop_star( bufsubstr() )); if (level == NULL) { level = last_level; continue; } (,) = cmd_parse_args(1,1); } % f_lvl <= last_level: we come from a level where folding % is active % level <= f_lvl: level < f_lvl or level == f_lvl % level < f_lvl: we jump to a level where folding is % inactive % level == f_lvl: we jumped across a barrier that is on % f_lvl - 1---it must become visible if (level <= f_lvl and f_lvl <= last_level) { push_spot(); () = up(1); if (what_line <= first_line) % there is nothing to fold pop_mark(0); else set_region_hidden(1); pop_spot(); } if (level < start_level) break; % last_level < f_lvl and f_lvl <= level: % we come from a level where folding is inactive and % continue on a level where folding is active % level == f_lvl and f_lvl <= last_level: % we come from a level where folding is active and % jumped across a barrier on f_lvl - 1 that must % become visible if ((last_level < f_lvl and f_lvl <= level) or (level == f_lvl and f_lvl <= last_level)) { () = down(1); push_mark(); first_line = what_line; } } } { case NULL: doc_find(); variable in_preample = create_user_mark() < start_mark; if (in_preample) { if (f_lvl != 0) return; } else if (f_lvl == 0) throw InvalidParmError, "Folding the while file is not supported"; if (f_lvl <= 1) { (,) = cmd_parse_args(1,1); () = down(1); push_mark(); first_line = what_line; !if ( search_not_commented(&fsearch, "\\begin{document}", 1) ) { % fixme: throw pop_mark(0); return; } push_spot(); () = up(1); if (what_line <= first_line) pop_mark(0); else set_region_hidden(1); pop_spot(); if (in_preample) return; } else !if ( search_not_commented(&fsearch, "\\begin{document}", 1) ) { % fixme: throw return; } () = right(1); fold(f_lvl - 1); } { level = 0; do { if ( looking_at("\\begin{") ) { if (level < f_lvl) ++level; else { () = down(1); push_mark(); first_line = what_line; eoenv(); push_spot(); () = up(1); if (what_line <= first_line) % there is nothing to fold pop_mark(0); else set_region_hidden(1); pop_spot(); } } else if ( looking_at("\\end{") ) --level; () = right(1); } while ( andelse {level > 0} {re_fsearch("\\[be][en][gd]"R)} ); } } finally { goto_user_mark(start_mark); if ( is_line_hidden() ) skip_hidden_lines_backward(1); } } %%%%%%%%%% % % Helping stuff % %!%+ %\variable{User_Mark line_mark} %\synopsis{holds the mark of the current line} %\description % we need this variable as buffer for the line mark. % if the line mark isn't associated with a variable it isn't shown % %\seealso{update_log_hook()} %!%- private variable line_mark; %!%+ %\function{update_log_hook} %\synopsis{Marks the current line} %\usage{update_log_hook()} %\description % This function marks the current line for highlighting. % % It is used in the buffers with the output of latex and other programms % to show better the line the cursor is in. %!%- private define update_log_hook() { line_mark = create_line_mark(color_number("region")); } private variable TEXDOC_KEYMAP = "texdoc-help"; !if ( keymap_p(TEXDOC_KEYMAP) ) { make_keymap(TEXDOC_KEYMAP); definekey("latex->texdoc_show()", "g", TEXDOC_KEYMAP); definekey("latex->texdoc_show()", "\n", TEXDOC_KEYMAP); definekey("latex->texdoc_show()", "\r", TEXDOC_KEYMAP); definekey("delbuf(whatbuf());call(\"delete_window\")", "q", TEXDOC_KEYMAP); definekey("delbuf(whatbuf());call(\"delete_window\")", "c", TEXDOC_KEYMAP); definekey("delbuf(whatbuf());call(\"delete_window\")", "^G", TEXDOC_KEYMAP); } static define texdoc_show() { variable file = line_as_string(); delbuf( whatbuf() ); call("delete_window"); variable file_bn = path_basename(file); variable ext = path_extname(file_bn); if ( is_list_element(".gz,.bz2", ext, ',') ) { file_bn = path_sans_extname(file_bn); ext = path_extname(file_bn); } if (file_bn == "README" or is_list_element(".tex,.txt", ext, ',')) { () = find_file(file); return; } () = system("texdoc '$file' &"$); } private define texdoc_run(td_arg) { try { variable pattern = read_mini("Search pattern:", "", ""); pop2buf("*Texdoc help*"); set_readonly(0); erase_buffer(); () = run_shell_cmd("texdoc "+td_arg+" '"+pattern+"'"); use_keymap(TEXDOC_KEYMAP); set_buffer_hook("update_hook", &update_log_hook); set_buffer_modified_flag(0); set_readonly(1); bob(); } catch UserBreakError: { } } static define texdoc_help() { texdoc_run("-l"); } static define texdoc_search() { texdoc_run("-s"); } static define texdoc(what) { () = system("texdoc '$what' &"$); } static define info_page() { info_reader(); if (_NARGS) { try { "(latex)"; exch; info_find_node( () + () ); } catch AnyError: info_find_node("(latex)Top"); } else info_find_node("(latex)Top"); } %%%%%%%%%% % % Keyboard stuff % static define insert_quote() { if ( orelse {is_escaped()} {is_verbatim()} {andelse {LAST_CHAR != '"'} {LAST_CHAR != '`'}} ) { call("self_insert_cmd"); return; } variable lang = NULL; if ( pkg_loaded("babel") ) { variable opt = pkg_options("babel"); if (opt != "") lang = strchop(opt, ',', '\0')[-1]; else { (opt,) = doc_options_class(); if (opt != "") { variable array = strchop(opt, ',', '\0'); #ifexists array_reverse array_reverse(array); #endif foreach opt (array) if ( is_list_element("ngerman,german,french,francais,frenchb", opt, ',') ) { lang = opt; #ifnexists array_reverse break; #endif } } } } else if ( orelse {pkg_loaded("ngerman")} {pkg_loaded("german")} ) lang = "german"; variable lquote, rquote; switch (lang) { case "french" or case "francais": switch (LAST_CHAR) { case '"': lquote = "<<~"; rquote = "~>>"; } { case '`': lquote = "<~"; rquote = "~>"; } } { case "frenchb": switch (LAST_CHAR) { case '"': lquote = "\\og"; rquote = "\\fg"; } { case '`': lquote = "`"; rquote = "'"; } } { case "german" or case "ngerman": switch (LAST_CHAR) { case '"': lquote = "\"`"; rquote = "\"'"; } { case '`': lquote = "\\glq"; rquote = "\\grq"; } } { case "russian": switch (LAST_CHAR) { case '"': lquote = "\"`"; rquote = "\"'"; } { case '`': lquote = "`"; rquote = "'"; } } { % case "english": switch (LAST_CHAR) { case '"': lquote = "``"; rquote = "''"; } { case '`': lquote = "`"; rquote = "'"; } } variable start_mark = create_user_mark(); variable quote_sign = lquote, search = &bsearch(); forever { !if ( @search(quote_sign) ) break; if ( is_commented() ) continue; if (quote_sign == lquote) { () = left(1); if ( looking_at( substr(quote_sign, 1, 1) ) ) % ` \subset ``, ' \subset '' continue; quote_sign = rquote; search = &fsearch(); } else { if ( looking_at( quote_sign + substr(quote_sign, strlen(quote_sign), 1) ) ) % ` \subset ``, ' \subset '' () = right(1); else { if (create_user_mark() < start_mark) quote_sign = lquote; break; } } } goto_user_mark(start_mark); if (substr(quote_sign, 1, 1) == "\\") cmd_insert( substr(quote_sign, 2, -1) ); else insert(quote_sign); } static define insert_dollar() { if ( orelse {is_escaped()} {is_verbatim()} {not is_math()} ) { call("self_insert_cmd"); return; } #ifexists abbrev_table_p call("self_insert_cmd"); % expand abbreviations () = left(1); del(); #endif push_spot(); variable close_stack = list_new(), open_stack = list_new(); forever { bskip_chars("^$(){}[]"); () = left(1); variable ch = what_char(), counterpart, alt_counterpart = ""; switch (ch) { case ')' or case ']' or case '}': if ( andelse {ch == '}'} {is_escaped()} ) ch = "\\}"; else ch = char(ch); list_append(close_stack, ch, -1); continue; } { case '$': if ( is_escaped() ) continue; else break; } { case '(': counterpart = ")"; alt_counterpart = "]"; } { case '[': counterpart = "]"; alt_counterpart = ")"; } { case '{': if ( is_escaped() ) counterpart = "\\}"; else counterpart = "}"; } if (length(close_stack) == 0) list_append(open_stack, counterpart, -1); else { if (close_stack[-1] == counterpart or close_stack[-1] == alt_counterpart) list_delete(close_stack, -1); else list_append(open_stack, counterpart, -1); } } if (BLINK) { update_sans_update_hook(0); () = input_pending(5); } pop_spot(); while (length(open_stack) > 0) { variable looking_for = list_pop(open_stack, 0); if ( looking_at(looking_for) ) () = right( strlen(looking_for) ); else insert(looking_for); } if ( looking_at_char('$') ) () = right(1); else insert_char('$'); } static define insert_without_spaces() { variable insert_backslash = is_escaped(); if (insert_backslash xor (LAST_CHAR == ',' or LAST_CHAR == ' ')) { call("self_insert_cmd"); return; } if (insert_backslash) { () = left(1); del(); } trim(); if ( andelse {bolp()} {left(1)} ) { del(); trim(); } if (insert_backslash) insert_char('\\'); call("self_insert_cmd"); update(1); forever { variable ch = getkey(); if (ch != ' ' and ch != '\t' and ch != '\n') { ungetkey(ch); break; } flush("Whitespaces around a special space make it meaningless"); } } #ifnexists isalpha define isalpha(ch) { % Fixme! fails for ß return orelse {ch != toupper(ch)} {ch != tolower(ch)}; } #endif static define math_arrow(); % declare it for recursion static define math_arrow() { if ( orelse {is_escaped()} {is_verbatim()} ) { call("self_insert_cmd"); return; } variable arrow_str; switch (LAST_CHAR) { case '>': () = left(1); switch ( what_char() ) { case '-': () = left(1); switch (what_char()) { case '-': () = left(1); switch (what_char) { case '<': deln(3); arrow_str = "longleftrightarrow"; } { case '|': deln(3); arrow_str = "longmapsto"; } { () = right(1); deln(2); arrow_str = "longrightarrow"; } } { case '|': deln(2); arrow_str = "mapsto"; } { case '<': deln(2); arrow_str = "leftrightarrow"; } { case '`': deln(2); arrow_str = "hookrightarrow"; } { () = right(1); del(); arrow_str = "rightarrow"; } } { case '=': () = left(1); switch (what_char()) { case '=': () = left(1); if (what_char() == '<') { deln(3); arrow_str = "Longleftrightarrow"; } else { () = right(1); deln(2); arrow_str = "Longrightarrow"; } } { case '<': deln(2); arrow_str = "Leftrightarrow"; } { () = right(1); del(); arrow_str = "Rightarrow"; } } { case '>': del(); arrow_str = "gg"; } { () = right(1); call("self_insert_cmd"); return; } } { case '-' or case '=': () = left(1); switch ( what_char() ) { case LAST_CHAR: () = left(1); switch ( what_char() ) { case '<': () = right(2); insert_char(LAST_CHAR); update_sans_update_hook(1); variable new_char = getkey(); if (new_char == '>') { LAST_CHAR = '>'; math_arrow(); return; } else { ungetkey(new_char); () = left(3); deln(3); if (LAST_CHAR == '-') arrow_str = "longleftarrow"; else arrow_str = "Longleftarrow"; } } { () = right(2); call("self_insert_cmd"); return; } } { case '<': () = right(1); insert_char(LAST_CHAR); update_sans_update_hook(1); new_char = getkey(); switch (new_char) { case '>' or case '-' or case '=': LAST_CHAR = new_char; math_arrow(); return; } { ungetkey(new_char); () = left(2); deln(2); if ( LAST_CHAR == '-' ) arrow_str = "leftarrow"; else arrow_str = "Leftarrow"; } } { () = right(1); if (LAST_CHAR == '-') typo_hyphen(); else call("self_insert_cmd"); return; } } { throw UsageError, "unknow character: $LAST_CHAR"$; } cmd_insert(arrow_str); } static define math_ll() { if ( left(1) ) { if ( what_char() == '<' ) { del(); cmd_insert("ll"); } else { ()=right(1); call("self_insert_cmd"); } } else call("self_insert_cmd"); } static define math_right_parenthesis() { if (what_char() == '}') { push_spot(); find_matching_delimiter(LAST_CHAR) != 1; pop_spot(); if ( () ) () = right(1); } push_spot(); if (find_matching_delimiter(LAST_CHAR) == 1) { push_mark(); bskip_chars("leftbigB\\"); variable size = bufsubstr(), delim; switch ( strlow(size) ) { case "\\left": delim = "\\right"; } { case "\\big" or case "\\bigg": delim = size; } { case "\\bigl" or case "\\biggl": delim = size[[:-2]] + "r"; } { delim = ""; } pop_spot(); insert(delim); } else pop_spot(); call("self_insert_cmd"); } static define insert_limits_char() { if ( orelse {is_escaped()} {is_verbatim()} ) { call("self_insert_cmd"); return; } variable skip_dollar_after_compl = 0; if ( blooking_at("$") ) { skip_dollar_after_compl = 1; () = left(1); } push_spot(); bskip_chars(TeX_Command_Chars + "0-9"); () = left(1); !if ( looking_at_char('\\') ) () = right(1); variable insert_dollar = 0; !if ( is_math() ) { insert_dollar = 1; skip_dollar_after_compl = 1; insert_char('$'); } push_mark(); pop_spot(); variable last_cmd = bufsubstr(); if (insert_dollar) { insert_char('$'); if (last_cmd != "$") % if no text was enclosed in $ $, the arrangement of spot and % mark is difficult and leads to ^{}$$. This deals with this. () = left(1); } switch (last_cmd) { case "\\rightarrow" or case "\\leftarrow": () = left( strlen(last_cmd)-1 ); insert_char('x'); () = right( strlen(last_cmd)-1 ); if (LAST_CHAR == '_') { insert("[]{}"); () = left(3); } else { insert("{}"); () = left(1); } return; } { case "\\cup" or case "\\cap" or case "\\vee" or case "\\wedge": () = left( strlen(last_cmd)-1 ); insert("big"); () = right( strlen(last_cmd)-1 ); last_cmd = "\\big" + substr(last_cmd, 2, -1); } insert(char(LAST_CHAR) + "{}"); () = left(1); if (last_cmd[0] != '\\') % completion is only supported for TeX commands return; push_spot(); () = left(strlen(last_cmd) + 2); % $last_cmd$LAST_CHAR{ % the \ at the begin is the regexp quote of the \ in the command !if ( re_bsearch("\\$last_cmd[_^]"$) ) { pop_spot(); return; } () = right( strlen(last_cmd) ); variable counterpart_compl, compl; !if ( looking_at_char(LAST_CHAR) ) { () = right(1); (,counterpart_compl) = cmd_parse_args(0,1); } if ( looking_at_char(LAST_CHAR) ) { () = right(1); (,compl) = cmd_parse_args(0,1); } if (not __is_initialized(&counterpart_compl) and (looking_at_char('^') or looking_at_char('_')) ) { () = right(1); (,counterpart_compl) = cmd_parse_args(0,1); } pop_spot(); !if ( __is_initialized(&compl) ) return; push_visible_mark(); insert( str_compress_tex(compl[0]) ); update(1); variable k = getkey(); switch ( char(k) ) { case Key_Return or case Key_Enter: pop_mark(0); () = right(1); !if ( __is_initialized(&counterpart_compl) ) { if (skip_dollar_after_compl) () = right(1); return; } } { del_region(); ungetkey(k); return; } push_visible_mark(); if (LAST_CHAR == '_') "^{"; else "_{"; insert(() + str_compress_tex(counterpart_compl[0]) + "}"); update(1); k = getkey(); switch ( char(k) ) { case Key_Return or case Key_Enter: pop_mark(0); if (skip_dollar_after_compl) () = right(1); } { del_region(); ungetkey(k); } } static define key_fold() { variable arg = prefix_argument(); try { switch (arg) { case NULL: arg = 0; } % default: fold this level { case 9: % Fixme: This should be 0 digit_arg doesn't support it arg = integer( read_mini("Level to fold:", "9", "") ); } fold(arg); } catch UserBreakError; } static define key_unfold() { try { variable arg = prefix_argument(0); push_spot(); skip_hidden_lines_backward(1); () = down(1); push_mark(); skip_hidden_lines_forward(1); () = up(1); set_region_hidden(0); pop_spot(); if (arg > 0) fold(arg); } catch UserBreakError; } static define textormath(text, math) { variable cmd; if ( is_math() ) cmd = math; else cmd = text; if (cmd[0] == ' ') insert( substr(cmd, 2, strlen(cmd)) ); else { if ( is_internal(cmd) ) call(cmd); else eval(cmd); } } private define defkeyr_textormath_cmd(text, math, key, mode) { text = make_printable_string("latex->cmd_insert(\"$text\")"$); math = make_printable_string("latex->cmd_insert(\"$math\")"$); definekey_reserved("latex->textormath($text, $math)"$, key, mode); } private variable SIMPLE_KEYMAP = MODE + "-simple"; !if ( keymap_p(SIMPLE_KEYMAP) ) { make_keymap(SIMPLE_KEYMAP); % templates - ^CT or ^C^T definekey_reserved("menu_select_menu(\"Global.M&ode.&Templates\")", "t", SIMPLE_KEYMAP); definekey_reserved("menu_select_menu(\"Global.M&ode.&Templates\")", "^T", SIMPLE_KEYMAP); % packages - ^CP definekey_reserved("latex->pkg_prompt", "p", SIMPLE_KEYMAP); % array - ^Ca definekey_reserved("latex->array_edit_column_format", "ae", SIMPLE_KEYMAP); definekey_reserved("latex->array_next_cell", "a\t", SIMPLE_KEYMAP); definekey_reserved("latex->array_next_cell", "aa", SIMPLE_KEYMAP); definekey_reserved("latex->array_new_cell", "an", SIMPLE_KEYMAP); definekey_reserved("latex->array_prev_cell", "ap", SIMPLE_KEYMAP); % environments - ^CE definekey_reserved("latex->boenv", "e<", SIMPLE_KEYMAP); definekey_reserved("latex->env_close", "ec", SIMPLE_KEYMAP); definekey_reserved("latex->env_close", "}", SIMPLE_KEYMAP); definekey_reserved("latex->env_prompt", "ee", SIMPLE_KEYMAP); definekey_reserved("latex->env_prompt", "e\r", SIMPLE_KEYMAP); definekey_reserved("latex->env_rename", "er", SIMPLE_KEYMAP); definekey_reserved("latex->eoenv", "e>", SIMPLE_KEYMAP); % sections - ^Cs definekey_reserved("latex->cmd_insert(\"appendix\")", "sa", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"chapter\")", "sc", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"part\")", "sp", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"section\")", "ss", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"subsection\")", "su", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"subsubsection\")", "sb", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"paragraph\")", "sg", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"subparagraph\")", "sh", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"minisec\")", "sm", SIMPLE_KEYMAP); % commands - ^Cd definekey_reserved("latex->cmd_prompt", "d", SIMPLE_KEYMAP); % fonts - ^CF definekey_reserved("latex->font_resize(1)", "f-", SIMPLE_KEYMAP); definekey_reserved("latex->font_resize(0)", "f+", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathcal\")", "fa", SIMPLE_KEYMAP); defkeyr_textormath_cmd("textbf", "mathbf", "fb", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathbf\")", "fB", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"textsc\")", "fc", SIMPLE_KEYMAP); defkeyr_textormath_cmd("underline", "underbar", "fd", SIMPLE_KEYMAP); defkeyr_textormath_cmd("underline", "underbar", "f_", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"underbar\")", "fD", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"emph\")", "fe", SIMPLE_KEYMAP); defkeyr_textormath_cmd("textsf", "mathsf", "ff", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathsf\")", "fF", SIMPLE_KEYMAP); defkeyr_textormath_cmd("textit", "mathit", "fi", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathit\")", "fI", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathfrak\")", "fk", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"textmd\")", "fm", SIMPLE_KEYMAP); defkeyr_textormath_cmd("textnormal", "mathnormal", "fn", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathnormal\")", "fN", SIMPLE_KEYMAP); definekey_reserved("latex->font_cmd", "fp", SIMPLE_KEYMAP); defkeyr_textormath_cmd("textrm", "mathrm", "fr", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathrm\")", "fR", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"textsl\")", "fs", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"textup\")", "fu", SIMPLE_KEYMAP); defkeyr_textormath_cmd("texttt", "mathtt", "ft", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mathtt\")", "fT", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"verb\")", "fv", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"text\")", "fx", SIMPLE_KEYMAP); % definekey_reserved("latex_modify_font(\"\")", "fD", SIMPLE_KEYMAP); % definekey_reserved("latex_rename_font", "fN", SIMPLE_KEYMAP); % links - ^CL definekey_reserved("latex->cmd_insert(\"label\")", "ll", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"label\")", "^L^L", SIMPLE_KEYMAP); definekey_reserved("latex->label_insert_at_mark", "lm", SIMPLE_KEYMAP); definekey_reserved("latex->label_insert_at_mark", "^L^M", SIMPLE_KEYMAP); definekey_reserved("latex->label_ref", "lr", SIMPLE_KEYMAP); definekey_reserved("latex->label_ref", "^L^R", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pageref\")", "lp", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pageref\")", "^L^P", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cite\")", "lb", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cite\")", "^l^b", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"url\")", "lu", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"url\")", "^L^U", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nocite\")", "ln", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nocite\")", "^L^N", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"index\")", "li", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"index\")", "^L^I", SIMPLE_KEYMAP); % PSTricks - ^Ci definekey_reserved("latex->pst_move_points", "im", SIMPLE_KEYMAP); definekey_reserved("latex->pst_update_pic_size", "iu", SIMPLE_KEYMAP); % math symbols - ^C m definekey_reserved("latex->cmd_insert(\"alpha\")", "ma", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"beta\")", "mb", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"chi\")", "mc", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"delta\")", "md", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"epsilon\")", "me", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"phi\")", "mf", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"gamma\")", "mg", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"eta\")", "mh", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"kappa\")", "mk", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"lambda\")", "ml", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"mu\")", "mm", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nabla\")", "mN", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nu\")", "mn", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"omega\")", "mo", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pi\")", "mp", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"theta\")", "mq", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"rho\")", "mr", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"sigma\")", "ms", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"tau\")", "mt", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"upsilon\")", "mu", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Xi\")", "mX", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"xi\")", "mx", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"psi\")", "my", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"zeta\")", "mz", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Delta\")", "mD", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Gamma\")", "mG", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Theta\")", "mQ", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Lambda\")", "mL", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Phi\")", "mV", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Psi\")", "mY", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Pi\")", "mP", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Sigma\")", "mS", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Upsilon\")", "mU", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Omega\")", "mO", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"rightarrow\")", "m^f", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"leftarrow\")", "m^b", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"uparrow\")", "m^p", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"downarrow\")", "m^n", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"leq\")", "m<", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"geq\")", "m>", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"tilde\")", "m~", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"infty\")", "mI", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"forall\")", "mA", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"exists\")", "mE", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"neg\")", "m!", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"in\")", "mi", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"times\")", "m*", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cdot\")", "m.", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"subset\")", "m{", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"supset\")", "m}", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"subseteq\")", "m[", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"supseteq\")", "m]", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"not\")", "m/", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"setminus\")", "m\\", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cup\")", "m+", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cap\")", "m-", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"wedge\")", "m&", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"vee\")", "m|", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"langle\")", "m(", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"rangle\")", "m)", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"exp\")", "m^e", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"sin\")", "m^s", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cos\")", "m^c", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"sup\")", "m^^", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"inf\")", "m^_", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"det\")", "m^d", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"lim\")", "m^l", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"tan\")", "m^t", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"hat\")", "m^", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"vee\")", "mv", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"emptyset\")", "m0", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"colon\")", "m:", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"infty\")", "m8", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"ne\")", "m=", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"overline\")", "m_", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Phi\")", "mF", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"omega\")", "mw", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"Omega\")", "mW", SIMPLE_KEYMAP); % not so common math stuff - ^C n definekey_reserved("latex->cmd_insert(\"mathcal\")", "nc", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\")", "nf", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nicefrac\")", "nF", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"int\")", "ni", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"log\")", "nl", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pmod\")", "nm", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"oint\")", "no", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"prod\")", "np", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"sum\")", "ns", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"sqrt\")", "nq", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\"])", "n1", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"2\"])", "n2", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"3\"])", "n3", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"4\"])", "n4", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"5\"])", "n5", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"6\"])", "n6", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"7\"])", "n7", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"8\"])", "n8", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"frac\", 1, [\"1\", \"9\"])", "n9", SIMPLE_KEYMAP); % breaks - ^CK definekey_reserved("latex->cmd_insert(\"newline\");newline()", "kl", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"newline\");newline()", "^K^L", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"linebreak[1]\");newline()", "kb", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"linebreak[1]\");newline()", "^K^B", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"newpage\");newline()", "kp", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"newpage\");newline()", "^K^P", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"clearpage\");newline()", "kc", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"clearpage\");newline()", "^K^C", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cleardoublepage\");newline()", "kd", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"cleardoublepage\");newline()", "^K^D", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pagebreak\");newline()", "kr", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"pagebreak\");newline()", "^K^R", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nolinebreak[1]\");newline()", "kn", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nolinebreak[1]\");newline()", "^K^N", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nopagebreak\");newline()", "ko", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"nopagebreak\");newline()", "^K^O", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"enlargethispage\")", "ke", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"enlargethispage\")", "^K^E", SIMPLE_KEYMAP); % math arrows - ^C + arrow definekey_reserved("latex->cmd_insert(\"uparrow\")", Key_Up, SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"downarrow\")", Key_Down, SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"leftarrow\")", Key_Left, SIMPLE_KEYMAP); definekey_reserved("latex->cmd_insert(\"rightarrow\")", Key_Right, SIMPLE_KEYMAP); definekey_reserved("latex->newline_with_completion", Key_Return, SIMPLE_KEYMAP); % special characters definekey_reserved(" \\$", "$", SIMPLE_KEYMAP); definekey_reserved(" \\&", "&", SIMPLE_KEYMAP); definekey_reserved(" \\%", "%", SIMPLE_KEYMAP); definekey_reserved(" \\_", "_", SIMPLE_KEYMAP); definekey_reserved(" \\#", "#", SIMPLE_KEYMAP); definekey_reserved(" \\{", "(", SIMPLE_KEYMAP); definekey_reserved(" \\}", ")", SIMPLE_KEYMAP); definekey_reserved(" \\textless{}", "<", SIMPLE_KEYMAP); definekey_reserved(" \\textgreater{}", ">", SIMPLE_KEYMAP); definekey_reserved(" \\textbackslash{}", "\\", SIMPLE_KEYMAP); definekey_reserved(" \\textbar{}", "|", SIMPLE_KEYMAP); definekey_reserved(" \\textasciicircum{}", "^", SIMPLE_KEYMAP); definekey_reserved(" \\textasciitilde{}", "~", SIMPLE_KEYMAP); % stuff from latex_external - ^C r definekey_reserved("latex_external->select_master_file", "ra", SIMPLE_KEYMAP); definekey_reserved("latex_external->bibtex", "rb", SIMPLE_KEYMAP); definekey_reserved("latex_external->show_bibtex_log", "rv", SIMPLE_KEYMAP); definekey_reserved("latex_external->clearup", "rc", SIMPLE_KEYMAP); definekey_reserved("latex_external->makeindex", "ri", SIMPLE_KEYMAP); definekey_reserved("latex_external->show_mkidx_log", "ru", SIMPLE_KEYMAP); definekey_reserved("latex_external->mrproper", "rm", SIMPLE_KEYMAP); definekey_reserved("latex_external->cust_view", "ro", SIMPLE_KEYMAP); definekey_reserved("latex_external->print", "rp", SIMPLE_KEYMAP); % often used stuff from latex_external definekey_reserved("latex_external->compose", "c", SIMPLE_KEYMAP); definekey_reserved("latex_external->compose", "^C", SIMPLE_KEYMAP); definekey_reserved("latex_external->view", "v", SIMPLE_KEYMAP); definekey_reserved("latex_external->view", "^V", SIMPLE_KEYMAP); definekey_reserved("latex_external->pop_log_file", "y", SIMPLE_KEYMAP); definekey_reserved("latex_external->pop_log_file", "^y", SIMPLE_KEYMAP); % help definekey_reserved("latex->texdoc_help()", "ht", SIMPLE_KEYMAP); definekey_reserved("latex->texdoc_search()", "hT", SIMPLE_KEYMAP); definekey_reserved("latex->texdoc_search()", "^h^T", SIMPLE_KEYMAP); definekey_reserved("latex->texdoc(\"symbols-a4\")", "hs", SIMPLE_KEYMAP); definekey_reserved("latex->texdoc(\"symbols-a4\")", "^H^S", SIMPLE_KEYMAP); definekey_reserved("latex->info_page", "hi", SIMPLE_KEYMAP); definekey_reserved("latex->info_page", "^h^I", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_help", "hc", SIMPLE_KEYMAP); definekey_reserved("latex->cmd_help", "^H^C", SIMPLE_KEYMAP); definekey_reserved("latex->env_help", "he", SIMPLE_KEYMAP); definekey_reserved("latex->env_help", "^H^E", SIMPLE_KEYMAP); definekey_reserved("latex->pkg_help", "hp", SIMPLE_KEYMAP); definekey_reserved("latex->pkg_help", "^H^P", SIMPLE_KEYMAP); definekey_reserved("latex->indent_region", "q", SIMPLE_KEYMAP); definekey_reserved("latex->key_fold", "oo", SIMPLE_KEYMAP); definekey_reserved("latex->key_unfold", "ou", SIMPLE_KEYMAP); } private define definekey_textormath(text, math, key, mode) { text = make_printable_string(text); math = make_printable_string(math); definekey("latex->textormath($text, $math)"$, key, mode); } static define unfold_or_newline() { if (orelse {is_line_hidden()} {andelse {right(1)} {is_line_hidden()}}) key_unfold(); else { () = left(1); call("newline_and_indent"); } } !if ( keymap_p(MODE) ) { copy_keymap(MODE, SIMPLE_KEYMAP); % misc definekey("latex->insert_quote", "\"", MODE); definekey("latex->insert_quote", "`", MODE); definekey("latex->insert_dollar", "$", MODE); definekey("latex->math_ll", "<", MODE); definekey("latex->math_arrow", ">", MODE); definekey("latex->math_arrow", "-", MODE); definekey("latex->math_arrow", "=", MODE); foreach $1 ([" ", "~"]) definekey_textormath("latex->insert_without_spaces", "self_insert_cmd", $1, MODE); % typo stuff definekey_textormath("latex->typo_slash", "self_insert_cmd", "/", MODE); definekey("latex->typo_percent", "%", MODE); definekey_textormath("latex->insert_without_spaces", "latex->typo_german_decimal_point", ",", MODE); definekey("latex->typo_dots", ".", MODE); % math stuff definekey_textormath("self_insert_cmd", "latex->cmd_insert(\"colon\")", ":", MODE); definekey_textormath("self_insert_cmd", "latex->math_right_parenthesis", ")", MODE); definekey_textormath("self_insert_cmd", "latex->math_right_parenthesis", "]", MODE); definekey("latex->insert_limits_char()", "^", MODE); definekey("latex->insert_limits_char()", "_", MODE); definekey("latex->newline_with_completion", Key_Shift_Return, MODE); definekey("latex->unfold_or_newline", Key_Return, MODE); } %%%%%%%%%% % % Menu stuff % private define menu_init_helper(menu, list, fun) { foreach (list) { variable entry = (); if (typeof(entry) == Array_Type) menu_append_item(menu, entry[0], fun, entry[1]); else menu_append_item(menu, entry, "latex->" + string(fun)[[1:]] + "(\"" + str_delete_chars(entry, "&\\"R) + "\")"); } } private define menu_init(menu) { % templates menu_append_popup(menu, "&Templates"); $1 = menu+".&Templates"; if (LaTeX_Template_Dir != NULL) { variable templates = Assoc_Type[String_Type]; foreach ( strtok(LaTeX_Template_Dir, ",") ) { variable tmp = (); foreach ( listdir(tmp) ) { variable file = (); if (strlen( path_sans_extname(file) ) != 0) templates[path_sans_extname(file)] = path_concat(tmp, file); } } variable keys = assoc_get_keys(templates); foreach ( keys[array_sort(keys)] ) { variable templ = (); menu_append_item($1, templ, &templ_insert(), templates[templ]); } } % packages menu_append_popup(menu, "&Packages"); menu_init_helper(menu+".&Packages", ["alltt", "amsmath", "babel", "booktabs", "calc", "color", "eepic", "fancyhdr", "fancyvrb", "geometry", "graphicx", "hyperref", "isolatin1", "longtable", "makeidx", "moreverb", "psfrag", "pslatex", "rotating", "url"], &pkg_insert() ); % environments menu_append_popup(menu, "&Environments"); $1 = menu+".&Environments"; menu_append_item($1, "&array", "latex->env_insert(\"array\", [\"ll\"])"); menu_init_helper($1, {"¢er", "&description", "&enumerate", "&figure", "flush&left", ["flush&Right", "flushright"], "&itemize", ["&List", "list"]}, &env_insert() ); menu_append_item($1, "&minipage", "latex->env_insert(\"minipage\", [\"\\linewidth\"R])"); menu_init_helper($1, ["&picture", ""ation", "qu&ote", "ta&bbing", "&table", "tab&ular"], &env_insert() ); menu_append_item($1, "thebibliograph&y", "latex->env_insert(\"thebibliography\", [\"99\"])"); menu_init_helper($1, {["t&Heorem", "theorem"], "titlepa&ge", "&verbatim", "ver&se"}, &env_insert() ); menu_append_separator($1); menu_append_item($1, "&Custom...", "latex->env_prompt"); menu_append_item($1, "re&Name...", "latex->env_rename"); menu_append_item($1, "close...", "latex->env_close"); menu_append_item($1, "Goto begin...", "latex->boenv"); menu_append_item($1, "Goto end...", "latex->eoenv"); % font menu_append_popup(menu, "&Font"); $1 = menu+".&Font"; menu_append_popup($1, "&Family"); menu_init_helper($1+".&Family", {["&Roman", "textrm"], ["&Sans serif", "textsf"], ["&Typewriter", "texttt"]}, &cmd_insert()); menu_append_popup($1, "&Shape"); menu_init_helper($1+".&Shape", {["&Italic", "textit"], ["&Slanted", "textsl"], ["Small &caps", "textsc"], ["&Upright (normal)", "textup"]}, &cmd_insert()); menu_append_popup($1, "S&eries"); $2 = $1+".S&eries"; menu_append_item($2, "&Boldface", "latex->cmd_insert(\"textbf\")"); menu_append_item($2, "&Medium weight (normal)", "latex->cmd_insert(\"textmd\")"); menu_append_popup($1, "Si&ze"); menu_init_helper($1+".Si&ze", ["&tiny", "s&criptsize", "&footnotesize", "&small", "&normalsize", "&large", "&Large", "L&ARGE", "&huge", "&Huge"], &cmd_insert() ); menu_append_separator($2); menu_append_item($2, "re&size", "latex_resize_font"); menu_init_helper($1, {["&Emphasis", "emph"], ["&Underline", "underline"], ["&Normal font", "textnormal"], ["\\&verb", "verb"]}, &cmd_insert() ); menu_append_separator($1); menu_append_item($1, "&Delete last setting", "latex_modify_font(\"\")"); menu_append_item($1, "Re&name", "latex_rename_font"); % font/environment menu_append_popup($1, "As &Environment"); menu_init_helper($1+".As &Environment", ["&rmfamily", "&itshape", "&mdseries", "&bfseries", "&upshape", "&slshape", "s&ffamily", "s&cshape", "&ttfamily", "&normalfont"], &env_insert() ); % font/math menu_append_popup($1, "&Math"); menu_init_helper($1+".&Math", ["mathr&m", "math&bf", "math&sf", "math&tt", "math&it", "math&normal"], &cmd_insert() ); % sections menu_append_popup(menu, "&Sections"); menu_init_helper(menu+".&Sections", ["\\p&art", "\\&chapter", "\\§ion", "\\s&ubsection", "\\su&bsubsection", "\\¶graph", "\\subparagrap&h", "\\&minisec"], &cmd_insert() ); % paragraph menu_append_popup(menu, "&Paragraph"); $1 = menu+".&Paragraph"; menu_append_item($1, "F&ramed Paragraph", "latex_par_frame"); menu_append_item($1, "&background Colour", "latex_par_bgcolour"); menu_append_item($1, "&foreground Colour", "latex_par_fgcolour"); menu_append_item($1, "\\par&indent", "insert(\"\\\\setlength{\\\\parindent}{0pt}\\n\")"); menu_append_item($1, "\\par&skip", "insert(\"\\\\setlength{\\\\parskip}{3pt}\\n\")"); menu_append_item($1, "\\&marginpar", "latex_cmd(\"marginpar\", 1)"); menu_append_item($1, "\\foot¬e", "latex_cmd(\"footnote\", 1)"); menu_append_item($1, "\\inc&ludegraphics", "latex_includegraphics"); % paragraph/margins menu_append_popup($1, "&Margins"); $2 = $1+".&Margins"; menu_append_item($2, "\\&leftmargin", "latex_cmd(\"setlength{\\\\leftmargin}\", 1)"); menu_append_item($2, "\\&rightmargin", "latex_cmd(\"setlength{\\\\rightmargin}\", 1)"); menu_append_item($2, "\\&evensidemargin", "latex_cmd(\"setlength{\\\\evensidemargin}\", 1)"); menu_append_item($2, "\\&oddsidemargin", "latex_cmd(\"setlength{\\\\oddsidemargin}\", 1)"); menu_append_item($2, "\\&topmargin", "latex_cmd(\"setlength{\\\\topmargin}\", 1)"); menu_append_item($2, "\\text&width", "latex_cmd(\"setlength{\\\\textwidth}\", 1)"); menu_append_item($2, "\\text&height", "latex_cmd(\"setlength{\\\\textheight}\", 1)"); menu_append_popup($1, "Brea&ks"); $2 = $1+".Brea&ks"; menu_append_item($2, "\\new&line", "insert(\"\\\\newline\\n\")"); menu_append_item($2, "\\\\&*[]", "latex_linebreak"); menu_append_item($2, "\\line&break", "insert(\"\\\\linebreak[1]\\n\")"); menu_append_item($2, "\\new&page", "insert(\"\\\\newpage\\n\")"); menu_append_item($2, "\\&clearpage", "insert(\"\\\\clearpage\\n\")"); menu_append_item($2, "\\clear&doublepage", "insert(\"\\\\cleardoublepage\\n\")"); menu_append_item($2, "\\pageb&reak", "insert(\"\\\\pagebreak\\n\")"); menu_append_item($2, "\\&nolinebreak", "insert(\"\\\\nolinebreak[1]\\n\")"); menu_append_item($2, "\\n&opagebreak", "insert(\"\\\\nopagebreak\\n\")"); menu_append_item($2, "\\&enlargethispage", "insert(\"\\\\enlargethispage\\n\")"); % paragraph/spaces menu_append_popup($1, "&Spaces"); $2 = $1+".&Spaces"; menu_append_item($2, "\\&frenchspacing", "insert(\"\\\\frenchspacing\\n\")"); menu_append_item($2, "\\&@.", "insert(\"\\\\@.\\n\")"); menu_append_item($2, "\\&dotfill", "insert(\"\\\\dotfill\\n\")"); menu_append_item($2, "\\&hfill", "insert(\"\\\\hfill\\n\")"); menu_append_item($2, "\\h&rulefill", "insert(\"\\\\hrulefill\\n\")"); menu_append_item($2, "\\&smallskip", "insert(\"\\\\smallskip\\n\")"); menu_append_item($2, "\\&medskip", "insert(\"\\\\medskip\\n\")"); menu_append_item($2, "\\&bigskip", "insert(\"\\\\bigskip\\n\")"); menu_append_item($2, "\\&vfill", "insert(\"\\\\vfill\\n\")"); menu_append_item($2, "\\hspace", "insert(\"\\\\hspace\\n\")"); menu_append_item($2, "\\vs&pace", "insert(\"\\\\vspace\\n\")"); menu_append_item($2, "Set \\baselines&kip", "insert(\"\\\\baselineskip 2\\\\baselineskip\\n\")"); % paragraph/boxes menu_append_popup($1, "Bo&xes"); $2 = $1+".Bo&xes"; menu_append_item($2, "\\&fbox", "latex_cmd(\"fbox\", 1)"); menu_append_item($2, "\\f&ramebox", "latex_cmd(\"framebox[\\\\width][c]\", 1)"); menu_append_item($2, "\\&mbox", "latex_cmd(\"mbox\", 1)"); menu_append_item($2, "\\ma&kebox", "latex_cmd(\"makebox[\\\\width][c]\", 1)"); menu_append_item($2, "\\&newsavebox", "latex_cmd(\"newsavebox\", 1)"); menu_append_item($2, "\\ru&le", "latex_cmd(\"rule{\\\\linewidth}\", 1)"); menu_append_item($2, "\\save&box", "latex_cmd(\"savebox{}[\\\\linewidth][c]\", 1)"); menu_append_item($2, "\\&sbox", "latex_cmd(\"sbox{}\", 1)"); menu_append_item($2, "\\&usebox", "latex_cmd(\"usebox\", 1)"); % links menu_append_popup(menu, "&Links"); menu_init_helper(menu+".&Links", ["\\&label", "\\&ref", "\\&cite", "\\&nocite", "\\&url", "\\n&olinkurl", "\\&index"], &cmd_insert() ); menu_append_popup(menu + ".&Links", "&More index commands"); $1 = menu + ".&Links.&More index commands"; menu_append_item($1, "\\&index{entry!subentry}", "latex->cmd_insert(\"index\", 1, [\"entry!subentry\"])"); menu_append_item($1, "\\&index{entry|(} (begin range)", "latex->cmd_insert(\"index\", 1, [\"entry|(\"])"); menu_append_item($1, "\\&index{entry|)} (end range)", "latex->cmd_insert(\"index\", 1, [\"entry|)\"])"); menu_append_item($1, "\\&index{sortentry@textentry)}", "latex->cmd_insert(\"index\", 1, [\"sortentry@textentry\"])"); menu_append_item($1, "\\&index{entry|format)}", "latex->cmd_insert(\"index\", 1, [\"entry|format\"])"); % math menu_append_popup(menu, "&Math"); $1 = menu+".&Math"; menu_append_item($1, "&Toggle Math Mode", "toggle_math_mode"); menu_append_item($1, "&Greek Letter...", "latex_greek_letter"); menu_append_item($1, "&_{} subscript", "latex_insert_tags(\"_{\", \"}\", 1, 1)"); menu_append_item($1, "&^{} superscript", "latex_insert_tags(\"^{\", \"}\", 1, 1)"); menu_append_item($1, "\\&frac", "latex_insert_tags(\"\\\\frac{\", \"}{}\", 1, 1)"); menu_append_item($1, "\\&int", "latex_insert_tags(\"\\\\int_{\", \"}^{}\", 1, 1)"); menu_append_item($1, "\\&lim", "latex_insert_tags(\"\\\\lim_{\", \"}\", 1, 1)"); menu_append_item($1, "\\&oint", "latex_insert_tags(\"\\\\oint_{\", \"}^{}\", 1, 1)"); menu_append_item($1, "\\&prod", "latex_insert_tags(\"\\\\prod_{\", \"}^{}\", 1, 1)"); menu_append_item($1, "\\&sum", "latex_insert_tags(\"\\\\sum_{\", \"}^{}\", 1, 1)"); menu_append_item($1, "\\s&qrt", "latex_insert_tags(\"\\\\sqrt[]{\", \"}\", 1, 1)"); % math/accents menu_append_popup($1, "&Accents"); menu_init_helper($1+".&Accents", ["hat", "acute", "bar", "dot", "breve", "check", "grave", "vec", "ddot", "tilde", "widetilde", "widehat", "overleftarrow", "overrightarrow", "overline", "underline", "overbrace", "underbrace"], &cmd_insert() ); menu_append_popup($1, "&Delimiters"); menu_append_item($2, "\\left(", "latex_insert(\"left(\")"); menu_append_item($2, "\\right)", "latex_insert(\"right)\")"); menu_append_item($2, "\\left[", "latex_insert(\"left[\")"); menu_append_item($2, "\\right]", "latex_insert(\"right[\")"); menu_append_item($2, "\\left{", "latex_insert(\"left\\\\{\")"); menu_append_item($2, "\\right}", "latex_insert(\"right\\\\}\")"); menu_init_helper($1+".&Delimiters", ["rmoustache", "lmoustache", "rgroup", "lgroup", "arrowvert", "Arrowvert", "bracevert", "lfloor", "rfloor", "lceil", "rceil", "langle", "rangle"], &cmd_insert() ); menu_append_item($2, "\\|", "latex_insert(\"\\|\")"); menu_append_popup($1, "F&unctions"); menu_init_helper($1+".F&unctions", ["arccos", "arcsin", "arctan", "arg", "cos", "cosh", "cot", "coth", "csc", "deg", "det", "dim", "exp", "gcd", "hom", "inf", "ker", "lg", "lim", "liminf", "limsup", "ln", "log", "max", "min", "Pr", "sec", "sin", "sinh", "sup", "tan", "tanh"], &cmd_insert() ); menu_append_popup($1, "Binary &Relations"); menu_init_helper($1+".Binary &Relations", ["leq", "geq", "equiv", "models", "prec", "succ", "sim", "perp", "preceq", "succeq", "simeq", "mid", "ll", "gg", "asymp", "parallel", "subset", "supset", "approx", "bowtie", "subseteq", "supseteq", "cong", "Join", "sqsubset", "sqsupset", "neq", "smile", "sqsubseteq", "sqsupseteq", "doteq", "frown", "in", "ni", "propto", "vdash", "dashv", "not"], &cmd_insert() ); % math/binary operators menu_append_popup($1, "&Binary Operators"); menu_init_helper($1+".&Binary Operators", ["pm", "cap", "diamond", "oplus", "mp", "cup", "bigtriangleup", "ominus", "times", "uplus", "bigtriangledown", "otimes", "div", "sqcap", "triangleleft", "oslash", "ast", "sqcup", "triangleright", "odot", "star", "vee", "bigcirc", "circ", "wedge", "dagger", "bullet", "setminus", "ddagger", "cdot", "wr", "analg"], &cmd_insert() ); % math/spaces menu_append_popup($1, "Spa&ces"); $2 = $1+".Spa&ces"; menu_append_item($2, "\\! -3/18 quad", "insert(\"\\\\! \")"); menu_append_item($2, "\\, 3/18 quad", "insert(\"\\\\, \")"); menu_append_item($2, "\\: 4/18 quad", "insert(\"\\\\: \")"); menu_append_item($2, "\\; 5/18 quad", "insert(\"\\\\; \")"); menu_append_item($2, "\\quad 1em", &cmd_insert(), "quad"); menu_append_item($2, "\\qquad 2em", &cmd_insert(), "qquad"); % math/arrows menu_append_popup($1, "Arro&ws"); menu_init_helper($1+".Arro&ws", {["<-", "leftarrow"], ["<--", "longleftarrow"], ["<=", "Leftarrow"], ["<==", "Longleftarrow"], ["->", "rightarrow"], ["-->", "longrightarrow"], ["=>", "Rightarrow"], ["==>", "Longrightarrow"], "uparrow", "Uparrow", "downarrow", "Downarrow", ["<->", "leftrightarrow"], ["<-->", "longleftrightarrow"], ["<=>", "Leftrightarrow"], ["<==>", "Longleftrightarrow"], "updownarrow", "Updownarrow", ["|->", "mapsto"], ["|-->", "longmapsto"], "hookleftarrow", "hookrightarrow", "leftarpoonup", "rightarpoonup", "leftarpoondown", "rightarpoondown", "nearrow", "searrow", "swarrow", "nwarrow"}, &cmd_insert() ); % math/misc menu_append_popup($1, "&Misc"); menu_init_helper($1+".&Misc", ["ldots", "cdots", "vdots", "ddots", "aleph", "prime", "forall", "infty", "hbar", "emptyset", "exists", "nabla", "surd", "triangle", "imath", "jmath", "ell", "neg", "top", "flat", "natural", "sharp", "wp", "bot", "clubsuit", "diamondsuit", "heartsuit", "spadesuit", "Re", "Im", "angle", "partial"], &cmd_insert() ); % bibliography menu_append_popup(menu, "Bibliograph&y"); $1 = menu+".Bibliograph&y"; menu_append_item($1, "&thebibliography", "latex->env_insert(\"thebibliography\", [\"{99}\"])"); menu_init_helper(menu+".Bibliograph&y", ["\\bib&item", "\\&bibliography", "\\bibliography&style"], &cmd_insert() ); % PSTricks menu_append_popup(menu, "PSTr&icks"); $1 = menu + ".PSTr&icks"; menu_append_item($1, "&pspicture", "latex->env_insert(\"pspicture\")"); menu_init_helper($1, ["\\ps&circle", "\\ps&fram", "\\ps&line", "\\&rput"], &cmd_insert() ); menu_append_separator($1); menu_append_item($1, "Move points in region", "latex->pst_move_points"); menu_append_item($1, "Update pspicture size", "latex->pst_update_pic_size"); menu_append_separator(menu); menu_append_item(menu, "Select M&aster File", "latex_external->select_master_file"); menu_append_item(menu, "Customize Build", "latex_external->cust_view"); menu_append_item(menu, "Compose", "latex_external->compose"); menu_append_item(menu, "&View", "latex_external->view"); menu_append_item(menu, "Show LaTeX lo&g", "latex_external->pop_log_file"); menu_append_item(menu, "Pri&nt", "latex_external->print"); menu_append_item(menu, "&BibTeX", "latex_external->bibtex"); menu_append_item(menu, "Show BibTeX log", "latex_external->show_bibtex_log"); menu_append_item(menu, "Makeinde&x", "latex_external->makeindex"); menu_append_item(menu, "Show Makeindex log", "latex_external->show_mkidx_log"); % menu_append_item(menu, "&Document Outline", "latex_browse_tree"); menu_append_item(menu, "&Remove temp files", "latex_external->clearup"); menu_append_item(menu, "&Remove all files", "latex_external->mrproper"); % convert menu_append_popup(menu, "&Convert"); $1 = menu+".&Convert"; menu_append_item($1, "$:$ -> $\\colon$", "latex_conv->colon"); menu_append_item($1, "\"a -> ä (Latin 1)", "latex_conv->german_lat1"); menu_append_item($1, "\"a -> ä (UTF-8)", "latex_conv->german_utf8"); menu_append_item($1, "\\\"a -> ä (Latin 1)", "latex_conv->native_lat1"); menu_append_item($1, "\\\"a -> ä (UTF-8)", "latex_conv->native_utf8"); menu_append_item($1, "2.0 (\\bf) -> 2e (\\textbf)", "latex_conv->ltx209_ltx2e"); % specials menu_append_popup(menu, "Specials"); $1 = menu + ".Specials"; menu_append_item($1, "Simple keymap", "use_keymap(\"$SIMPLE_KEYMAP\")"$); menu_append_item($1, "Default keymap", "use_keymap(\"$MODE\")"$); menu_append_separator(menu); menu_append_item(menu, "Latex info page", "latex->info_page"); menu_append_item(menu, "TeXdoxTk", "() = system(\"texdoctk &\")"); menu_append_item(menu, "LaTeX Mode &Help", "latex_mode_help"); menu_append_popup(menu, "Common &documentations"); $1 = menu + ".Common &documentations"; menu_init_helper($1, {"&amsldoc", "&de-tex-faq", ["&Hyperref manual", "hyperref/manual"], "&Mathmode", "pst-quickref", "pstricks-doc", "&scrguide", "s&ymbols-a4", "&visualFAQ"}, &texdoc()); } mode_set_mode_info(MODE, "init_mode_menu", &menu_init); create_syntax_table(MODE); define_syntax("%", "", '%', MODE); % Comment Syntax define_syntax('\\', '\\', MODE); % Quote character define_syntax("~^_&#", '+', MODE); % operators define_syntax("|&{}[]", ',', MODE); % delimiters define_syntax(TeX_Command_Chars, 'w', MODE); set_syntax_flags(MODE, 8); #ifdef HAS_DFA_SYNTAX private define setup_dfa_callback(name) { dfa_enable_highlight_cache("latex.dfa", name); % comments: dfa_define_highlight_rule("%(.*[^ \t])?", "comment", name); dfa_define_highlight_rule("\\documentclass.*}"R, "Qpreprocess", name); dfa_define_highlight_rule("\\begin{.*}({.*})*"R, "preprocess", name); dfa_define_highlight_rule("\\end{.*}"R, "Qpreprocess", name); % % known keywords in curly braces % dfa_define_highlight_rule("{article}", "Qstring", name); % dfa_define_highlight_rule("{book}", "Qstring", name); % dfa_define_highlight_rule("{letter}", "Qstring", name); % dfa_define_highlight_rule("{report}", "Qstring", name); % dfa_define_highlight_rule("{slides}", "Qstring", name); % dfa_define_highlight_rule("{document}", "Qstring", name); % dfa_define_highlight_rule("{scrreport}", "Qstring", name); % % environments % dfa_define_highlight_rule("{abstract}", "Qstring", name); % dfa_define_highlight_rule("{array}", "Qstring", name); % dfa_define_highlight_rule("{center}", "Qstring", name); % dfa_define_highlight_rule("{description}", "Qstring", name); % dfa_define_highlight_rule("{displaymath}", "Qstring", name); % dfa_define_highlight_rule("{enumerate}", "Qstring", name); % dfa_define_highlight_rule("{eqnarray}", "Qstring", name); % dfa_define_highlight_rule("{figure}", "Qstring", name); % dfa_define_highlight_rule("{flushleft}", "Qstring", name); % dfa_define_highlight_rule("{flushright}", "Qstring", name); % dfa_define_highlight_rule("{itemize}", "Qstring", name); % dfa_define_highlight_rule("{list}", "Qstring", name); % dfa_define_highlight_rule("{minipage}", "Qstring", name); % dfa_define_highlight_rule("{picture}", "Qstring", name); % dfa_define_highlight_rule("{quotation}", "Qstring", name); % dfa_define_highlight_rule("{quote}", "Qstring", name); % dfa_define_highlight_rule("{tabbing}", "Qstring", name); % dfa_define_highlight_rule("{table}", "Qstring", name); % dfa_define_highlight_rule("{tabular}", "Qstring", name); % dfa_define_highlight_rule("{thebibliography}", "Qstring", name); % dfa_define_highlight_rule("{theorem}", "Qstring", name); % dfa_define_highlight_rule("{titlepage}", "Qstring", name); % dfa_define_highlight_rule("{verbatim}", "Qstring", name); % dfa_define_highlight_rule("{verse}", "Qstring", name); % % font family % dfa_define_highlight_rule("{rmfamily}", "Qkeyword2", name); % dfa_define_highlight_rule("{itshape}", "Qkeyword2", name); % dfa_define_highlight_rule("{mdseries}", "Qkeyword2", name); % dfa_define_highlight_rule("{bfseries}", "Qkeyword2", name); % dfa_define_highlight_rule("{upshape}", "Qkeyword2", name); % dfa_define_highlight_rule("{slshape}", "Qkeyword2", name); % dfa_define_highlight_rule("{sffamily}", "Qkeyword2", name); % dfa_define_highlight_rule("{scshape}", "Qkeyword2", name); % dfa_define_highlight_rule("{ttfamily}", "Qkeyword2", name); % dfa_define_highlight_rule("{normalfont}", "Qkeyword2", name); % dfa_define_highlight_rule("\\text[^{][^{]"R, "keyword2", name); % dfa_define_highlight_rule("{gather\*?}"R, "Qnumber", name); % dfa_define_highlight_rule("{align\*?}"R, "Qnumber", name); % % everithing else between curly braces % % !!! doesn't span multiple lines !!! % dfa_define_highlight_rule("{.*}", "Qkeyword1", name); % dfa_define_highlight_rule("^([^{])*}", "Qkeyword1", name); % dfa_define_highlight_rule("{.*", "keyword1", name); % % short symbols that delimit math: $ \[ \] \( \) % dfa_define_highlight_rule("\\\\\\[.*\\\\\\]", "Qstring", name); % dfa_define_highlight_rule("\\\\\\(.*\\\\\\)", "Qstring", name); % dfa_define_highlight_rule("^.*\\\\[\\)\\]]", "Qstring", name); % dfa_define_highlight_rule("\\\\[\\(\\[].*", "string", name); % dfa_define_highlight_rule("\\$.*\\$", "Qnumber", name); % dfa_define_highlight_rule("\\$.*[^ ]", "number", name); % % dfa_define_highlight_rule("^[^\\$]*\\$", "number", name); % % Fundamental delimiters in the TeX language: {}[] % dfa_define_highlight_rule("[{}\\[\\]]", "delimiter", name); % % \leftX \rightY constructions where X and Y are % % one of \| \{ \} [ ]( ) / | . % dfa_define_highlight_rule("\\\\(left|right)(\\\\\\||\\\\{|\\\\}|" + % "[\\[\\]\\(\\)/\\|\\.])", % "delimiter", name); % % type 2 keywords: font definitions % dfa_define_highlight_rule("\\\\bfseries", "keyword2", name); % dfa_define_highlight_rule("\\\\emph", "keyword2", name); % dfa_define_highlight_rule("\\\\itshape", "keyword2", name); % dfa_define_highlight_rule("\\\\mathbf", "keyword2", name); % dfa_define_highlight_rule("\\\\mathcal", "keyword2", name); % dfa_define_highlight_rule("\\\\mathit", "keyword2", name); % dfa_define_highlight_rule("\\\\mathnormal", "keyword2", name); % dfa_define_highlight_rule("\\\\mathrm", "keyword2", name); % dfa_define_highlight_rule("\\\\mathsf", "keyword2", name); % dfa_define_highlight_rule("\\\\mathtt", "keyword2", name); % dfa_define_highlight_rule("\\\\mdseries", "keyword2", name); % dfa_define_highlight_rule("\\\\normalfont", "keyword2", name); % dfa_define_highlight_rule("\\\\rmfamily", "keyword2", name); % dfa_define_highlight_rule("\\\\scshape", "keyword2", name); % dfa_define_highlight_rule("\\\\sffamily", "keyword2", name); % dfa_define_highlight_rule("\\\\slshape", "keyword2", name); % dfa_define_highlight_rule("\\\\textbf", "keyword2", name); % dfa_define_highlight_rule("\\\\textit", "keyword2", name); % dfa_define_highlight_rule("\\\\textmd", "keyword2", name); % dfa_define_highlight_rule("\\\\textnormal", "keyword2", name); % dfa_define_highlight_rule("\\\\textrm", "keyword2", name); % dfa_define_highlight_rule("\\\\textsc", "keyword2", name); % dfa_define_highlight_rule("\\\\textsf", "keyword2", name); % dfa_define_highlight_rule("\\\\textsl", "keyword2", name); % dfa_define_highlight_rule("\\\\texttt", "keyword2", name); % dfa_define_highlight_rule("\\\\textup", "keyword2", name); % dfa_define_highlight_rule("\\\\ttfamily", "keyword2", name); % dfa_define_highlight_rule("\\\\upshape", "keyword2", name); % % size % dfa_define_highlight_rule("\\tiny"R, "keyword2", name); % dfa_define_highlight_rule("\\scriptsize"R, "keyword2", name); % dfa_define_highlight_rule("\\footnotesize"R, "keyword2", name); % dfa_define_highlight_rule("\\small"R, "keyword2", name); % dfa_define_highlight_rule("\\normalsize"R, "keyword2", name); % dfa_define_highlight_rule("\\large"R, "keyword2", name); % dfa_define_highlight_rule("\\Large"R, "keyword2", name); % dfa_define_highlight_rule("\\LARGE"R, "keyword2", name); % dfa_define_highlight_rule("\\huge"R, "keyword2", name); % dfa_define_highlight_rule("\\Huge"R, "keyword2", name); % type 1 keywords: a backslash followed by % one of -,:;!%$#&_ |\/{}~^´'``.=> : dfa_define_highlight_rule("\\[\-,:;!%\$#&_ \|\\/{}~\^'`\.=>]"R, "keyword1", name); % type 0 keywords: a backslash followed by alpha characters dfa_define_highlight_rule("\\["R + str_quote_string(TeX_Command_Chars, "*", '\\') + "]+", "keyword", name); % % a backslash followed by a single char not covered by one of the % % previous rules is probably an error % dfa_define_highlight_rule("\\.", "error", name); % The symbols ~ ^ _ dfa_define_highlight_rule("[~\\^_]", "operator", name); % numbers dfa_define_highlight_rule("[0-9]([\.,0-9]*[0-9])?"R, "number", name); dfa_define_highlight_rule("\$"R, "number", name); % % macro parameters(#1 #2 etc) % dfa_define_highlight_rule("#[1-9]", "operator", name); % quoted strings dfa_define_highlight_rule("\"`.*\"'", "Qstring", name); % german dfa_define_highlight_rule("``.*''", "Qstring", name); % english % signle quotes dfa_define_highlight_rule("`[^']*'", "string", name); % english % quoted strings accross lines; mark the three charaters after and % before the quote characters dfa_define_highlight_rule("[\"`]`.?.?.?", "string", name); dfa_define_highlight_rule(".?.?.?\"'", "string", name); dfa_define_highlight_rule(".?.?.?''", "string", name); dfa_define_highlight_rule("[ \t]+$", "trailing_whitespace", name); % Workaround to make UTF-8 characters are display correctly, not as % or dfa_define_highlight_rule("\xC2.", "normal", name); dfa_define_highlight_rule("\xC3.", "normal", name); dfa_define_highlight_rule("\xE2..", "normal", name); dfa_define_highlight_rule("\xE3..", "normal", name); dfa_define_highlight_rule("\xE4..", "normal", name); dfa_define_highlight_rule("\xE5..", "normal", name); dfa_define_highlight_rule("\xE6..", "normal", name); dfa_define_highlight_rule("\xE7..", "normal", name); dfa_define_highlight_rule("\xE8..", "normal", name); dfa_define_highlight_rule("\xE9..", "normal", name); % all the rest % Fixme: Why we need this rule? dfa_define_highlight_rule(".", "normal", name); dfa_build_highlight_table(name); } dfa_set_init_callback(&setup_dfa_callback, MODE); #endif %%%%%%%%%% % % Hooks % % Fix me! % we should save the blocal vars on buffer close, but there isn't a hook for % this private define save_buf_before_hook(filename) { % variable buf = latex_external->find_buf_of_file(filename); % if (buf == NULL) % buf = whatbuf(); % setbuf(buf); % push_spot(); % eob(); % variable old_buf_flags; % (,,,old_buf_flags) = getbuf_info(); % setbuf_info( getbuf_info() & ~0x20 ); % % the buf should end with a newline % !if(bolp()) newline(); % % Fix me! % while ( andelse {up(1)} {bol(), looking_at_char('%')} ) { % skip_chars("% "); % if ( looking_at("LaTeX") ) { % bol(); % push_mark(); % eol(); % ()=right(1); % del_region(); % } % } % % ()=down(1); % % !if (eobp()) { eol(); newline(); } % eob(); % variable error_occured=0; % ERROR_BLOCK { % error_occured = 1; % _clear_error(); % } % foreach ( ["LaTeX_master_file", "LaTeX_output_format"] ) { % if (error_occured) % break; % variable name = (); % if ( latex_external->exists_master_file_var(name) ) % insert("% "+name+": "+latex_external->get_master_file_var(name)+"\n"); % } % setbuf_info( getbuf_info() | (old_buf_flags&0x20) ); % pop_spot(); } % Fixme: better define a own format_paragraph private define paragraph_separator() { bol(); skip_white(); return orelse {looking_at_char('\\')} {is_commented()} {eolp()}; } %!%+ %\function{latex_mode} %\synopsis{latex_mode} %\usage{Void latex_mode()} %\description % This mode is designed to facilitate the task of editing LaTeX files. It % calls the function \var{latex_mode_hook} on startup if it is defined. In % addition, if the abbreviation table \var{"TeX"} is defined, that table is % used. % % There are way too many key-bindings for this mode. % Please have a look at the menus! %!%- public define latex_mode() { set_mode(MODE, 0x21); use_keymap(MODE); use_syntax_table(MODE); set_buffer_hook("indent_hook", &indent_hook); set_buffer_hook("newline_indent_hook", &newline_indent_hook); set_buffer_hook("wrap_hook", &wrap_hook); set_buffer_hook("wrapok_hook", &wrapok_hook); append_to_hook("_jed_save_buffer_before_hooks", &save_buf_before_hook); set_buffer_hook("par_sep", ¶graph_separator); WRAP_INDENTS = 1; define_blocal_var("info_page", "latex"); if ( abbrev_table_p("TeX") ) { set_abbrev_mode(1); use_abbrev_table("TeX"); } eob(); !if (bobp()) { % file is not empty % Fix me! % Bad Hack: bol() doesn't take an argument, so 1 is left on stack for % and while ( andelse {up(1) and bol(1)} {looking_at_char('%')} ) { skip_chars("% "); push_mark(); skip_chars("^:\n"); variable name = bufsubstr(); switch (name) { case "LaTeX_master_file" or case "LaTeX_output_format": create_blocal_var(name); skip_chars(": "); push_mark(); eol(); set_blocal_var(bufsubstr(), name); } } bob(); while ( fsearch("\\begin{") ) { () = right(7); if ( is_commented() ) continue; push_mark(); if ( ffind_char('}') ) { variable env = chop_star( bufsubstr() ); if (orelse {env == "document"} {env_lookup(env, NULL) != NULL}) continue; variable args = 0; () = right(1); while ( looking_at_char('{') ) { ++args; fsearch_matching_brace(); () = right(1); } env_register(env, args, "(auto-added on file load, found somewhere in document)", "", NULL); } else pop_mark(0); } bob(); if ( fsearch("\\documentclass") ) while ( re_fsearch("\\[nb]e[wg]"R) ) { () = right(1); if ( is_commented() ) continue; if ( looking_at("begin{document}") ) break; variable is_newcmd = 0, is_newtheorem = 0; if ( looking_at("newcommand") ) { is_newcmd = 1; () = right(10); } else if ( looking_at("newenvironment") ) () = right(14); else if ( looking_at("newtheorem") ) { is_newtheorem = 1; () = right(10); } else continue; if ( looking_at_char('*') ) () = right(1); variable arg_cnt; (,name) = cmd_parse_args(0, 1); name = name[0]; (arg_cnt,) = cmd_parse_args(1, 0); if (orelse {is_newtheorem} {length(arg_cnt) == 0}) arg_cnt = int(0); else { arg_cnt = integer(arg_cnt[0]); if (is_newcmd) { % \newcommand with default args variable tmp; (tmp,) = cmd_parse_args(arg_cnt, 0); arg_cnt -= length(tmp); } } if (is_newcmd) { variable def, is_math = 0; (,def) = cmd_parse_args(0,1); def = def[0]; if ( is_substr(def, "\\math") ) is_math = 1; else if ( string_match(def, "[^\\][_^]"R, 1) >= 1 ) is_math = 1; name = name[[1:]]; % remove the \ if (cmd_lookup(name, NULL) == NULL) cmd_register(name, arg_cnt[0], int(is_math), "(auto-added on file load, found in preample)", "", NULL); } else { % environments and theorems if (env_lookup(name, NULL) == NULL) env_register(name, arg_cnt, "(auto-added on file load, found in preample)", "", NULL); } } bob(); } run_mode_hooks("latex_mode_hook"); } % ----- provide("latex"); runhooks("after_latex_load_hook", MODE); % --- End of file latex.sl