Supongamos que me gustaría censurar una maldición <word> usando grawlixes , p. Ej. «¡¿Qué # @ $! Estás haciendo ?!» ¿Cómo puedo definir un comando \censor tal que \censor{<word>} resulte en una cadena de estos símbolos? No estoy completamente seguro de cuáles o cuántos símbolos deben usarse dada la palabra <word>. Supongo que la cantidad de símbolos utilizados debería ser aproximadamente igual a la cantidad de caracteres en <word>.

¡Gracias por tu entrada!

Comentarios

  • Es mucho más fácil hacer eso en la fuente del editor de texto que en TeX. (luatex es probablemente más fácil que el tex clásico si realmente quieres hacerlo a nivel de texto) (Es bastante fácil hacerlo en contextos de texto restringido pero difícil si necesitas hacerlo en párrafos arbitrarios y listas, etc.)
  • ver también tex.stackexchange.com/questions/88394/…
  • @percusse I # @ $! &%? !% $ @!% $.
  • @GonzaloMedina ¿Puedo comprar una vocal?
  • Bueno, al menos Hoy aprendí una palabra nueva . Pero, ¿por qué no es ‘ t el plural grawlices ?

Responder

Se toma un símbolo aleatorio de una lista y se agrega a una lista de tokens; cuando el ancho de los símbolos acumulados es mayor que el ancho de la palabra menos 2 puntos, los símbolos se imprimen; de lo contrario, se agrega otro símbolo.

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

ingrese la descripción de la imagen aquí

Responder

Un humilde intento con lualatex:

El código de reemplazo es muy ingenuo, necesitaríamos algo más 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} 

El resultado:

Más patos

Moral de la historia: Soy terrible contando historias. :)

Ahora, agreguemos los grawlixes . Como necesito un código Lua mejor, creemos un archivo externo censor.lua y llámelo desde nuestro .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} 

El resultado:

Grawlixes

Moraleja de la nueva historia: agregar grawlixes a un texto hace que parezca travieso. :)

Comentarios

  • +1 (aunque esperaba ver una imagen de pato, ¿tal vez fue censurada?)

Respuesta

Dejando de lado los pros y los contras de cómo y por qué hacer esto, me parece un pequeño ejercicio agradable para hacer con xstring . Así que esta es mi opinión:

\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 puede ver, la limitación es que el grawlix estará compuesto por el mismo conjunto de caracteres, en el mismo orden. (Puede redefinir el conjunto de caracteres o encontrar una manera de aleatorizarlos en cada invocación de la macro … ¡pero esa «es una historia diferente! ;)) Pero su grawlix será tan largo como la palabra censurada.

Lo que sucede es que xstring tiene sus propias formas de expandir argumentos y las macros no se pueden anidar. Por lo tanto, el resultado de la macro que encuentra la longitud de la palabra censurada se devuelve en una macro diferente (llamada imaginativamente aquí \result) que se (re) usará para dividir el \grawlix en el lugar correcto.

La macro \expandarg asegura que la expansión se realice correctamente. De acuerdo con xstring documentación, permitirá que todos los argumentos pasados se expandan exactamente una vez. Por lo tanto, se debe tener cuidado de proteger los grupos que representan un carácter único con llaves (por ejemplo, el \sharp símbolo vive en modo matemático, pero no queremos t los signos de dólar que los delimitan para que se vean como tokens separados).

Comentarios

  • No ‘ t creo que \makeatletter y \makeatother son necesarios alrededor del @ … Se puede usar como el símbolo que es de inmediato.
  • @cgnieder Es ‘ un buen trabajo, no son necesarios ya que no tienen ningún efecto si se usan dentro de la definición como aquí: – )
  • @DavidCarlisle cierto, no había ‘ t pensado en eso … necesito más café

Answer

Una solución simple de TeX sin paquetes adicionales, basada en ideas 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} 

Probablemente desee que el resultado se relacione con la palabra utilizada.En esta solución es \lccode de un carácter módulo 7. Puede escribir

 \fifo censored \ofif 

o, como se sugiere (perdón por mi idioma),

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

obteniendo

ingrese la descripción de la imagen aquí

Algunas explicaciones. La herramienta principal es la implementación de la cola 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} 

La llama a una macro \process que maneja los argumentos individuales. Cada token se procesa hasta \ofif.

El resto es simple. Manipulando en los contadores \cur y \cura obtenemos un número entre 0 y 6 y \ifcase toma diferentes caracteres de censura para diferentes valores.

Observación. Estoy muy interesado en las reglas reales ( si existen) de reemplazar las malas palabras por cadenas de símbolos como @.

Comentarios

  • Muy bueno. ¿Podría quizás expandir (perdón por el juego de palabras) un poco sobre cómo funciona realmente el código?
  • @AlanMunn Sí, pero después de regresar a casa (a última hora de la noche).
  • \censor{MSWORD}

Respuesta

Una forma estable de intercambiar símbolos es cambiar la codificación de fuente o para volver a codificar la fuente. Un ejemplo simple

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

Con lualatex, en el futuro (cuando la interfaz sea más estable) probablemente sea posible crear fuentes virtuales codificadas en la fly, actualmente ya debería ser posible hacerlo con un archivo de características.

Respuesta

Esta es una extensión de @egreg «s answer usando otra respuesta de @egreg.

Con este código puede ingresar una oración completa en \censor y todas las palabras agregadas inicialmente a una lista con \addcensor se reemplazan por grawlixes. El argumento para \addcensor puede ser un una sola palabra o una lista separada por comas.

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

ingrese la descripción de la imagen aquí

Comentarios

  • Me molesta cuando usas la colocación tradicional de open y llave de cierre (llave abierta adyacente a la función, luego nueva línea, luego el código, y luego la llave de cierre sola en una nueva línea —sin sangría—), mezclándola con la forma recomendada de LaTeX3 (ambas solas en una nueva línea, sangrado la misma cantidad de espacio).
  • @Manuel Lo siento, Espero que mi respuesta actualizada se ajuste al estilo recomendado.
  • Definitivamente mejor (IMO). Me gusta así, incluso ahora que ‘ estoy leyendo el código fuente de ConTeXt y escribe completamente diferente (al menos no ‘ usan la llave de apertura, nueva línea, código, llave de cierre de nueva línea sin sangría demasiado, pero algo más como %, nueva línea, llave de apertura y código, más código y llave de cierre a continuación al código).

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *