1

I'm looking for a shortcut generator that is not as picky as \newcommand -something like \input but from within a file. I.e., i would like to Have a normal .tex file, in which i at some point can write something like \this[20c]{\that} and the next 20 characters are used whenever i write \thatin my document, just as if those 20 characters were written at that point in the document.

  • tex is a macro expansion system and you are asking for a macro so \newcommand should be the answer. If you showed an example where you were getting an error then someone could help. Alternatively just save the text fragment in your editor and paste it in when required (many editors make it easy to save such fragments) – David Carlisle Apr 24 at 12:15
  • note you should never need \makeatletter in a document. any command with @ in its name is intentionally named that way to avoid it being used in a document. – David Carlisle Apr 24 at 12:17
  • @DavidCarlisle i'll open a question about my current problem, just for kicks, but i'll probably just use \input for the whole thing.... – bukwyrm Apr 24 at 12:35
  • @DavidCarlisle Question now online at tex.stackexchange.com/questions/540428/… – bukwyrm Apr 24 at 12:59
  • 2
    questions with no example code and referencing packages that don't exist are not really answerable. – David Carlisle Apr 24 at 14:20
0

When TeX processes a .tex-input-file, it reads this file and takes it as a set of instructions for producing so-called tokens and inserting them, one by one, into the token-stream. Tokens can be control-sequence-tokens or character-tokens.

I recently elaborated on the different stages of processing .tex-input in my answer to the question Make command output be the (multiple) arguments of another one.

You can have LaTeX read and tokenize the next few lines or the next few characters of .tex-input under verbatim-catcode-régime before passing the resulting set of character-tokens to \scantokens. Under verbatim-catcode-régime every character of the .tex-input-file is tokenized as a character-token. \scantokens essentially works as if the tokens that form its argument were written unexpanded to a text-file whereafter reading and tokenizing the content of that text-file is initiated via \input. If the argument of \scantokens consists of character-tokens only, writing them unexpanded (be that done really or be that emulated by \scantokens' writing-part) yields the same set of characters as can be found in the corresponding place of the .tex-input-file. Thus the \input-part of \scantokens will find the same characters as can be found in the corresponding place of the .tex-input-file. But the result of reading and tokenizing that set of characters when \scantokens does its \input-part depends on the catcode-régime in effect at the time when \scantokens does its \input-part.

I suppose for line-wise-processing you wish a macro which does

  • read the next few lines from the .tex-input-file under verbatim-catcode-régime,
  • insert newline-characters behind the tokens from each line but the last one
  • and define a macro from the result where everything is passed to \scantokens.

I suppose for character-wise-processing you wish a macro which does

  • read the next few characters from the .tex-input-file under verbatim-catcode-régime,
  • append a comment-character in order to ensure the last endline-character inserted by \scantokens has no effect,
  • and define a macro from the result where everything is passed to \scantokens.

Here is a small example of how such macros can be implemented:

\documentclass{article}
\begingroup
% Make @ a letter which can occur in names of control sequences:
\makeatletter
% Make return, which usually is TeX's endline-character, an ordinary character:
\catcode`\^^M=12 %
% Let's use as comment-character ^^A instead of %:
\catcode`\^^A=14 %
% Make % an ordinary character:
\catcode`\%=12 ^^A
\@firstofone{^^A
  \endgroup^^A
  \newcommand{\makenextlines}[2]{^^A
   \begingroup^^A
   \let\do\@makeother\dospecials^^A
   \catcode`\^^I=12 ^^A
   \catcode`\^^M=12 ^^A
   \romannumeral0^^A
   \expandafter\innermakenextlines\expandafter{\romannumeral\number\number#1 000}{#2}{}^^A
  }^^A
  \long\def\innermakenextlines#1#2#3#4^^M{^^A
    ^^A \innermakenextlines just checks whether there are more lines to collect.
    ^^A If not, defimes command to define to deliver the lines collected so far nested in
    ^^A a call to \scantokens.
    ^^A If so calls \innerinnermakenextlines for collecting the next line of .tex-input
    ^^A and then calling \innermakenextlines again.
    ^^A #1 = Characters m in an amount that equals the amount of lines still to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Lines collected so far.
    ^^A #4 = In the first iteration:   Remaining characters of the line which contains the call to \makenextlines.
    ^^A                                These will silently be discarded. (One could implement triggering an error-message
    ^^A                                depending on the non-emptiness of #4.)
    ^^A      In subsequent iterations: Empty as TeX's endline-character ^^M  is provided explicitly as argument-delimiter
    ^^A                                right  behind the third argument.
    \ifx X#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    { \endgroup^^A
      \newcommand#2{\scantokens{#3}}^^A
    }{^^A
      \innerinnermakenextlines{#1}{#2}{#3}^^A
    }^^A
  }^^A
  \long\def\innerinnermakenextlines#1#2#3#4^^M{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Lines collected so far.
    ^^A #4 = Collected next line.
    \expandafter\ifx\expandafter X\@firstoftwo{}#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    {^^A There is only one m left, thus the last line is to be collected. With the last line no
     ^^A newline-character will be attached.
      \expandafter\innermakenextlines\expandafter{\@firstoftwo{}#1}{#2}{#3#4}{}^^M^^A
    }{^^A Not yet the last line, so attach a newline-character ^^J. When \scantokens, which emulates
      ^^A unexpanded writing to file and inputtong that file, does its unexpanded-writing-part, the
      ^^A newline-character will not br written verbatim but will cause TeX to begin writing another line.
      \expandafter\innermakenextlines\expandafter{\@firstoftwo{}#1}{#2}{#3#4^^J}{}^^M^^A
    }^^A
  }^^A
  ^^A-----------------------------------------------------------------------------------------------------------
  ^^A-----------------------------------------------------------------------------------------------------------
  ^^A-----------------------------------------------------------------------------------------------------------
  \newcommand{\makenextcharacters}[2]{^^A
   \begingroup^^A
   \let\do\@makeother\dospecials^^A
   \catcode`\^^I=12 ^^A
   \catcode`\^^M=12 ^^A
   \romannumeral0^^A
   \expandafter\innermakenextcharacters\expandafter{\romannumeral\number\number#1 000}{#2}{}^^A
  }^^A
  \long\def\innermakenextcharacters#1#2#3{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Characters collected so far.
    \ifx X#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    { \endgroup^^A
      ^^A Let's append a percent to make sure the endline-character apppended to what
      ^^A can be taken for the last line when \scantokens does its \input-part 
      ^^A will have no effect as under normal catcode-régime that percent will be taken
      ^^A for a comment whereafter characters and thus also the appended endline-character
      ^^A are dropped instead of being tokenized.
      \newcommand#2{\scantokens{#3%}}^^A
    }{^^A
      \innerinnermakenextcharacters{#1}{#2}{#3}^^A
    }^^A
  }^^A
  \long\def\innerinnermakenextcharacters#1#2#3#4{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Characters collected so far.
    ^^A #4 = Collected next character.
    ^^A Be aware that endline-characters need to be replaced by newline-characters
    ^^A so that they yield line-break when \scantokens does its writing-part-
    \ifx#4^^M\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    {^^A
      \expandafter\innermakenextcharacters\expandafter{\@firstoftwo{}#1}{#2}{#3^^J}^^A
    }{^^A
      \expandafter\innermakenextcharacters\expandafter{\@firstoftwo{}#1}{#2}{#3#4}^^A
    }^^A
  }^^A
}%

\begin{document}

\makenextlines{10}{\thiscommand}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\show\thiscommand

\makenextcharacters{17}{\thatcommand}12345678901234567\show\thatcommand

% A linebreak is counted like one character:

\makenextcharacters{17}{\onemorecommand}1234
567890123456\show\onemorecommand

\end{document}

The console-output is:

> \thiscommand=\long macro:
->\scantokens {\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}}.
l.113 \show\thiscommand

? 
> \thatcommand=\long macro:
->\scantokens {12345678901234567%}.
l.115 ...ommand}12345678901234567\show\thatcommand

? 
> \onemorecommand=\long macro:
->\scantokens {1234
567890123456%}.
l.120 567890123456\show\onemorecommand

? 
[...]
No pages of output.
| improve this answer | |
  • ... i ... guess that is what i asked for. Wow. The source of the filecontents environment looks kinda similar (to my overloaded mind), so i guess one could do a filecontents-input combination to arrive at a similar result. – bukwyrm Apr 30 at 9:33
  • @bukwyrm Yes. By the way: The filecontents/filecontents*-environments tokenize horizontal-tab-characters as space-tokens (character code 32 and category code 10(space)) because the horizontal-tab-character has catcode 10(space) and every input-character of catcode 10 gets tokenized as space-token. Writing a space-token to external file in turn yields writing a space-character. Thus a side-effect of these environments is that horizontal-tabs will be turned into spaces. As you changed your request from reading line by line to reading character by character I edited my answer accordingly. ;-) – Ulrich Diez Apr 30 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.