Emendar (alterar) comandos existentes

No caso geral (enfiar alguma coisa no meio de um comando existente), isso é difícil. No entanto, a necessidade usual de adicionar algum código no início ou no final de um comando existente é conceitualmente bastante fácil. Suponha que se queira definir uma versão de um comando que faça uma pequena extensão de sua definição original: naturalmente, escreveríamos:

\renewcommand{\splat}{\mumble\splat}
No entanto, isso não funcionaria: uma solicitação de \splat executaria \mumble e, em seguida, solicitaria novamente o \splat ; seria uma ‘repetição sem fim’ que, rapidamente, esgotaria a memória do TeX.

Felizmente, o comando primitivo \let do TeX vem em nosso socorro; ele nos permite tirar um “retrato” do estado atual de um comando, o qual pode ser usado na redefinição do comando. Então:

\let\OldSmooth\smooth
\renewcommand{\smooth}{\mumble\OldSmooth}
faz a alteração necessária de forma segura. Adicionar coisas no final de um comando funciona de forma semelhante.

Se \smooth aceitar argumentos, é preciso passá-los adiante:

\let\OldSmooth\smooth
\renewcommand{\smooth}[2]{\mumble\OldSmooth{#1}{#2}}

A situação é ainda mais difícil se \smooth puder receber um argumento opcional; a estrutura do comando é tão complexa que o simples comando \let não vai reter os detalhes necessários. Neste caso, precisaremos do pacote letltxmacro, que conhece todos os tipos de comando do LaTeX e sabe como replicá-los. Suponha que tenhamos um comando definido como:

\newcommand{\rough}[1][\default]{...}
com um argumento opcional (substituído por \default , se não estiver presente) e um argumento comum. Neste caso, nós o copiamos usando
\LetLtxMacro{\NewRough}{\rough}
e, depois, repetimos a técnica que tínhamos acima, com uma extensão:
\renewcommand{\rough}[1][\newdef]%
             {\mumble\OldRough[{#1}]{#2}}
Aqui, vemos que (por razões entediantes de fazer corresponderem os argumentos) é necessário que o argumento opcional que está sendo passado seja colocado entre chaves.

O caso geral pode ser alcançado de duas maneiras. Primeiro, pode-se usar o comando \CheckCommand do LaTeX , que compara um comando existente com a definição que você atribuiu a ele e emite um aviso se os dois não corresponderem. Portanto, a utilização é:

\CheckCommand{\complex}{definição original}
\renewcommand{\complex}{nova definição}
Esta técnica é obviamente um pouco trabalhosa, mas se o comando original vier de uma fonte que possa ser alterada sob o controle de outra pessoa, ela pelo menos te avisa que o seu “patch” corre o risco de dar errado.

Alternativamente, os usuários do LaTeX podem usar um dos seguintes pacotes: patchcmd, ted ou etoolbox.

O pacote patchcmd lida com uma tarefa um pouco mais simples, restringindo o conjunto de comandos que você pode emendar; você não pode alterar nenhum comando que tenha um argumento opcional, embora ele lide com o caso de comandos definidos com \DeclareRobustCommand. O pacote define um comando \patchcommand que recebe três argumentos: o comando a ser alterado, coisas que vão entrar na frente de sua definição, e coisas para ficar no final de sua definição. Então, depois de

\def\b{b}
\patchcmd\b{a}{c}
nós teremos uma nova versão de \b definida como “abc”.

O pacote ted é um ‘editor de lista simbólico’ e fornece um comando \substitute que emenda o conteúdo de uma macro e coloca o resultado em uma lista de token, ou (na forma \Substitute*) usa o resultado para (re)definir uma macro. O exemplo a seguir define uma macro simples e, em seguida, altera sua definição:

\newcommand{\myfont}%
    {\Large\sffamily\selectfont}
\Substitute*[\renewcommand{\myfont}]{\myfont}%
    {\Large\sffamily}{\huge\itshape}
Agora, a definição da macro é:
\huge\itshape\selectfont

O pacote também oferece um comando \ShowTokens, que mostra o conteúdo de seu argumento, um token por linha, com detalhes do código da categoria do token etc. Ele é recomendado como ferramenta de depuração.

O pacote etoolbox (que dá ao usuário acesso aos recursos de programação do e-TeX) fornece um comando \patchcmd que é muito parecido com o \Substitute, exceto pelo fato de que ele substitui uma única instância do(s) token(s) em seu padrão de pesquisa. Como nem todos os comandos podem ser emendados dessa maneira, o \patchcmd recebe argumentos extras para casos de sucesso e fracasso. O pacote também fornece comandos que incluem algo no início (\pretocmd) ou no final (\apptocmd) da definição de um comando. Nem todos os comandos podem ser emendados dessa maneira; o pacote fornece um comando \ifpatchable que verifica os pré-requisitos e verifica se o corpo do comando de destino realmente inclui o ‘patch’ que você deseja usar. (O comando \ifpatchable* não faz a verificação do ‘patch’.)

O pacote regexpatch trata de casos que são inacessíveis com o etoolbox; ele usa o pacote de expressão regular (pattern-matching) l3regex da distribuição LaTeX3 para encontrar o código que você precisa alterar. O pacote também “sabe” dos comandos robustos e do biblatex.

Finalmente, vamos falar brevemente sobre um pacote que é (praticamente) utilizável, mas não é muito recomendável. O Patch lhe dá um mecanismo engenhoso (e difícil de entender); ele vem como um arquivo de macro documentada à moda antiga do LaTeX, que não pode mais ser processado para produzir documentação formatada etc.. Felizmente, o arquivo (patch.doc) pode ser inserido diretamente, e a “documentação" pode ser encontrada fazendo a leitura da origem do pacote. Grosso modo, dá-se ao comando um conjunto de instruções análogas a substituições sed e regenera o comando assim emendado. A menos que você não possa fazer seu trabalho de outra maneira, o patch deve ser evitado.

etoolbox.sty
etoolbox
l3regex.sty
Distributed as part of l3experimental
letltxmacro.sty
Distributed as part of oberdiek
patch.doc
patch
patchcommand.sty
patchcmd
regexpatch.sty
regexpatch
ted.sty
ted

This answer last edited: 2012-12-21


Do you have any question? Ask on: latex.net.br - we love qood questions!