Philipp Gesang avatar Philipp Gesang committed d51c7c0

[cbk] make auto-grouping an option

Comments (0)

Files changed (4)

doc/context/third/enigma/enigma_manual.tex

         day_key = I II III
                   01 01 01,
         rotor_setting = aaa,
+        spacing = yes,
         verbose = 1,
       }
       %% Usage ················ %%
     positions of the three rotors, the ring settings, and the plugboard
     wiring.
   \item{rotor_setting}{string} The initial rotor advancement.
+  \item{spacing}{boolean} Auto-space output?
   \item{verbose}{integer} Controls overall verbosity level (\emph{global}!).
 \stopitemize
 
 one rotor (e.\,g. \type{fkd}). Historically this was not part of the day
 key but supposed to be chosen at random by the operating signal officer.
 
+The output can be automatically grouped into sequences of five
+characters, delimited by spaces. This does not only conform with
+traditional crypto-style, but also allows for the resulting text to be
+sanely broken into lines by \TEX.
+
 %%% other_chars
 % The option \identifier{other_chars} determines how the machine -- in our
 % Unicode-aware times -- should behave when it encounters a non-Latin

doc/context/third/enigma/examples/enigma-example-context.tex

   other_chars = no,
   day_key = I II III 01 01 01,
   rotor_setting = aaa,
+  spacing = yes,
   verbose = 3,
 ]
 

doc/context/third/enigma/examples/enigma-example-latex.tex

   other_chars = yes,
   day_key = B V III II 12 03 01 GI JV KZ WM PU QY AD CN ET FL,
   rotor_setting = ben,
+  spacing = yes,
+  verbose = 3,
 }
 %%·····································································%
 %% This second machine below will be used to decrypt the string. It is

tex/context/third/enigma/enigma.lua

     local raw_settings = handle_day_key(setup_string, name)
     local rotors, ring =
       get_rotors(raw_settings.rotors, raw_settings.ring)
-    local plugboard = raw_settings.plugboard
-                  and get_plugboard_substitution(raw_settings.plugboard)
-                  or get_plugboard_substitution{ }
+    local plugboard
+        = raw_settings.plugboard
+          and get_plugboard_substitution(raw_settings.plugboard)
+          or  get_plugboard_substitution{ }
     local machine = {
       name                = name,
       step                = 0, -- n characters encoded
       ring                = ring,
       state               = init_state,
       other_chars         = args.other_chars,
+      spacing             = args.spacing,
       ---> a>1, b>2, c>3
       reflector           = letter_to_value[raw_settings.reflector],
       plugboard           = plugboard,
       --- <badcodingstyle>
       __raw               = raw_settings -- hackish but occasionally useful
       --- </badcodingstyle>
-    }
+    } --- machine
     local init_state = pattern_to_state(pattern or get_random_pattern())
     emit(1, pprint_init, init_state)
     machine:set_state(init_state)
 
   local sanitizers = {
     other_chars   = toboolean,          -- true = keep, false = drop
+    spacing       = toboolean,
     day_key       = alphanum_or_space,
     rotor_setting = ensure_alpha,
     verbose       = ensure_int,
   enigma.machines [name] = machine
   local space_node
   local mod_5 = 0
-  local insert_with_spacing = function (head, n, replacement)
-    local insertion = nodecopy(n)
-    if replacement then -- inefficient but bulletproof
-      insertion.char = utf8byte(replacement)
-      --print(utf8char(n.char), "=>", utf8char(insertion.char))
+  local insert_encoded
+  --- First we need to choose an insertion method. If autospacing is
+  --- requested, a space will have to be inserted every five characters.
+  --- The rationale behind using differend functions to implement each
+  --- method is that it should be faster than branching for each
+  --- character.
+  if machine.spacing then -- auto-group output
+    insert_encoded = function (head, n, replacement)
+      local insertion = nodecopy(n)
+      if replacement then -- inefficient but bulletproof
+        insertion.char = utf8byte(replacement)
+        --print(utf8char(n.char), "=>", utf8char(insertion.char))
+      end
+      nodeinsert_before(head, n, insertion)
+      mod_5 = mod_5 + 1
+      if mod_5 >= 5 then
+        mod_5 = 0
+        nodeinsert_after(head, insertion, nodecopy(space_node))
+      end
+      noderemove(head, n)
     end
-    nodeinsert_before(head, n, insertion)
-    mod_5 = mod_5 + 1
-    if mod_5 >= 5 then
-      mod_5 = 0
-      nodeinsert_after(head, insertion, nodecopy(space_node))
+  else
+    insert_encoded = function (head, n, replacement)
+      local insertion = nodecopy(n)
+      if replacement then -- inefficient but bulletproof
+        insertion.char = utf8byte(replacement)
+      end
+      nodeinsert_before(head, n, insertion)
+      noderemove(head, n)
     end
-    noderemove(head, n)
   end
   local format_is_context_p = format_is_context_p
+  --- The callback proper starts here.
   local cbk = function (a, _, c)
     space_node = generate_space ()
     local head = format_is_context_p and c or a
         --if replacement == false then
         if not replacement then
           if machine.other_chars then
-            insert_with_spacing(head, n, nil)
+            insert_encoded(head, n, nil)
           else
             noderemove(head, n)
           end
         elseif treplacement == "string" then
-          insert_with_spacing(head, n, replacement)
+          insert_encoded(head, n, replacement)
         elseif treplacement == "table" then
           for i=1, #replacement do
-            insert_with_spacing(head, n, replacement)
+            insert_encoded(head, n, replacement)
           end
         end
       elseif nid == GLUE_NODE then
         if npre and npost then
           local replacement_pre  = machine:encode(utf8char(npre.char))
           local replacement_post = machine:encode(utf8char(npost.char))
-          insert_with_spacing(head,  npre, replacement_pre)
-          insert_with_spacing(head, npost, replacement_post)
+          insert_encoded(head,  npre, replacement_pre)
+          insert_encoded(head, npost, replacement_post)
         end
         noderemove(head, n)
       --else
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.