;;; unit3 --- Mapping of strings to unicode characters or strings
;;; License: GPLv3
;;; Author:  blu3
;;
;;; Code:


(require 'ht)
(require 'cl-lib)

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

(defvar unit3/mappings nil)



(setq   unit3/mappings 
        `(("==>" . "⟹")    ("[|" . "⟦")    ("|]" . "⟧")
          
          ("⎧" . "/{")
          ("⎨" . "|{")
          ("⎩" . "\\{")


          (  "I" . "Ⅰ")  (  "Ⅱ" . "II")  (  "Ⅲ" . "III")                                 
          ("IV" . "Ⅳ")  ("V" . "Ⅴ")  ("VI" . "Ⅵ")                                  
          ("VII" . "Ⅶ")  ("VIII" . "Ⅷ")  ("IX" . "Ⅸ")                              
          ("X" . "Ⅹ")  ("XI" . "Ⅺ")  ("XII" . "Ⅻ")                                 
          ("I" . "Ⅰ")  (  "II" . "Ⅱ")  ("<" . "⟨")                                   
          (">" . "⟩")  (  "III" . "Ⅲ")  (  "IV" . "Ⅳ")                                 
          (  "V" . "Ⅴ")  (  "VI" . "Ⅵ")  (  "VII" . "Ⅶ")                                 
          (  "VIII" . "Ⅷ")  (  "IX" . "Ⅸ")  (  "X" . "Ⅹ")                                
          (  "XI" . "Ⅺ")  (  "XII" . "Ⅻ")

          ("\\\\x" . "λx.x")  ("\\\\y" . "λy.y")  ("\\\\z" . "λz.z")                     
          ("\\\\f" . "λf.(f f)")  ("[|" . "⟦")    ("<>" . "⟨ ⟩")                     
          
          ("<==" . "⟸")                                   ("__" . "⸏")
          ("\\" . "\")                                   ("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" . "⫟")
          ("hourglass" . "⏳") ("\\and" . "∧") ("∧" . "⋀")  ("⋀" . "∧")
          ("\\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" . "⎳")
          ("^(" . "⁽")
          ("^)" . "⁾")

          ("^n" . "ⁿ")
          
          ("^i" . "ⁱ")
          ("^=" . "⁼")
          ("^-" . "⁻")
          ("^+" . "⁺")
          ("^|/" . "⎧") 
          ("^\\\\|" . "⎫")
          ("^{" . "⎨")
          ("^}" . "⎬")
          ("^|\\" . "⎩")
          ("^|//" . "⎭")

          ("([" . "⟬")
          ("])" . "⟭")
          ("⟪" . "⟪")
          ("⟫" . "⟫") 
          ("⟪" . "⟨")
          ("⟫" . "⟩")
          ("⟬" . "❲")
          ("⟭" . "❳")
          ("⟨" . "❰")
          ("⟩" . "❱")
          ("⟨" . "❬")
          ("⟩" . "❭")
          ("~" . "⎰")
          ("⎰" . "⎱")
          ("⎱" . "⎰")
          ("|¨" . "⎡")
          ("¨|" . "⎤")
          ("| " . "⎢")
          (" |" . "⎥")
          ("|_" . "⎣")
          ("_|" . "⎦")

          ("^8" . "⁸")
          ("^9" . "⁹")
          ("^7" . "⁷")
          ("^6" . "⁶")
          ("^5" . "⁵")
          ("^4" . "⁴")
          ("^3" . "³")
          ("^2" . "²")
          ("^1" . "¹")
          ("^0" . "⁰")

          ("\\sqrt" . "√")                                ("\\in" . "∈")
          ("\\notin" . "∉")                               ("\\thereexists" . "∃")
          ("\\theredoesnotexist" . "∄")                   ("\\exists" . "∃")
          ("\\notexists" . "∄")                           ("\\forall" . "∀")
          ("\\all" . "∀")                                 ("\\prod" . "∏")
          ("\\product" . "∏")
          ("\\inf" . "∞")
          ("oo" . "∞")         

          
          ("\\Q" . "ℚ")                                   ("\\N" . "ℕ")
          ("\\Z" . "ℤ")                                   ("\\R" . "ℝ")

          ("\\natural" . "ℕ")   ("\\real" . "ℝ") 
          ("\\integer" . "ℤ")   ("\\rational" . "ℚ")
          
          ("፡" . ":") (":" . "፡")

          ("\\ " . " ")(" " . " ")
          (" "  . " ")(" "  . " ")
          (" "  . " ")(" "  . " ")
          (" "  . " ")(" "  . " ")
          (" "  . " ")(" "  . " ")
          (" "  . " ")(" "  . " ")
          (" " . "\\ ")("\\ws12" . " ") 
          ("\\ws11" . " ")
          ("\\ws10" . " ")
          ("\\ws9" . " ")  
          ("\\ws8" . " ")  
          ("\\ws7" . " ")  
          ("\\ws6" . " ")  
          ("\\ws5" . " ")  
          ("\\ws4" . " ") 
          ("\\ws3" . " ")  
          ("\\ws2" . " ")  
          ("\\ws1" . " ")  
          ("\\ws0" . " ")  
          ("\\spcZ" . "​")
          ("\\spcZNB" . "")
          ("\\_" . "̲") ("\\-" . "̶")
          ("_r" . "ᵣ")                                    ("_v" . "ᵥ")
          ("_beta" . "ᵦ")                                 ("_gamma" . "ᵧ")
          ("_rho" . "ᵨ")                                  ("_phi" . "ᵩ")
          ("_chi" . "ᵪ")                                  ("_(" . "₍")
          ("_)" . "₎")                                    ("_a" . "ₐ")
          ("_e" . "ₑ")                                    ("_o" . "ₒ")
          ("_x" . "ₓ")                                    ("_h" . "ₕ")
          ("_k" . "ₖ")                                    ("_i" . "ₗ")
          ("_m" . "ₘ")                                    ("_n" . "ₙ")
          ("_p" . "ₚ")                                    ("_s" . "ₛ")
          ("_t" . "ₜ ")                                   ("_j" . "ⱼ")
          ("_i" . "ᵢ")                                     ("_u" . "ᵤ")  ("_i" . "ᵢ")
          ("_0" . "₀")                                    ("_1" . "₁")
          ("_2" . "₂")                                    ("_3" . "₃")
          ("_4" . "₄")                                    ("_5" . "₅")
          ("_6" . "₆")                                    ("_7" . "₇")
          ("_8" . "₈")                                    ("_9" . "₉")
          ("_+" . "₊")                                    ("_-" . "₋")
          ("_=" . "₌")                                    ("[]" . "🞎")
          ("><" . "🟇")                                    ("star" . "🟇")
          ("def" . "≔")                                   (":=" . "≔")
          ("/=" . "≠")                                    ("!=" . "≠")
          ("\\neq" . "≠")                                 ("\\leq" . "≤")
          ("\\geq" . "≥")                                 ("\\union" . "∪")
          ("\\intersect" . "∩")  ("\\sect" . "∩")
          ("\\sect" . "∩")                               ("x" . "𝚡") ("𝚡" . "x")
          ("y" . "𝚢") ("𝚢" . "y")
          ("𝚣" . "z") ("z" . "𝚣")
          ("w" . "𝚠") ("𝚠" . "w")))


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

(provide 'unit3/lookup)

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

(provide 'unit3/map)
  
(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))) 

(provide 'unit3/region)



(seq-do `(lambda (x) (interactive)
           (unit3/map (car x) (cdr x)))
        unit3/mappings
)


(defun select-face (face)
  "Complete faces with preview . 
Actions are provided by default for describing or customizing the
selected face                  . "
  (interactive)
  (let* ((names (mapcar #'symbol-name (face-list)))
         (counsel--faces-format
          (format "%%-%ds %%s"
                  (apply #'max 0 (mapcar #'string-width names)))))
 (ivy-read "Face: " names
  :require-match t
  :history 'face-name-history
  :preselect face
  :initial-input face
  :action counsel-describe-face-function
  :caller 'counsel-faces)))


;;(defun insert-replace (regx-match after before &optional beg end)
;;  (interactive
;;   "sRegexp Match:
;;sInsert AFTER:
;;sInsert BEFORE:
;;")
;;             
;;  (save-excursion
;;;;    (dotimes (line+ (- e_line b_line))
;;;;      (let  ((cline (+ b_line line+)))
;;    (goto-char   (region-beginning))
;;
;;    (while :until (> (point) (region-end))
;;              :do
;;              (progn
;;    (search-forward-regexp regx-match (region-end) t)
;;    (insert after)    
;;    (search-backward-regexp regx-match (region-end) t)
;;    (insert before)
;;    (search-forward-regexp regx-match (region-end) t)))))
          
 


 

(defun prop-region (&optional face beg end)
 (interactive)

 (insert
 (propertize
 (buffer-substring-no-properties
 (or beg (region-beginning))
 (or end (region-end)))
 'face
 (or face (select-face face)))))

 (global-unset-key (kbd "M-u") )
 (global-set-key (kbd "M-u") 'uni3/region)
 (global-unset-key (kbd "C-c p") )
 (global-set-key (kbd "C-c p") 'prop-region)


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