Supposons que je souhaite censurer un mot de malédiction <word> en utilisant grawlixes , par exemple « Quest-ce que tu fais # @ $!?! » Comment définir une commande \censor telle que \censor{<word>} aboutisse à une chaîne de ces symboles? Je ne suis pas tout à fait sûr de savoir quels symboles ou combien de symboles utiliser étant donné le mot <word>. Je suppose que le nombre de symboles utilisés doit être approximativement égal au nombre de caractères dans <word>.

Merci pour votre contribution!

Commentaires

  • Il est beaucoup plus facile de faire cela dans le source de léditeur de texte que dans TeX. (luatex est probablement plus facile que le tex classique si vous voulez vraiment le faire au niveau du texte) (Il est assez facile de le faire dans des contextes de texte restreints mais difficile si vous devez le faire dans des paragraphes et des listes arbitraires, etc.)
  • voir aussi tex.stackexchange.com/questions/88394/…
  • @percusse I # @ $! &%? !% $ @!% $.
  • @GonzaloMedina Puis-je acheter une voyelle?
  • Eh bien, au moins Jai appris un nouveau mot aujourdhui. Mais pourquoi ‘ t le pluriel grawlices ?

Answer

Un symbole aléatoire est pris dans une liste et ajouté à une liste de jetons; lorsque la largeur des symboles accumulés est supérieure à la largeur du mot moins 2pt, les symboles sont imprimés, sinon un autre symbole est ajouté.

\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} 

entrez la description de limage ici

Réponse

Une humble tentative avec lualatex:

Le code de remplacement est très naïf, nous aurions besoin de quelque chose de plus robuste.

\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} 

Le résultat:

Plus de canards

Morale de l’histoire: Je « m’arrive mal à raconter des histoires. :)

Maintenant, ajoutons les grawlix . Puisque jai besoin dun meilleur code Lua, créons un fichier externe censor.lua et appelons-le depuis le code .tex:

\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} 

Le résultat:

Grawlixes

Morale de la nouvelle histoire: ajouter des grawlix à un texte le rend méchant. :)

Commentaires

  • +1 (même si jespérais voir une photo de canard, elle était peut-être censurée?)

Réponse

En laissant de côté les avantages et les inconvénients de comment et pourquoi faire cela, je trouve que cest un joli petit exercice à faire avec xstring . Voici donc mon point de vue:

\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} 

Comme vous pouvez le voir, la limitation est que le grawlix sera composé du même jeu de caractères, dans le même ordre. (Vous pouvez redéfinir le jeu de caractères ou trouver un moyen de les randomiser à chaque invocation de la macro … mais cest « une histoire différente! ;)) Mais votre grawlix sera aussi long comme mot censuré.

Ce qui se passe, cest que xstring a ses propres façons détendre les arguments et les macros ne peuvent pas être imbriquées. Le résultat de la macro qui trouve la longueur du mot censuré est renvoyée dans une macro différente (appelée ici de manière imaginative \result) qui sera (re) utilisée pour fractionner le \grawlix au bon endroit.

La macro \expandarg sassure que lexpansion est effectuée correctement. Selon xstring documentation, il permettra à tous les arguments passés dêtre développés exactement une fois. Par conséquent, il faut veiller à protéger les groupes qui représentent un caractère unique avec des accolades (par exemple le \sharp le symbole vit en mode mathmode, mais nous ne voulons pas t le signe dollar le délimitant pour être vu comme des jetons séparés).

Commentaires

  • I don ‘ Je pense que \makeatletter et \makeatother sont nécessaires autour du @ … Il peut être utilisé comme symbole tout de suite.
  • @cgnieder Cest ‘ un bon travail, ils ne sont pas nécessaires car ils nont aucun effet sils sont utilisés à lintérieur de la définition comme ici: – )
  • @DavidCarlisle vrai, je navais ‘ pas pensé à ça … Jai besoin de plus de café

Réponse

Une solution TeX simple sans packages supplémentaires, basée sur les idées 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} 

Vous voulez probablement que le résultat soit lié au mot utilisé.Dans cette solution, il sagit de \lccode dun caractère modulo 7. Vous pouvez écrire soit

 \fifo censored \ofif 

ou, comme suggéré (désolé pour ma langue),

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

obtenant

entrez la description de limage ici

Quelques explications. Loutil principal est limplémentation de la file dattente FIFO (First-In-First-Out) suggérée par Kees van der Laan:

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

Le appelle une macro \process qui gère les arguments individuels. Chaque jeton est traité jusquà \ofif.

Le reste est simple. En manipulant sur les compteurs \cur et \cura nous obtenons un nombre compris entre 0 et 6 et \ifcase prend différents caractères de censure pour différentes valeurs.

Remarque. Je suis très intéressé par les règles réelles ( sils existent) de remplacer les mots maudits par des chaînes de symboles @-like.

Commentaires

  • Très bien. Pourriez-vous peut-être développer (pardonner le jeu de mots) un peu le fonctionnement du code?
  • @AlanMunn Oui, mais après être rentré chez vous (en fin de soirée).
  • \censor{MSWORD}

Réponse

Un moyen stable déchanger des symboles consiste à changer le codage de la police ou pour réencoder la police. Un exemple simple

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

Avec lualatex, il sera probablement possible à lavenir (lorsque linterface sera plus stable) de créer des polices virtuelles réencodées sur-le- fly, actuellement, il devrait être déjà possible de le faire avec un fichier de fonctionnalités.

Réponse

Ceci est une extension de @egreg « s answer en utilisant une autre réponse de @egreg.

Avec ce code, vous pouvez saisir une phrase entière dans \censor et tous les mots initialement ajoutés à une liste à laide de \addcensor sont remplacés par des grawlixes. Largument de \addcensor peut être soit un un seul mot ou une liste séparée par des virgules.

\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} 

entrez la description de limage ici

Commentaires

  • Cela me gêne lorsque vous utilisez le placement traditionnel de open et laccolade fermante (accolade ouverte adjacente à la fonction, puis nouvelle ligne, puis le code, puis laccolade fermante seule dans une nouvelle ligne – sans retrait -), en la mélangeant avec la méthode LaTeX3 recommandée (les deux seules sur une nouvelle ligne, en retrait de la même quantité despace).
  • @Manuel Désolé, Jespère que ma réponse mise à jour correspond au style recommandé.
  • Certainement mieux (IMO). Jaime cette façon, même maintenant que je ‘ m en train de lire le code source de ConTeXt et quil écrit complètement différent (au moins ils nutilisent pas ‘ laccolade ouvrante, la nouvelle ligne, le code, laccolade fermante de nouvelle ligne sans indentation trop, mais quelque chose de plus comme %, nouvelle ligne, accolade ouvrante et code, plus de code et accolade fermante ensuite au code).

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *