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}
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:
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:
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
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}
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).