% Release 0.2 (2021-05-05) of xintsession.tex % author: Jean-Francois Burnol % License: LPPL 1.3c (author-maintained) % Usage: execute etex or pdftex % then enter "xintsession" at the ** prompt \input xintexpr.sty\relax% % AJOUTER CHECK DE VERSION ICI \input xintbinhex.sty\relax% \input polexpr.sty\relax% attention will crash if < 0.8 \let\PolToExprOneTerm\PolToExprOneTermStyleB% %\let\PolToExprTimes\empty% % we do assume standard catcodes on loading and use % \XINTrestorecatcodes as a convenience facility. % It stores \endlinechar but not \newlinechar % and was renamed at 1.4e \edef\xsrestorecatcodes{\XINTrestorecatcodes% \newlinechar\the\newlinechar\relax}% \endlinechar 13 % \newlinechar 10 \catcode`_ 11 \catcode`& 11 \catcode`@ 11 \catcode`^ 11 \catcode`" 7 \catcode0 12 \newwrite\xs_out \edef\xs_name{\jobname-\expandafter\xint_gobble_ii\the\year \expandafter\xint_gobble_i\the\numexpr100+\month\relax \expandafter\xint_gobble_i\the\numexpr100+\day\relax _% \expandafter\xint_gobble_i\the\numexpr(\time+30)/60+99h% \expandafter\xint_gobble_i\the\numexpr100+\time-60*((\time+30)/60-1).tex}% \immediate\openout\xs_out=\xs_name\relax \begingroup\catcode37 12 \long\gdef\xs_message#1{\message{#1}\immediate\write\xs_out{%#1}}\endgroup {\catcode13\active\def {""J}\catcode32\active\edef {\string }% \catcode`?=0\catcode`\\=12\relax% ?xdef?xs_logo{% _____ _____ ____ ____(_)________ /_________ _________________ __ |/_/_ /__ __ \ __/ _ \_ |/_/__ __ \_ ___/ __> < _ / _ / / / /_ / __/_> < __ /_/ / / /_/|_| /_/ /_/ /_/\__/ \___//_/|_| _ .___//_/ /_/ _____ _____ __________ ___(_)________ /__________________ ________ /___(_)__ ______ __ /__ __ \ __/ _ \_ ___/ __ `/ ___/ __/_ /__ | / / _ \ _ / _ / / / /_ / __/ / / /_/ // /__ / /_ _ / __ |/ // __/ /_/ /_/ /_/\__/ \___//_/ \__,_/ \___/ \__/ /_/ _____/ \___/ }% ?immediate?write128{% xintsession 0.2 Copyright (c) Jean-Francois Burnol, 2021. \jobname is ?jobname Transcript will go to log and to ?xs_name ===> HIT THE KEY NOW! <===% }}% \def\xs_no{0}% \XINT_expr_defvar_one{@___}{{0}}% \XINT_expr_defvar_one{@__}{{0}}% \XINT_expr_defvar_one{@_}{{0}}% \def\xs_fetch{\let\xs_in\empty\xs_fetch_a}% \begingroup \catcode13\active% \long\gdef\xs_fetch_a#1 {% \odef\xs_firstitem{\romannumeral0\xintfirstitem{#1.}}% \ifcat\relax\expandafter\noexpand\xs_firstitem% \expandafter\xs_cs% \else% \if &\expandafter\noexpand\xs_firstitem% \expandafter\expandafter\expandafter\xs_magic% \fi% \fi% \if;\expandafter\noexpand\romannumeral0\xintlastitem{#1}% \xs_fetch_b#1^% \else% \message{(Use ; to end multi-line input)}% \odef\xs_in{\xs_in#1}\expandafter\xs_fetch_a% \fi% }% \endgroup \long\def\xs_cs\if;\expandafter\noexpand\romannumeral0\xintlastitem#1#2\fi {% \xs_message{(executing \detokenize{#1} in background)}% #1\xs_fetch_a }% \def\xs_firstfour#1#2#3#4#5\xint_bye{\edef\xs_magic_in{#1#2#3#4}\def\xs_magic_inb{#5}}% \long\def\xs_magic\if;\expandafter\noexpand\romannumeral0\xintlastitem#1#2\fi {% \xs_firstfour#1\empty\empty\empty\empty\xint_bye \ifcsname xs_magic@\xs_magic_in\endcsname \csname xs_magic@\xs_magic_in\expandafter\endcsname \else \xs_message{(\detokenize\expandafter{\xint_gobble_i#1} is not a magic keyword: ignored)}% \fi\xs_fetch_a }% \long\def\xs_fetch_b#1;^% {% \odef\xs_in{\xs_in#1}\expandafter\xs_fetch_c }% \def\xs_fetch_c {% \if\relax\romannumeral`""@\detokenize\expandafter{\xs_in}\relax\expandafter\xs_pause\fi \expandafter\xs_parse_a\xs_in:=^% }% \def\xs_pause\expandafter\xs_parse_a\xs_in:=^{\xs_pause_a\xs_fetch_a}% \def\xs_pause_a\xs_fetch_a {% \xs_message{Need a break? OK, use \string\xintresume\space if you change your mind.}% \xs_resetcats }% \def\xs_bye\xs_fetch_a {% \xs_message{Did I say something wrong?}% \xs_message{Session transcript written on \xs_name}% % \xs_resetcats \immediate\closeout\xs_out % expeditive exit because I need to think about generating new output % filename with a check that it is not same (a minute may be too coarse?). % Add random postfix? or simply do not bother rather... \csname bye\endcsname }% \def\xs_parse_a#1:=#2% {% \xint_gob_til_^#2\xs_calc ^% \def\xs_left{#1}\xs_parse_b#2% }% \def\xs_calc ^#1^% {% \edef\xs_no{\the\numexpr1+\xs_no}% \xs_xintdefvar @_\xs_no=\xs_in;% \immediate\write\xs_out {\expandafter\string\xs_xintdefvar\space @_\xs_no:=% \detokenize\expandafter{\xs_in};}% \XINT_expr_defvar_one{@___}{\csname XINT_expr_varvalue_@__\endcsname}% \XINT_expr_defvar_one{@__}{\csname XINT_expr_varvalue_@_\endcsname}% \XINT_expr_defvar_one{@_}{\csname XINT_expr_varvalue_@_\xs_no\endcsname}% \xs_message{(@_\xs_no)\space\space\space\space\xs_xinteval{@_\xs_no}}% \xs_fetch }% \def\xs_parse_b #1:=^% {% \def\xs_right{#1}\expandafter\xs_parse_c\xs_left(;% }% \def\xs_parse_c #1(#2% {% \edef\xs_funcname{\expandafter\xint_zapspaces\detokenize{#1} \xint_gobble_i}% \xint_gob_til_sc#2\xs_defvar;\xs_deffunc }% \def\xs_deffunc #1;% {% % attention: \xs_xintdeffunc needs to see parentheses immediately \expandafter\xs_xintdeffunc\xs_left=\xs_right;% \immediate\write\xs_out {\expandafter\string\xs_xintdeffunc\space\detokenize\expandafter{\xs_left}:=% \detokenize\expandafter{\xs_right};}% \expandafter\ifx\xs_xintdeffunc\poldef \xs_message{\xs_funcname\space = \PolToExpr{\xs_funcname}}% \xs_message{Issue \string\PolGenFloatVariant{\xs_funcname} if fp evaluations with \xs_funcname\space are intended}% \else\xs_message{Function \xs_funcname\space defined}% \fi\xs_fetch }% \def\xs_defvar;\xs_deffunc {% \edef\xs_no{\the\numexpr1+\xs_no}% \xs_xintdefvar @_\xs_no=\xs_right;% \immediate\write\xs_out {\expandafter\string\xs_xintdefvar\space\detokenize\expandafter{\xs_left}:=% \detokenize\expandafter{\xs_right};}% \XINT_expr_defvar_one{@___}{\csname XINT_expr_varvalue_@__\endcsname}% \XINT_expr_defvar_one{@__}{\csname XINT_expr_varvalue_@_\endcsname}% \XINT_expr_defvar_one{@_}{\csname XINT_expr_varvalue_@_\xs_no\endcsname}% % this is to allow multiple assignments \expandafter\xs_xintdefvar\xs_left=@_\xs_no;% \xs_message{(@_\xs_no)\space\space\space\space\xs_xinteval{@_\xs_no}}% \xs_fetch }% \let\xs_magic@&pau\xs_pause_a \let\xs_magic@&bye\xs_bye \def\xs_magic@&fp {% \xs_message{fp mode (\xinttheDigits\space digits)}% \def\xs_mode{fp (Digits=\xinttheDigits)}% \def\xs_xintdefvar{\xintdeffloatvar}% \def\xs_xintdeffunc{\xintdeffloatfunc}% \def\xs_xinteval{\xintfloateval}% }% \expandafter\def\csname xs_magic@&fp=\endcsname {% \xintDigits*:=\xs_magic_inb\relax \xs_message{fp mode (log and trig reloaded at Digits=\xinttheDigits)}% \def\xs_mode{fp=\xinttheDigits}% \def\xs_xintdefvar{\xintdeffloatvar}% \def\xs_xintdeffunc{\xintdeffloatfunc}% \def\xs_xinteval{\xintfloateval}% }% \def\xs_magic@&exa {% \xs_message{exact mode (floating point evaluations use \xinttheDigits\space digits)}% \def\xs_mode{exact}% \def\xs_xintdefvar{\xintdefvar}% \def\xs_xintdeffunc{\xintdeffunc}% \def\xs_xinteval{\xinteval}% }% \def\xs_magic@&int {% \xs_message{int mode (integer only: / rounds, // is floored division, /: is modulo)}% \def\xs_mode{int}% \def\xs_xintdefvar{\xintdefiivar}% \def\xs_xintdeffunc{\xintdefiifunc}% \def\xs_xinteval{\xintiieval}% }% \def\xs_magic@&pol {% \xs_message{pol mode (i.e. function definitions use \string\poldef)}% \def\xs_mode{pol}% \def\xs_xintdefvar{\xintdefvar}% \def\xs_xintdeffunc{\poldef}% \def\xs_xinteval{\xinteval}% }% \def\xs_magic@&mod{\xs_message{current mode: \xs_mode}}% \def\xs_setcats {% \newlinechar10\endlinechar13% \catcode13\active\catcode`@ 11\relax }% \def\xs_storecats{\edef\xs_resetcats {% \newlinechar\the\newlinechar \endlinechar\the\endlinechar \catcode13=\the\catcode13 \catcode`@\the\catcode`@\relax }}% \begingroup \catcode13\active\catcode32\active% \gdef\xintstart{\edef {\string }\xs_setcats\def {""J}\message{\xs_logo Welcome to xintexpr interactive mode! - input is `;'-terminated and can extend over multiple lines, - definitions must be done using the `:=' syntax, not `='. Any line starting with a control sequence is executed in the background, the interrupted numerical input resumes at prompt. Magic words: `&pause' (or `;'), `&help', `&bye'. Mode toggles: `&exact', `&fp', `&int', `&pol'. Say for example `&fp=24' at the prompt to work with Digits=24 (Digits range: 1 to 62) Starting in}\xs_magic@&exa\let =\xs_fetch}\gdef\xintresume{\edef {\string }\xs_storecats\xs_setcats% \message{Welcome back to xintexpr interactive mode!}\let =\xs_fetch}\catcode`?0\catcode`\\12?gdef?xs_help?xs_fetch_a{?def {""J}?edef {?string }?message{% - Terminate inputs using the `;' character. - Input can extend over multiple lines ( terminated). - An empty input (`;' terminated) or the magic word `&pause' puts the session on hold and switches to normal TeX interaction. Use \xintresume to resume the session. - The numerical engine can work in various modes: * exact mode means using \xintexpr context, * fp mode uses \xintfloatexpr, * int mode uses integer-only \xintiiexpr, * pol mode makes function definitions using \poldef. To activate a mode enter `&' at the prompt - Lines starting with any control sequence are handed over to TeX, and numerical input resumes on next line. - Say `&fp=' for example `&fp=32' at the prompt to change the Digits setting. This can be done in the midst of the input of a multi-line computation! (1/5) HIT KEY }?let =?xs_help_b}?gdef?xs_help_b{?def {""J}?message{% - Say `&exact' resp. `&fp' to go back and forth between exact and floating point mode - Issue `&mode' if you forgot in what mode you are currently in. - Definitions (variables or functions) are done using `:='. IMPORTANT: currently, using a `=' by oversight will cause breakage because xintsession thinks it is then a numerical evaluation, not a definition, but there is no `=' operator in xintexpr syntax. Perhaps in future it will be allowed to make definitions using `=' and xintsession will check if it is not misinterpreting a `=' from `<=', `>=', `!=', `==' or `seq()' syntax but this currently was considered to add too much overhead for the benefit. - Parentheses present before the `:=' trigger a function definition, else a variable definition is done. - Functions defined in one mode are not available for usage in other modes without further steps; check xintexpr doc. (2/5) HIT KEY }?let =?xs_help_c}?gdef?xs_help_c{?def {""J}?message{% - Polynomial definitions (pol mode) are function definitions (see polexpr documentation). To use a polynomial also as a numerical function when back in fp mode, issue \PolGenFloatVariant{} at the prompt. - Variables defined in any mode can be used in any mode except: * polynomials can be used as variables only in the pol and the exact modes, * integer-only mode requires... integer-only variables, also internally. Use in int mode num() or \xintiexpr...\relax as wrapper around exact or fp variables, even integer-valued ones. - Whenever a variable is defined, or a computation is performed, the result is assigned a label @_. These automatic variables can then be used in subsequent computations. - In the case of a multi-variable assignment (see xintexpr doc) the automatic variable @_ holds the whole thing, which may be a nutple or an ople, in addition to individual variables. - The special variables @_, @__, and @___ hold the last, next to last and next to next to last evaluation results. (3/5) HIT KEY }?let =?xs_help_d}?gdef?xs_help_d{?def {""J}?message{% Known issues: - The [P] optional argument of \xintfloateval can not be used because it is not recognized by \xintdeffloatvar, one can use the float() function with its second argument. - An \xintexpr...\relax wrapper inside fp mode or an \xintiexpr...\relax one inside int mode can not start a line, as it would trigger control sequence execution. Start with 0+ or use parentheses. - The definitive default output format of the exact and fp modes are not yet decided at upstream xintexpr: - trailing zeros are not trimmed, - exact and fp modes print out floating point numbers in diverging ways, - exact mode does not reduce to lowest terms, use reduce(). - By default, the ** and ^ operators operate _only_ with integer exponents in exact mode and with half-integers in fp mode. Fractional powers are available via the pow(x,a) function. (4/5) HIT KEY }?let =?xs_help_e}?gdef?xs_help_e{?def {""J}?message{% Known issues (cont.): - Refer to xintexpr \poormanloghack documentation on how to let fractional powers be available with ** or ^, and check polexpr documentation for related information. - A session transcript file is created which can be executed by eTeX to redo all calculations; however @_, @__, and @___ will not be defined in this context so need to be manually replaced by the suitable @_. Future: - a plot() function will be added at some point to export coordinates into a .tex file for usage either with PSTricks or TikZ/pgf. Miscellany: Misformed xintexpr input can drop you into TeX error mode. In that case, try escaping using `S'. It does work sometimes. (5/5) You are back to the xintexpr interactive session! (mode: ?xs_mode) Use `&bye' to terminate the session and the TeX run. }?let =?xs_fetch?xs_fetch_a}?endgroup \let\xs_magic@&hel\xs_help \xsrestorecatcodes \csname xs_storecats\endcsname \catcode13\active\def {\xintstart }\endinput%