Suponha que eu gostaria de censurar um palavrão <word> usando grawlixes , por exemplo “O que diabos você está fazendo ?!” Como posso definir um comando \censor de forma que \censor{<word>} resulte em uma sequência desses símbolos? Não estou totalmente certo de quais ou quantos símbolos devem ser usados com a palavra <word>. Suponho que o número de símbolos usados deve ser aproximadamente igual ao número de caracteres em <word>.

Obrigado por sua entrada!

Comentários

  • É muito mais fácil fazer isso no código-fonte do editor de texto do que no TeX. (luatex é provavelmente mais fácil do que o tex clássico se você realmente quiser fazer no nível do texto) (É fácil o suficiente fazer em contextos de texto restritos, mas difícil se você precisar fazê-lo em parágrafos arbitrários e listas, etc)
  • veja também tex.stackexchange.com/questions/88394/…
  • @percusse I # @ $! &%? !% $ @!% $.
  • @GonzaloMedina Posso comprar uma vogal?
  • Bem, pelo menos Aprendi uma nova palavra hoje. Mas por que não ' t o plural grawlices ?

Resposta

Um símbolo aleatório é retirado de uma lista e anexado a uma lista de tokens; quando a largura dos símbolos acumulados é maior do que a largura da palavra menos 2pt, os símbolos são impressos, caso contrário, outro símbolo é anexado.

\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_censor:n { #1 } } \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \begin{document} Censored \censor{Censored} \end{document} 

insira a descrição da imagem aqui

Resposta

Uma humilde tentativa com lualatex:

O código de substituição é muito ingênuo, precisaríamos de algo mais robusto.

\documentclass{article} \directlua{ % my list of bad words bad_words = { "fish", "cat", "dog", "horse", "alligator" } % the replacement string replacement = "duck" % a replacement function which returns % both the altered line and the number % of occurrences function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, replacement) end end return line, 0 end % my "naive" censor function, it simply % replaces any occurrences of the % list of bad words by the replacement % string function censor(line) occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end % add the hook callback.register("process_input_buffer", censor)} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document} 

O resultado:

Mais patos

Moral de a história: Sou péssimo em contar histórias. :)

Agora, vamos adicionar os grawlixes . Como preciso de um código Lua melhor, vamos criar um arquivo externo censor.lua e chamá-lo de fora do .tex código:

\begin{filecontents*}{censor.lua} -- a list of symbols to represent the -- grawlixe symbols -- note that we need to escape -- some chars grawlixe_symbols = { "\\$", "\\#", "@", "!", "*", "\\&" } -- generate a grawlixe of length s -- note that the seed is not so random, so -- same values of s might get the same -- grawlixe pattern (I could add another seed -- mid code, but I"m lazy) function grawlixe(s) math.randomseed(os.time()) local u = table.getn(grawlixe_symbols) local i = math.random(u) local r = grawlixe_symbols[i] local current local w = 1 repeat current = math.random(u) while current == i do current = math.random(u) end i = current r = r .. grawlixe_symbols[i] w = w + 1 until w == s return r end -- a list of bad words to be censored bad_words = { "fish", "cat", "dog", "horse", "alligator" } -- our replacement function, it returns -- the new line and the number of -- replacements made -- note that this is a very naive replacement -- function, there"s a lot of room for -- improvement function replace(line) for _, element in pairs(bad_words) do if string.find(line, element) then return string.gsub(line, element, grawlixe(string.len(element))) end end return line, 0 end -- the censor function, it repeats -- ad nauseam until the line has -- nothing more to be censored function censor(line) local occurrences = 0 repeat line, occurrences = replace(line) until occurrences == 0 return line end -- register the callback callback.register("process_input_buffer", censor) \end{filecontents*} \documentclass{article} \directlua{dofile("censor.lua")} \begin{document} Once upon a time, there was a little cat who lived inside an igloo. Don"t ask me what he was doing there. One day, the cat was visited by his two other friends, the dog and the alligator! --- ``What are you guys doing here?"", said the cat. --- ``We came to visit you, mr.\ cat!"", said the dog. --- ``Our friend horse will be late, he went to the store to buy some frozen fish for you``, replied the alligator. \end{document} 

O resultado:

Grawlixes

Moral da nova história: adicionar grawlixes a um texto faz com que pareça impertinente. :)

Comentários

  • +1 (embora eu esperasse ver uma foto de pato, talvez tenha sido censurada?)

Resposta

Deixando de lado os prós e contras de como e por que fazer isso, acho que é um pequeno exercício agradável para fazer com xstring . Então, aqui está minha opinião sobre isso:

\documentclass{article} \usepackage{xstring} \def\grawlix{{\makeatletter@\makeatother}\textdollar{$\sharp$}*?!} \newcommand{\censor}[1]{\StrLen{#1}[\result]% \expandarg\StrLeft{\grawlix}{\result}[]} \begin{document} What the \censor{word} is this??? \end{document} 

Como você pode ver, a limitação é que o grawlix será composto do mesmo conjunto de caracteres, na mesma ordem. (Você pode redefinir o conjunto de caracteres ou encontrar uma maneira de randomizá-los a cada invocação da macro … mas essa é uma história diferente! ;)) Mas seu grawlix será tão longo como a palavra censurada.

O que acontece é que xstring tem suas próprias maneiras de expandir argumentos e as macros não podem ser aninhadas. Portanto, o resultado da macro que encontra o comprimento da palavra censurada é retornado em uma macro diferente (imaginativamente chamada aqui \result) que será (re) usada para dividir o \grawlix no local certo.

A macro \expandarg garante que a expansão seja feita corretamente. De acordo com xstring documentação, ele permitirá que todos os argumentos passados sejam expandidos exatamente uma vez. Portanto, deve-se tomar cuidado para proteger os grupos que representam um único caractere com colchetes (por exemplo, o \sharp o símbolo vive no modo matemático, mas não queremos os cifrões que o delimitam para serem vistos como tokens separados).

Comentários

  • Eu não ' ache que \makeatletter e \makeatother são necessários em torno do @ … Ele pode ser usado como o símbolo que é imediatamente.
  • @cgnieder É ' um bom trabalho, eles não são necessários, pois não têm nenhum efeito se usados dentro da definição aqui: – )
  • @DavidCarlisle true, não ' pensei nisso … preciso de mais café

Resposta

Uma solução TeX simples sem pacotes adicionais, com base nas ideias de Kees van der Laan.

\documentclass{article} \begin{document} \newcount\cur \newcount\cura \def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi} \def\mynum#1{\cur\the\lccode`#1\relax\the\cur } \def\process#1{\cur\the\lccode`#1\relax\cura\cur \divide\cura by7 \multiply\cura by7 \advance\cur by-\cura\ifcase\cur!\or@\or\#\or\$\or\%\or\&\or*\else ERROR\fi } \fifo censored \ofif \bigskip \def\censor#1{\fifo #1\ofif} \censor{fuck} \censor{WORD} it is \censor{shit} \end{document} 

Você provavelmente deseja que o resultado seja conectado à palavra usada.Nesta solução, é \lccode de um módulo de caractere 7. Você pode escrever

 \fifo censored \ofif 

ou, conforme sugerido (desculpe meu idioma),

\censor{fuck} \censor{WORD} it is \censor{shit} 

obtendo

insira a descrição da imagem aqui

Algumas explicações. A principal ferramenta é a implementação da fila FIFO (First-In-First-Out) sugerida por Kees van der Laan:

\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi} 

O \fifo comando chama uma macro \process que trata os argumentos individuais. Cada token é processado até \ofif.

O resto é simples. Manipulando nos contadores \cur e \cura, obtemos um número entre 0 e 6 e \ifcase usa caracteres de censura diferentes para valores diferentes.

Observação. Estou muito interessado nas regras reais ( se existirem) de substituir palavrões por strings de símbolos do tipo @.

Comentários

  • Muito bom. Você poderia talvez expandir (com o perdão do trocadilho) um pouco sobre como o código realmente funciona?
  • @AlanMunn Sim, mas depois de voltar para casa (tarde da noite).
  • \censor{MSWORD}

Resposta

Uma maneira estável de trocar símbolos é mudar a codificação da fonte ou para recodificar a fonte. Um exemplo simples

\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document} 

Com lualatex, será provavelmente possível no futuro (quando a interface for mais estável) criar fontes virtuais recodificadas no voar, atualmente já deve ser possível fazê-lo com um arquivo de feição.

Resposta

Esta é uma extensão de @egreg “s resposta usando outra resposta de @egreg.

Com este código, você pode inserir uma frase inteira em \censor e todas as palavras inicialmente adicionadas a uma lista usando \addcensor são substituídas por grawlixes. O argumento para \addcensor pode ser um palavra única ou uma lista separada por vírgulas.

\documentclass{article} \usepackage{xparse,pgf} \ExplSyntaxOn \NewDocumentCommand{\censor}{m} { \pointer_badseq:n { #1 } } \tl_new:N \g_pointer_badwords_tl \NewDocumentCommand{\addcensor}{m} { \clist_map_inline:nn { #1 } { \tl_gput_right:Nn \g_pointer_badwords_tl { {##1}{} } } } \cs_generate_variant:Nn \str_case:nnTF { nV } \cs_new_protected:Npn \pointer_badseq:n #1 { \seq_set_split:Nnn \l_tmpa_seq { ~ } { #1 } \seq_map_inline:Nn \l_tmpa_seq { \str_case:nVTF { ##1 } \g_pointer_badwords_tl { \pointer_censor:n { ##1 } } { ##1 } ~ % Readd space } \tex_unskip:D % Remove the trailing space } % From @egreg"s answer \seq_new:N \g_pointer_grawlixes_seq \tl_map_inline:nn { @ * \# ! \$ \% ? ! \# @ \% *} { \seq_gput_right:Nn \g_pointer_grawlixes_seq { #1 } } \int_const:Nn \c_pointer_grawlix_list_int { \seq_count:N \g_pointer_grawlixes_seq } \dim_new:N \l_pointer_censor_dim \dim_new:N \l_pointer_try_dim \box_new:N \l_pointer_censor_box \tl_new:N \l_pointer_grawlixes_tl \cs_new_protected:Npn \pointer_censor:n #1 { \tl_clear:N \l_pointer_grawlixes_tl \hbox_set:Nn \l_pointer_censor_box { #1 } \dim_set:Nn \l_pointer_censor_dim { \box_wd:N \l_pointer_censor_box } \pointer_add_grawlix: } \cs_new_protected:Npn \pointer_add_grawlix: { \hbox_set:Nn \l_pointer_censor_box { \l_pointer_grawlixes_tl } \dim_compare:nTF { \l_pointer_censor_dim - 2pt < \box_wd:N \l_pointer_censor_box } { \tl_use:N \l_pointer_grawlixes_tl } { \pgfmathparse{random(1,\int_eval:n {\c_pointer_grawlix_list_int})} \tl_put_right:Nx \l_pointer_grawlixes_tl { \seq_item:Nn \g_pointer_grawlixes_seq { \pgfmathresult } } \pointer_add_grawlix: } } \ExplSyntaxOff \addcensor{censored,duck} \addcensor{street} \begin{document} A censored man walk down the street together with his duck. \censor{A censored man walk down the street together with his duck}. \end{document} 

insira a descrição da imagem aqui

Comentários

  • Fico irritada quando você usa a colocação tradicional de aberto e a chave de fechamento (abra a chave adjacente à função, depois a nova linha, o código e a chave de fechamento sozinha em uma nova linha —sem indentação—), misturando-a com o método LaTeX3 recomendado (ambos isolados em uma nova linha recuou a mesma quantidade de espaço).
  • @Manuel Desculpe, Espero que minha resposta atualizada se encaixe no estilo recomendado.
  • Definitivamente melhor (IMO). Gosto dessa forma, mesmo agora que ' estou lendo o código-fonte do ConTeXt e ele escreve de maneira completamente diferente (pelo menos eles ' não usam a chave de abertura, nova linha, código, chave de fechamento de nova linha sem muito recuo, mas algo mais como %, nova linha, chave de abertura e código, mais código e chave de fechamento a seguir ao código).

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *