Skip to content

Insérer du texte avec des séquences d'échappement de couleur terminale

Notre équipe spécialisée après plusieurs jours de travail et de collecte d'informations, nous trouvons la solution, nous voulons qu'elle vous soit utile dans votre projet.

Solution :

Voici une approximation de ce que vous demandez.

TeX ne fournit pas de moyen d'entrer des fichiers binaires de manière fiable, mais pour pdfTeX, il y a la fonction pdffiledump primitive pour lire un fichier binaire, échappé comme une séquence de nombres hexadécimaux. Nous devons d'abord prétraiter cette chaîne pour obtenir une séquence de caractères, chacun de code 12 ([email protected]).

Ensuite, nous analysons cette chaîne d'entrée ([email protected]), en construisant la ligne de sortie actuelle dans une liste de jetons. [email protected] (pour des raisons techniques, dans un ordre inversé). En fonction du caractère d'entrée actuel, les éléments de la liste de jetons de sortie sont soit ajoutés, soit supprimés, soit imprimés et une nouvelle liste est commencée.

Chaque fois qu'un caractère d'échappement (x1B) apparaît, le caractère suivant détermine le type de séquence d'échappement. S'il s'agit d'un [, ce qui suit est une série de numéros de paramètres, et un caractère final qui spécifie le type de sortie du terminal. Nous nous branchons ensuite sur ce type et le numéro de paramètre donné pour modifier les variables globales pour les attributs d'affichage actuels ([email protected]@termout). Ces derniers sont pris en compte chaque fois qu'un nouveau caractère est ajouté à la ligne de sortie courante.

Le code complet :

documentclass{article}

usepackage{xcolor}
usepackage{pdftexcmds}
usepackage{mdframed}
usepackage[utf8]{inputenc}
usepackage{textcomp}

makeatletter
endlinechar=-1

% Manipulation of current output line

newif[email protected]@

def[email protected]{}

def[email protected]@push#1{
    [email protected]@
        def[email protected]{}
    fi
    xdef[email protected]{
        {{noexpandstrut
          noexpandcolor{[email protected][email protected]@!75!whitefi}
          unexpanded{#1}}}
        unexpandedexpandafter{[email protected]}
    }
    [email protected]@false
}

def[email protected]@pop{
    xdef[email protected]{expandafterunexpandedexpandafterexpandafterexpandafter
        {expandafter@gobble[email protected]}}
    [email protected]@false
}

def[email protected]@print{
    leavevmode
    expandafter[email protected]@reverseexpandafter@sep[email protected]{}@end
}
def[email protected]@reverse#1@sep#2#3@end{
    [email protected]{#3}{
        #2#1
    }{
        [email protected]@reverse#2#1@sep#3@end
    }
}

% Display attributes

def[email protected]{}
def[email protected]@fgcolor{lightgray}
newif[email protected]@

% Input parsing

newcount[email protected]@a
newcount[email protected]@b

begingroup
count0=0relax
loop
    lccode`*=count0relax
    lowercase{
        expandaftergdefcsname [email protected]@[email protected]numbercount0endcsname{*}
    }
    advancecount0 by 1relax
ifnumcount0<256relax
repeat
endgroup

def[email protected]#1#2{
    [email protected]{#1}{}{
        csname [email protected]@[email protected]number"#1#2endcsname
        [email protected]
    }
}

def[email protected]#1{
    % End of input
    [email protected]@eq#1relax{
        @@par
        [email protected]{}
    }{}
    % Escape sequence
    [email protected]@eq#1[email protected]@char{
        [email protected][email protected]@esc
    }{}
    % Newline
    [email protected]@eq#1[email protected]@char{
        [email protected]@print
        @@par
        [email protected][email protected]
    }{}
    % Carriage return
    [email protected]@eq#1[email protected]@char{
        [email protected]@true
        [email protected][email protected]
    }{}
    [email protected]@eq#1[email protected]@char{
        [email protected]@pop
        [email protected][email protected]
    }{}
    [email protected]@eq#1[email protected]@char{
        [email protected]@push{ }
        [email protected][email protected]
    }{}
    [email protected]@range{`#1}{194}{223}{
        [email protected]{[email protected]@[email protected]#1}
    }{}
    [email protected]@range{`#1}{224}{239}{
        [email protected]{[email protected]@[email protected]#1}
    }{}
    [email protected]@range{`#1}{240}{244}{
        [email protected]{[email protected]@[email protected]#1}
    }{}
    [email protected]{
        [email protected]@push{#1}
        [email protected]
    }
}

def[email protected]@esc#1{
    [email protected]@eq#1[{
        [email protected]@csi
    }{
        GenericWarning{}{Warning: Ignored unknown escape sequence of type `#1'}
        [email protected]
    }
}

def[email protected]@csi#1{
    [email protected]@b=-1relax
    % Is private sequence?
    [email protected]@eq#1?{
        afterassignment[email protected]@[email protected]
        [email protected]@a=0
    }{
        afterassignment[email protected]@[email protected]
        [email protected]@a=0#1
    }
}

def[email protected]@[email protected]#1{
    % Check for second parameter
    [email protected]@eq#1;{
        afterassignment[email protected]@termout
        [email protected]@b=0
    }{
        [email protected]@termout #1
    }
}

def[email protected]@termout#1{
    % SGR parameter
    [email protected]@eq#1m{
        [email protected]@sgr[email protected]@a
        ifnum[email protected]@b<0else
            [email protected]@sgr[email protected]@b
        fi
        [email protected]{}
    }{}
    [email protected]{
%        GenericWarning{}{Warning: Ignored unknown terminal output sequence of type `#1'}
    }
    [email protected]
}

def[email protected]@sgr#1{
    % Reset
    [email protected]@eq{#1}{0}{
        let[email protected]=[email protected]@fgcolor
        [email protected]@false
        [email protected]{}
    }{}

    % Bold/intense
    [email protected]@eq{#1}{1}{
        [email protected]@true
        [email protected]{}
    }{}

    % Standard colors
    [email protected]@eq{#1}{30}{
        def[email protected]{black}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{31}{
        def[email protected]{red}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{32}{
        def[email protected]{green}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{33}{
        def[email protected]{yellow}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{34}{
        def[email protected]{blue}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{35}{
        def[email protected]{magenta}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{36}{
        def[email protected]{cyan}
        [email protected]{}
    }{}
    [email protected]@eq{#1}{37}{
        def[email protected]{white}
        [email protected]{}
    }{}
    [email protected]{}
}

% n-byte Unicode sequences

def[email protected]@[email protected]#1#2{
    scantokens{csname [email protected]@pushendcsname{#1#2}}
    [email protected]
}

def[email protected]@[email protected]#1#2#3{
    scantokens{csname [email protected]@pushendcsname{#1#2#3}}
    [email protected]
}

def[email protected]@[email protected]#1#2#3#4{
    scantokens{csname [email protected]@pushendcsname{#1#2#3#4}}
    [email protected]
}

% Helper macros

def[email protected]#1{
    ifrelaxdetokenize{#1}relax
        expandafter@firstoftwo
    else
        expandafter@secondoftwo
    fi
}

def[email protected]@eq#1#2{
    if#1#2%
        expandafter@firstoftwo
    else
        expandafter@secondoftwo
    fi
}

def[email protected]@eq#1#2{
    ifnum#1=#2 %
        expandafter@firstoftwo
    else
        expandafter@secondoftwo
    fi
}

def[email protected]@range#1#2#3{
    ifnum#1<#2 %
        expandafter@firstoftwo
    else
        expandafter@secondoftwo
    fi
    {
        @secondoftwo
    }{
        ifnum#1>#3 %
            expandafter@secondoftwo
        else
            expandafter@firstoftwo
        fi
    }
}

def[email protected]#1#2[email protected]#3{#1}
def[email protected]#1{#1}

def@temp#1#2{
    begingroup
    lccode`*=`#2
    lowercase{globallet#1=*}
    endgroup
}
@temp[email protected]@char ^^H
@temp[email protected]@char        ^^J
@temp[email protected]@char        ^^M
@temp[email protected]@char    ^^[
@temp[email protected]@char      %

% User macros

% Print terminal session stored in #1
newcommandterminalinput[1]{
    begin{mdframed}[
        backgroundcolor=black,
        innerleftmargin=0pt,
        innerrightmargin=0pt,
        innertopmargin=0pt,
        innerbottommargin=0pt
    ]
    begingroup
    parindent=0pt
    frenchspacing
    ttfamily
    fboxsep=0pt
    [email protected]@sgr{0}

    xdef@temp{[email protected]{0}{[email protected]{#1}}{#1}}
    expandafterxdefexpandafter[email protected]expandafter{
        expandafter[email protected]@temp{}{}
    }
    expandafter[email protected][email protected]relax
    endgroup
    end{mdframed}
}

endlinechar=`^^M
makeatother

DeclareUnicodeCharacter{279C}{textrightarrow}

begin{document}
terminalinput{typescript.bin}
end{document}

sort

enter image description here

Il y a encore plusieurs problèmes avec l'implémentation actuelle :

  • Le code ne fonctionne qu'avec le pdflatex ou lualatex car il s'appuie sur le compilateur pdffiledump ou sa réimplémentation en code Lua, respectivement.
  • Actuellement, aucun caractère Unicode n'est pris en charge, car le fichier est décodé comme un flux à un seul octet. Les caractères en dehors de la plage ASCII imprimable sont ignorés pour le moment.
    EDIT: Les caractères Unicode sont supportés maintenant. Chaque fois qu'une séquence UTF-8 2/3/4 octets est rencontrée, les octets sont re-mappés vers leurs catcodes standards via. scantokens de telle sorte que inputenc puisse faire son travail normalement. De nouveaux mappages de caractères peuvent être ajoutés via DeclareUnicodeCharacter.
  • La "fenêtre du terminal" est actuellement juste une boîte noire s'étendant sur toute la largeur du texte.
  • L'implémentation actuelle ne couvre qu'un petit sous-ensemble de toutes les séquences d'échappement/séquences de sortie du terminal disponibles. Plus particulièrement, les couleurs d'arrière-plan ne sont pas gérées du tout, il n'y a qu'une gestion tiède des couleurs grasses/intense (en ajoutant !75!white à la couleur actuelle), seules les huit couleurs standard (codes 30-37) sont implémentées, etc.
  • Le positionnement du curseur n'est pas non plus géré correctement, par exemple le retour chariot (x0D) efface la ligne complète au lieu de déplacer seulement le curseur au début de la ligne.
  • Dans les séquences de sortie de terminal, seuls un ou deux numéros de paramètres sont supportés, alors que n'importe quel nombre ou paramètres devrait être supporté.
  • Le code n'a pas été bien testé, en fait seulement avec le fichier d'exemple donné 😉

Comme ceci, par exemple.

documentclass{article}
usepackage{fancyvrb}
usepackage{color}

defdefaultcode{[0}
defbluecode{[1;34}
defredcode{[1;31}
makeatletter
defe#1m{%                                                                                                                                                                   
defcolcode{#1}%                                                                                                                                                             
ifxcolcodedefaultcodecolor{black}%
elseifxcolcodebluecodecolor{blue}%
elseifxcolcoderedcodecolor{red}%
fififi}
makeatother

begin{document}
begin{Verbatim}[commandchars=\{}]
echo -e 'e[1;34mBLUE TEXTe[0m'
echo -e 'e[1;31mRED TEXTe[0m'
echo -e 'DEFAULT COLOURED TEXT'
end{Verbatim}
end{document}

enter image description here

L'idée est que les codes de contrôle commencent par e et se terminent par m. Par conséquent, nous prenons tout ce qui se trouve entre les deux, puis nous le comparons à certains codes prédéfinis. Il est facile d'ajouter des codes supplémentaires, par exemple le vert serait pris en charge par...

defgreencode{[1;32}

et ensuite

elseifxcolcodegreencodecolor{green}

avec un autre fi à la fin. Après cela, vous avez juste besoin d'un environnement verbatim qui autorise les macros. Ici, j'ai utilisé le paquet fancyvrb. Notez que vous aurez besoin de changer la couleur en

ifxcolcodedefaultcodecolor{black}

si votre couleur par défaut n'est pas le noir.

Commentaires et notes

N'oubliez pas que vous avez la possibilité de dire si vous appuyez sur la trouvaille.



Utilisez notre moteur de recherche

Ricerca
Generic filters

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.