Tegyük fel, hogy egy átokszót <word>
cenzúrázni szeretnék a grawlixes , pl “Mi a # @ $! Csinálsz ?!” Hogyan definiálhatok egy \censor
parancsot úgy, hogy a \censor{<word>}
e szimbólumokból álló karaktersorozatot eredményezzen? Nem vagyok teljesen biztos abban, hogy melyik vagy hány szimbólumot kell használni a <word>
szóra való tekintettel. Feltételezem, hogy a használt szimbólumok számának hozzávetőlegesen meg kell egyeznie a <word>
karakterek számával.
Köszönjük a közreműködést!
Megjegyzések
- Ezt sokkal könnyebb megtenni a szövegszerkesztő forrásban, mint a TeX-ben. (A luatex valószínűleg könnyebb, mint a klasszikus tex, ha valóban szöveges szinten akarja megtenni) (Elég egyszerű ezt korlátozott szöveges kontextusban megtenni, de nehéz, ha tetszőleges bekezdésekben és listákban kell megtenni stb.)
- lásd még: tex.stackexchange.com/questions/88394/…
- @percusse I # @ $! &%? !% $ @!% $.
- @GonzaloMedina Vásárolhatok magánhangzót?
- Nos, legalább ma megtanultam egy új szót . De miért nem ‘ t a többes számú szemcsék ?
válasz
Véletlenszerű szimbólumot veszünk fel egy listáról, és egy token listához csatolunk; ha a felhalmozott szimbólumok szélessége meghaladja a 2pt mínusz szó szélességét, akkor a szimbólumok kinyomtatásra kerülnek, különben egy másik szimbólum kerül hozzá.
\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}
Válasz
Alázatos kísérlet a :
A helyettesítő kód nagyon naiv, valami erősebbre lenne szükségünk.
\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}
A kimenet:
Erkölcs a történet: Szörnyű vagyok a történetek elmondásában. :)
Most adjuk hozzá a grawlixeket . Mivel jobb Lua kódra van szükségem, hozzunk létre egy külső fájlt censor.lua
, és hívjuk ki .tex
kódból:
\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}
A kimenet:
Az új történet morálja: grawlixek hozzáadása egy szöveghez csintalannak tűnik. :)
Megjegyzések
- +1 (bár reméltem, hogy kacsa képet látok, talán cenzúrázták?)
Válasz
Eltekintve az előnyeivel és hátrányaival, hogyan és miért kell ezt csinálni, jó kis gyakorlatnak tartom a következőt: xstring
. Tehát itt állok vele:
\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}
Amint láthatja, a korlátozás az, hogy a grawlix ugyanazokból a karakterekből áll, ugyanabban a sorrendben. (Lehet, hogy újradefiniálja a karakterkészletet, vagy megtalálhatja a módját, hogy véletlenszerűen véletlenszerűsítse őket a makró minden egyes meghívásakor … de ez “más történet! ;)
) De a grawlixje olyan hosszú lesz mint a cenzúrázott szó.
Az történik, hogy xstring
megvannak a maga módszerei az argumentumok kiterjesztésére, és a makrókat nem lehet egymásba ágyazni. Tehát a megtalált makró eredménye a cenzúrázott szó hossza egy másik makróban kerül visszaadásra (ötletesen itt nevezzük \result
), amelyet (előre) az előre definiált \grawlix
a megfelelő helyen.
A \expandarg
makró gondoskodik a bővítés megfelelő végrehajtásáról. A xstring
szerint dokumentációval, lehetővé teszi az összes átadott argumentum pontosan kibővítését egyszer. Ezért gondosan ügyelni kell arra, hogy zárójelekkel védjük azokat a csoportokat, amelyek egy egyetlen karaktert képviselnek (pl. a \sharp
szimbólum mathmode-ban él, de mi nem t a dollárjelek azt határolják, hogy külön jelzőknek tekintsék).
Megjegyzések
- Nem ‘ Nem gondolom, hogy
\makeatletter
és\makeatother
szükségesek a @ körül … Ez azonnal használható szimbólumként használható. - @cgnieder Ez ‘ jó munka, nincs szükség rájuk, mivel egyáltalán nincs hatásuk, ha a definíciót belül használják, mint itt: – )
- @DavidCarlisle igaz, nem gondoltam ‘ erre nem gondoltam … Több kávéra van szükségem
Válasz
Egyszerű TeX megoldás további csomagok nélkül, Kees van der Laan ötletei alapján.
\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}
Valószínűleg az eredményt szeretné összekapcsolni a használt szóval.Ebben a megoldásban ez egy modul modul 7 \lccode
karaktere. Írhat akár
\fifo censored \ofif
, akár a javaslat szerint (elnézést a nyelvemért),
\censor{fuck} \censor{WORD} it is \censor{shit}
lekérés
Néhány magyarázat. A fő eszköz a Kees van der Laan által javasolt FIFO (First-In-First-Out) sor beültetése:
\def\fifo#1{\ifx\ofif#1\ofif\fi \process#1\fifo} \def\ofif#1\fifo{\fi}
A parancs meghív egy makrót \process
, amely kezeli az egyes argumentumokat. Minden tokent a \ofif
-ig feldolgozunk.
A többi egyszerű. A \cur
és a \cura
számlálókon 0 és 6 és \ifcase
számot kapunk különböző cenzor karaktereket vesz fel különböző értékekhez.
Megjegyzés. Nagyon érdekelnek a valós szabályok ( ha vannak ilyenek), akkor az átok szavakat @ típusú szimbólumokkal kell felváltani.
Megjegyzések
- Nagyon szép. Esetleg kibővítené (elnézést a szójátékért) egy kicsit a kód tényleges működéséről?
- @AlanMunn Igen, de miután hazatért (késő este).
-
\censor{MSWORD}
Válasz
A szimbólumok cseréjének stabil módja a fontkódolás megváltoztatása vagy a betűtípus újrakódolásához. Egyszerű példa
\documentclass{article} \begin{document} \newcommand\censor[1]{\fontencoding{OMS}\selectfont #1} \censor{Censored} \end{document}
A lualatex használatával a jövőben (amikor az interfész stabilabb lesz) valószínűleg virtuális újrakódolt betűtípusokat lehet létrehozni a repülni, jelenleg lehetővé kell tenni egy funkciófájl használatával.
Válasz
Ez a @egreg “s válasz
Ezzel a kóddal egész mondatot írhat be a és a listához a \addcensor
használatával eredetileg hozzáadott összes szó helyébe grawlixek lépnek. A \addcensor
argumentum lehet egyetlen szó vagy vesszővel elválasztott lista.
\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}
Megjegyzések
- Idegesít, ha a nyílt nyíl hagyományos elhelyezését használom és záró zárójel (nyitott zárójel a függvény mellett, majd új sor, majd a kód, majd a záró zárójel egyedül egy új sorban – behúzás nélkül), összekeverve az ajánlott LaTeX3 módszerrel (mindkettő egyedül egy új soron, ugyanannyi helyet behúzott).
- @Manuel Sajnáljuk, Remélem, hogy frissített válaszom megfelel az ajánlott stílusnak.
- Határozottan jobb (IMO). Tetszik ez a módszer, még most is, amikor ‘ olvasom a ConTeXt forráskódot, és teljesen másként ír (legalábbis nem használnak ‘ a nyitó zárójel, új vonal, kód, új vonal záró zárójel túl nagy behúzás nélkül, de valami hasonló
%
, új sor, nyitó zárójel és kód, további kód és záró zárójel kódhoz).