;;; Package --- Summary
;;; 
;;; Code:

(defvar 3/ht-unicode nil)
(setq   3/ht-unicode (ht))

(defun 3/unicodify (str)
  "Get a corresponding unicode symbol, to `STR'."
  (ht-get 3/ht-unicode str))

  
(cl-defun uni3/region (&optional beg end)
  "Replace the first mapped char sequence (to a unicode char) between `BEG' and `END'"
  (interactive)
  (let* ((m 0))

    (save-excursion

    (let* ((e    (or end (point)))
           (b    (or beg (progn (beginning-of-line) (point))))
           ;; Current line
           (s    (buffer-substring-no-properties b e))


           ;; ∀ KEY ∈ HT, STR ∈ LINE; 
           ;;    LINE[(|LINE|-|KEY|), |LINE|] = KEY)
           ;;    -⟶ |KEY| ∈ `mtch' 
           ;; `mtch' := all keys which are present as a substring at end of
           ;;      region.           
           
           (mtch (list))
           ;; All keys which map to some string
           (uk   (ht-keys 3/ht-unicode)))
               
      (progn

        ;; Check all keys in the unicode mapping
        ;; (string which maps to a unicode/pretty string)
        ;; if they begin with a string in the mapping of keys.
        ;; infront of the cursor/marker/(region end).

        (dotimes (n (length uk))
          (when (string-suffix-p (nth n uk) s)
            ;; As different keys can begin with the same char
            ;; all the matching keys are added to a list.
            ;; ex: [=>] and =[=>]  
            (push (nth n uk) mtch)))

        (when (>= (length mtch) 1)
          ;; Sort the matches and pick the longest matching string
            (setq m (car (sort mtch
                   #'(lambda (n m)
                       (> (length n) (length m))))))

            ;; Replace matched string with the mapped string
            (goto-char e)
            (delete-backward-char (length m))
            (insert (ht-get 3/ht-unicode m))
            (setq m (length (ht-get 3/ht-unicode m)))))))
    
            (forward-char m))) 

  (defun uni3 (str ustr)
    "Map `STR' to a Unicode string `USTR'."
    (ht-set 3/ht-unicode str ustr))


(seq-do
`(lambda (x) (interactive)
   (uni3 (car x) (cdr x)))

`(("==>" . "⟹")                                   ("[[" . "⟦")
  ("<==" . "⟸")                                   ("__" . "⸏")
  ("\\" . "\")                                   ("joker" . "🂿")
  ("joker" . "🂿")                                 ("Bin" . "Bin(n, p)")
  ("PY" . "P(X)")                                 ("PX" . "P(Y)")
  ("AX" . "P(A)")                                 ("BX" . "P(B)")
  ("C" . "C(X, Y)")                               ("PY=" . "P(X = x)")
  ("fx" . "𝑓(x)")                                 ("px" . "p(x)")
  ("pxy" . "p(x, y)")                             ("P|" . "P(A|B) = P(A ∩ B)/P(B)")
  ("P-" . "P(A ∩ B) = P(B|A)P(A)")                ("P^" . "P(A ∩ B) = P(B|A)P(A)")
  ("PB" . "P(B|L) = P(L|R)P(B)/P(L)")             ("PA*" . "P(B ∩ A*) = P(B) - P(A ∩ B)")
  ("PU" . "P(A ∪ B) = P(A) + P(B) - P(A ∩ B)")    ("PU*" . "P(A* ∪ B*) = 1 - P(A ∩ B)")
  ("P+" . "P(A ∪ B) = P(A) + P(B)")               ("P*" . "P(A*) = 1 - P(A)")
  
  
  ("PX=" . "P(Y = y)")                            ("AX=" . "P(A = x)")
  ("BX=" . "P(B = x)")                            ("Ge" . "Ge(p)")
  ("Po" . "Po(μ)")                                ("Re" . "Re(a, b)")
  ("Exp" . "Exp(𝜆)")                              ("Re" . "Re(n, Γ)")
  ("N" . "N(μ)")                                  ("\\" . "⟍")
  ("/" . "⟋")
  
  ("fool" . "🃠")                                  ("\\tautologi" . "⫟")
  ("\\falseness" . "⫠")                           ("|>" . "⮚")
  ("<|" . "⮘")                                    ("<==>" . "⟺")        
  ("<(" . "⟨")                                    (")>" . "⟩")
  ("<<" . "⟪")                                    (">>" . "⟫")
  ("O" . "𝛀")                                     ("\\beta" . "𝛃")
  ("𝛃" . "𝛽")                                     ("𝛽" . "𝛃")
  ("\\alpha" . "𝛂")                               ( "𝛂" . "𝛼")
  ( "𝛼" . "𝛂")                                    ("3.14" . "𝝅")
  ("\\pi" . "𝝅")                                  ("𝜋" . "𝝅")
  ("𝝅" . "𝜋")                                     ("\\gamma" . "𝛄")
  ("𝛾" . "𝛄")                                     ("𝛄" . "𝛾")
  ("\\sigma" . "𝚺")                               ("\\chi" . "𝛘")
  ("𝜒" . "𝛘")                                     ("𝛘" . "𝜒")
  
  ("\\kappa" . "𝛞")                               ("𝜘" . "𝛞")
  ("𝛞" . "𝜘")                                     ("/x" . "𝑥")
  ("/y" . "𝑦")                                    ("/z" . "𝑧")
  ("/v" . "𝑣")                                    ("/u" . "𝑢")
  ("/r" . "𝑟")                                    ("/s" . "𝑠")
  ("/n" . "𝑛")                                    ("/m" . "𝑚")
  ("/k" . "𝑘")                                    ("/j" . "𝑗")
  ("/i" . "𝑖")                                    ("/g" . "𝑔")
  ("/f" . "𝑓")                                    ("/e" . "𝑒")
  ("*" . "∙")                                     ("\\unions" . "⨅")
  ("\\intersections" . "⨆")                       ("AND" . "⨁")
  ("XOR" . "⨂")                                   ("dot" . "⋅")
  
  ("\\Psi" . "𝛙")                                 ("\\psi" . "𝛗")
  ("𝜑" . "𝛗")                                     ("𝛗" . "𝜑")
  
  ("\\Theta" . "𝜽")                               ("𝜽" . "𝜭")
  ("𝜭" . "𝜃")                                     ("𝜃" . "𝜽")
  
  ("\\Lambda" . "𝜦")                              ("\\sigma" . "𝛔")
  ("𝜎" . "𝛔")                                     ("𝛔" . "𝜎")
  
  ("\\mu" . "𝝁")                                  ("μ" . "𝝁")
  ("𝝁" . "𝜇")                                     ("𝜇" . "μ")
  
  ("/f" . "𝑓")                                    ("\\tau" . "𝛕")
  ("𝜏" . "𝛕")                                     ("𝛕" . "𝜏")
  
  ("\\blam" . "𝝀")                                ("\\lam" . "𝜆")
  ("\\." . "𝜆")                                   ("\\\\" . "𝜆")
  ("lambda" . "𝜆")                                ("𝛌" . "𝝀")
  ("𝝀" . "𝜆")                                     ("𝜆" . "𝛌")
  
  ("*K" . "𝐊")                                    ("*L" . "𝐋")
  ("*M" . "𝐌")                                    ("*N" . "𝐍")
  ("*W" . "𝑊")                                    ("\\mark" . "🠷")
  ("\\doc" . "🖹")                                 ("\\folder" . "🗀")
  ("[v]" . "🗹")                                   ("[x]" . "🗷")
  ("pen" . "✎")                                   ("cross" . "❌")
  ("<->" . "⟷")                                   ("<--" . "⟵")
  ("-->" . "⟶")                                   ("⟶" . "→")
  ("→" . "↦")                                     ("↦" . "➞") 
  ("➞" . "⇥")                                     ("⇥" . "⟿")
  ("⟿" . "⟼")                                     ("|==>" . "⟾")
  ("⟹" . "⟾")                                     ("⟺" . "⟻")
  ("<--|" . "⟻")                                  ("⟻" . "⟽")
  ("⇣" . "↓")                                     ("↓" . "↑")
  ("⇡" . "ꜛ")                                     ("ꜛ" . "⌃")
  ("⇍" . "⇏")                                     ("⇏" . "⃗")
  ("^<--" . "⃖")                                   ("⃖" . "⃡")   
  ("^<->" . "⃡")                                   ("⃡" . "᷾")
  ("^<" . "᷾")                                     ("__>" . "ࣺ")
  ("__<" . "ࣹ")                                    ("ࣺ" . "˲")
  ("_<" . "˱")                                    ("_v" . "˯")
  ("_>" . "˲")                                    ("_^" . "˰")
  ("/X" . "𝑋")                                    ("/Y" . "𝑌")
  ("\\Omega" . "𝜴")                               ("𝜴" . "𝛺")
  ("𝛺" . "𝜴")                                     ("\\omega" . "𝜔")
  ("\\phi" . "𝜱")                                 ("𝜱" . "ϕ")
  ("ϕ" . "ɸ")                                     ("ɸ" . "Φ")
  ("Φ" . "𝜱")                                     ("/Z" . "𝑍")
  ("(~)" . "☯")                                   ("point" . "☞")
  ("\\equiv" . "≡")                               ("\\nequiv" . "≢")
  
  ("\\divides" . "∣")                             ("\\sum" . "∑")
  ("∑" . "𝜮")                                     ("𝜮" . "∑")
  ("\\product" . "∏")                             ("\\coproduct" . "∐")
  ("∐" . "⨿")                                     ("⨿" . "∐")
  ("\\integral" . "∫")                            ("\\integral1" . "⌠")
  ("\\integral2" . "⎮")                           ("\\integral3" . "⌡")
  ("\\sum1" . "⎲")                                ("\\sum2" . "⎳")
  
  ("\\sqrt" . "√")                                ("\\in" . "∈")
  ("\\notin" . "∉")                               ("\\thereexists" . "∃")
  ("\\theredoesnotexist" . "∄")                   ("\\exists" . "∃")
  ("\\notexists" . "∄")                           ("\\forall" . "∀")
  ("\\all" . "∀")                                 ("\\prod" . "∏")
  ("\\product" . "∏")                             ("\\inf" . "∞")
  ("oo" . "∞")                                    ("//R" . "ℝ")
  ("//Q" . "ℚ")                                   ("//N" . "ℕ")
  ("//Z" . "ℤ")
  
  
  ("_0" . "₀")                                    ("_1" . "₁")
  ("_2" . "₂")                                    ("_3" . "₃")
  ("_4" . "₄")                                    ("_5" . "₅")
  ("_6" . "₆")                                    ("_7" . "₇")
  ("_8" . "₈")                                    ("_9" . "₉")
  ("_+" . "₊")                                    ("_-" . "₋")
  ("_=" . "₌")                                    ("[]" . "🞎")
  ("><" . "🟇")                                    ("star" . "🟇")
  ("def" . "≔")                                   (":=" . "≔")
  ("/=" . "≠")                                    ("!=" . "≠")
  ("\\neq" . "≠")                                 ("\\leq" . "≤")
  ("\\geq" . "≥")                                 ("\\union" . "∪")
  ("\\intersect" . "∩")  ("\\sect" . "∩")
  ("\\snitt" . "∩")                               (">x" . "𝚡")
  (">y" . "𝚢")                                    (">z" . "𝚣")
  (">v" . "𝚟")                                    (">w" . "𝚠")))


(global-unset-key (kbd "M-u") )
(global-set-key   (kbd "M-u") 'uni3/region)


(provide 'unit3)
;;; unit3 ends here.