Skip to content

Instantly share code, notes, and snippets.

@DeLaGuardo
Last active February 28, 2024 01:27
Show Gist options
  • Save DeLaGuardo/fe1f3d9397d6ef7468460d54d5601156 to your computer and use it in GitHub Desktop.
Save DeLaGuardo/fe1f3d9397d6ef7468460d54d5601156 to your computer and use it in GitHub Desktop.
Snippet for support ligatures from PragmataPro font in Emacs
;; Enable ligatures without prettify-symbols
(provide 'add-pragmatapro-symbol-keywords)
(defconst pragmatapro-fontlock-keywords-alist
(mapcar (lambda (regex-char-pair)
`(,(car regex-char-pair)
(0 (prog1 ()
(compose-region (match-beginning 1)
(match-end 1)
,(concat (list ?\C-i)
(list (decode-char 'ucs (cadr regex-char-pair)))))))))
'(("\\(\\[ERROR\\]\\)" #XE380)
("\\(\\[DEBUG\\]\\)" #XE381)
("\\(\\[INFO\\]\\)" #XE382)
("\\(\\[WARN\\]\\)" #XE383)
("\\(\\[WARNING\\]\\)" #XE384)
("\\(\\[ERR\\]\\)" #XE385)
("\\(\\[FATAL\\]\\)" #XE386)
("\\(\\[TRACE\\]\\)" #XE387)
("\\(!!\\)" #XE720)
("\\(!=\\)" #XE721)
("\\(!==\\)" #XE722)
("\\(!!!\\)" #XE723)
("\\(!≡\\)" #XE724)
("\\(!≡≡\\)" #XE725)
("[^<]\\(!>\\)" #XE726)
("\\(#(\\)" #XE740)
("\\(#_\\)" #XE741)
("\\(#{\\)" #XE742)
("\\(#\\?\\)" #XE743)
("[^<]\\(#>\\)" #XE744)
("\\(##\\)" #XE745)
("\\(%=\\)" #XE750)
("[^<]\\(%>\\)" #XE751)
("\\(&%\\)" #XE760)
("\\(&&\\)" #XE761)
("\\(&\\*\\)" #XE762)
("\\(&\\+\\)" #XE763)
("\\(&-\\)" #XE764)
("\\(&/\\)" #XE765)
("\\(&=\\)" #XE766)
("\\(&&&\\)" #XE767)
("[^<]\\(&>\\)" #XE768)
("\\(\\*\\*\\*\\)" #XE780)
("\\(\\*=\\)" #XE781)
("\\(\\*/\\)" #XE782)
("[^<]\\(\\*>\\)" #XE783)
("\\(\\+\\+\\)" #XE790)
("\\(\\+\\+\\+\\)" #XE791)
("[^\\+]\\(\\+=\\)" #XE792)
("[^<]\\(\\+>\\)" #XE793)
("\\(\\+\\+=\\)" #XE794)
("\\(--\\)" #XE7A0)
("[^-]\\(-<\\)" #XE7A1)
("\\(-<<\\)" #XE7A2)
("\\(-=\\)" #XE7A3)
("[^|]\\(->\\)" #XE7A4)
("[^|]\\(->>\\)" #XE7A5)
("\\(---\\)" #XE7A6)
("\\(-->\\)" #XE7A7)
("\\(-\\+-\\)" #XE7A8)
("\\(-\\\\/\\)" #XE7A9)
("[^\\^]\\(\\.\\.\\)" #XE7B0)
("\\(\\.\\.\\.\\)" #XE7B1)
("\\(\\.\\.<\\)" #XE7B2)
("\\(\\.>\\)" #XE7B3)
("\\(\\.~\\)" #XE7B4)
("\\(\\.=\\)" #XE7B5)
("\\(/\\*\\)" #XE7C0)
("\\(//\\)" #XE7C1)
("[^<]\\(/>\\)" #XE7C2)
("[^=]\\(/=\\)" #XE7C3)
("\\(/==\\)" #XE7C4)
("\\(///\\)" #XE7C5)
("\\(/\\*\\*\\)" #XE7C6)
("\\(::\\)" #XE7D0)
("\\(:=\\)" #XE7D1)
("[^≡]\\(:≡\\)" #XE7D2)
("\\(:>\\)" #XE7D3)
("\\(:=>\\)" #XE7D4)
("\\(<\\*\\)" #XE7E1)
("\\(<\\*>\\)" #XE7E2)
("[^<]\\(<-\\)" #XE7E4)
("[^-]\\(<<\\)" #XE7E5)
("\\(<<<\\)" #XE7E6)
("\\(<<=\\)" #XE7E7)
("[^<]\\(<=\\)" #XE7E8)
("\\(<=>\\)" #XE7E9)
("\\(<>\\)" #XE7EA)
("\\(<<-\\)" #XE7EC)
("\\(<|\\)" #XE7ED)
("\\(<|>\\)" #XE7EB)
("\\(<=<\\)" #XE7EE)
("[^<]\\(<~\\)" #XE7EF)
("\\(<~~\\)" #XE7F0)
("\\(<<~\\)" #XE7F1)
("\\(<\\$\\)" #XE7F2)
("\\(<\\$>\\)" #XE7E0)
("\\(<\\+\\)" #XE7F3)
("\\(<\\+>\\)" #XE7E3)
("\\(<~>\\)" #XE800)
("\\(<\\*\\*>\\)" #XE801)
("\\(<<\\^\\)" #XE802)
("\\(<!\\)" #XE803)
("\\(<!>\\)" #XE7F4)
("\\(<@\\)" #XE804)
("\\(<#\\)" #XE805)
("\\(<#>\\)" #XE7F6)
("\\(<%\\)" #XE806)
("\\(<%>\\)" #XE7F7)
("[^<]\\(<\\^\\)" #XE807)
("\\(<&\\)" #XE808)
("\\(<&>\\)" #XE7F9)
("\\(<\\?\\)" #XE809)
("\\(<\\.\\)" #XE80A)
("\\(<\\.>\\)" #XE7FB)
("\\(</\\)" #XE80B)
("\\(</>\\)" #XE7FC)
("\\(<\\\\\\)" #XE80C)
("\\(<\"\\)" #XE80D)
("\\(<\">\\)" #XE7FE)
("\\(<:\\)" #XE80E)
("\\(<:>\\)" #XE7FF)
("\\(<->\\)" #XE80F)
("\\(<!--\\)" #XE810)
("\\(<--\\)" #XE811)
("\\(<~<\\)" #XE812)
("\\(<==>\\)" #XE813)
("\\(==<\\)" #XE820)
("[^/!<=>]\\(==\\)[^><=]" #XE821)
("\\(===\\)" #XE822)
("[^<]\\(==>\\)" #XE823)
("[^=:<]\\(=>\\)" #XE824)
("\\(=~\\)" #XE825)
("\\(=>>\\)" #XE826)
("\\(=/=\\)" #XE827)
("[^!]\\(≡≡\\)" #XE830)
("\\(≡≡≡\\)" #XE831)
("\\(≡:≡\\)" #XE832)
("[^>]\\(>-\\)" #XE840)
("\\(>=\\)" #XE841)
("[^=-]\\(>>\\)" #XE842)
("\\(>>-\\)" #XE843)
("\\(>==\\)" #XE844)
("\\(>>>\\)" #XE845)
("\\(>=>\\)" #XE846)
("\\(>>\\^\\)" #XE847)
("\\(\\?\\?\\)" #XE860)
("\\(\\?~\\)" #XE861)
("\\(\\?=\\)" #XE862)
("\\(\\?>\\)" #XE863)
("\\(<\\?>\\)" #XE7FA)
("\\(\\?\\?\\?\\)" #XE864)
("\\(\\^=\\)" #XE868)
("\\(\\^\\.\\)" #XE869)
("\\(\\^\\?\\)" #XE86A)
("\\(\\^\\.\\.\\)" #XE86B)
("\\(\\^<<\\)" #XE86C)
("\\(\\^>\\)" #XE86E)
("\\(\\^>>\\)" #XE86D)
("\\(<\\^>\\)" #XE7F8)
("[^\\\\]\\(\\\\\\\\\\)" #XE870)
("[^<]\\(\\\\>\\)" #XE871)
("\\(<\\\\>\\)" #XE7FD)
("\\(\\\\/-\\)" #XE872)
("\\(@>\\)" #XE877)
("\\(<@>\\)" #XE7F5)
("\\(|=\\)" #XE880)
("\\(||\\)" #XE881)
("[^<]\\(|>\\)" #XE882)
("\\(|||\\)" #XE883)
("\\(|\\+|\\)" #XE884)
("\\(|->\\)" #XE885)
("\\(|-->\\)" #XE886)
("\\(|=>\\)" #XE887)
("\\(|==>\\)" #XE888)
("\\(~=\\)" #XE890)
("[^~<]\\(~>\\)" #XE891)
("\\(~~>\\)" #XE892)
("\\(~>>\\)" #XE893)
("[^<]\\(\">\\)" #XE8B0))))
(defun add-pragmatapro-symbol-keywords ()
(font-lock-add-keywords nil pragmatapro-fontlock-keywords-alist))
(add-hook 'prog-mode-hook
#'add-pragmatapro-symbol-keywords)
;; For emacs25
(setq prettify-symbols-unprettify-at-point 'right-edge)
(defconst pragmatapro-prettify-symbols-alist
(mapcar (lambda (s)
`(,(car s)
.
,(vconcat
(apply 'vconcat (make-list (- (length (car s)) 1) (vector (decode-char 'ucs #X0020) '(Br . Bl))))
(vector (decode-char 'ucs (cadr s))))))
'(("[ERROR]" #XE380)
("[DEBUG]" #XE381)
("[INFO]" #XE382)
("[WARN]" #XE383)
("[WARNING]" #XE384)
("[ERR]" #XE385)
("[FATAL]" #XE386)
("[TRACE]" #XE387)
("!!" #XE720)
("!=" #XE721)
("!==" #XE722)
("!!!" #XE723)
("!≡" #XE724)
("!≡≡" #XE725)
("!>" #XE726)
("#(" #XE740)
("#_" #XE741)
("#{" #XE742)
("#?" #XE743)
("#>" #XE744)
("##" #XE745)
("%=" #XE750)
("%>" #XE751)
("&%" #XE760)
("&&" #XE761)
("&*" #XE762)
("&+" #XE763)
("&-" #XE764)
("&/" #XE765)
("&=" #XE766)
("&&&" #XE767)
("&>" #XE768)
("***" #XE780)
("*=" #XE781)
("*/" #XE782)
("*>" #XE783)
("++" #XE790)
("+++" #XE791)
("+=" #XE792)
("+>" #XE793)
("++=" #XE794)
("--" #XE7A0)
("-<" #XE7A1)
("-<<" #XE7A2)
("-=" #XE7A3)
("->" #XE7A4)
("->>" #XE7A5)
("---" #XE7A6)
("-->" #XE7A7)
("-+-" #XE7A8)
("-\\/" #XE7A9)
(".." #XE7B0)
("..." #XE7B1)
("..<" #XE7B2)
(".>" #XE7B3)
(".~" #XE7B4)
(".=" #XE7B5)
("/*" #XE7C0)
("//" #XE7C1)
("/>" #XE7C2)
("/=" #XE7C3)
("/==" #XE7C4)
("///" #XE7C5)
("/**" #XE7C6)
("::" #XE7D0)
(":=" #XE7D1)
(":≡" #XE7D2)
(":>" #XE7D3)
(":=>" #XE7D4)
("<$>" #XE7E0)
("<*" #XE7E1)
("<*>" #XE7E2)
("<+>" #XE7E3)
("<-" #XE7E4)
("<<" #XE7E5)
("<<<" #XE7E6)
("<<=" #XE7E7)
("<=" #XE7E8)
("<=>" #XE7E9)
("<>" #XE7EA)
("<|>" #XE7EB)
("<<-" #XE7EC)
("<|" #XE7ED)
("<=<" #XE7EE)
("<~" #XE7EF)
("<~~" #XE7F0)
("<<~" #XE7F1)
("<$" #XE7F2)
("<+" #XE7F3)
("<!>" #XE7F4)
("<@>" #XE7F5)
("<#>" #XE7F6)
("<%>" #XE7F7)
("<^>" #XE7F8)
("<&>" #XE7F9)
("<?>" #XE7FA)
("<.>" #XE7FB)
("</>" #XE7FC)
("<\\>" #XE7FD)
("<\">" #XE7FE)
("<:>" #XE7FF)
("<~>" #XE800)
("<**>" #XE801)
("<<^" #XE802)
("<!" #XE803)
("<@" #XE804)
("<#" #XE805)
("<%" #XE806)
("<^" #XE807)
("<&" #XE808)
("<?" #XE809)
("<." #XE80A)
("</" #XE80B)
("<\\" #XE80C)
("<\"" #XE80D)
("<:" #XE80E)
("<->" #XE80F)
("<!--" #XE810)
("<--" #XE811)
("<~<" #XE812)
("<==>" #XE813)
("==<" #XE820)
("==" #XE821)
("===" #XE822)
("==>" #XE823)
("=>" #XE824)
("=~" #XE825)
("=>>" #XE826)
("=/=" #XE827)
("≡≡" #XE830)
("≡≡≡" #XE831)
("≡:≡" #XE832)
(">-" #XE840)
(">=" #XE841)
(">>" #XE842)
(">>-" #XE843)
(">==" #XE844)
(">>>" #XE845)
(">=>" #XE846)
(">>^" #XE847)
("??" #XE860)
("?~" #XE861)
("?=" #XE862)
("?>" #XE863)
("???" #XE864)
("^=" #XE868)
("^." #XE869)
("^?" #XE86A)
("^.." #XE86B)
("^<<" #XE86C)
("^>>" #XE86D)
("^>" #XE86E)
("\\\\" #XE870)
("\\>" #XE871)
("\\/-" #XE872)
("@>" #XE877)
("|=" #XE880)
("||" #XE881)
("|>" #XE882)
("|||" #XE883)
("|+|" #XE884)
("|->" #XE885)
("|-->" #XE886)
("|=>" #XE887)
("|==>" #XE888)
("~=" #XE890)
("~>" #XE891)
("~~>" #XE892)
("~>>" #XE893)
("\">" #XE8B0))))
(defun add-pragmatapro-prettify-symbols-alist ()
(dolist (alias pragmatapro-prettify-symbols-alist)
(push alias prettify-symbols-alist)))
(add-hook 'prog-mode-hook
#'add-pragmatapro-prettify-symbols-alist)
(global-prettify-symbols-mode +1)
;; All ligatures (for testing)
;; [ERROR]
;; [DEBUG]
;; [INFO]
;; [WARN]
;; [WARNING]
;; [ERR]
;; [FATAL]
;; [TRACE]
;; !!
;; !=
;; !==
;; !!!
;; !≡
;; !≡≡
;; !>
;; #(
;; #_
;; #{
;; #?
;; #>
;; ##
;; %=
;; %>
;; &%
;; &&
;; &*
;; &+
;; &-
;; &/
;; &=
;; &&&
;; &>
;; ***
;; *=
;; */
;; *>
;; ++
;; +++
;; +=
;; +>
;; ++=
;; --
;; -<
;; -<<
;; -=
;; ->
;; ->>
;; ---
;; -->
;; -+-
;; -\/
;; ..
;; ...
;; ..<
;; .>
;; .~
;; .=
;; /*
;; //
;; />
;; /=
;; /==
;; ///
;; /**
;; ::
;; :=
;; :≡
;; :>
;; :=>
;; <$>
;; <*
;; <*>
;; <+>
;; <-
;; <<
;; <<<
;; <<=
;; <=
;; <=>
;; <>
;; <|>
;; <<-
;; <|
;; <=<
;; <~
;; <~~
;; <<~
;; <$
;; <+
;; <!>
;; <@>
;; <#>
;; <%>
;; <^>
;; <&>
;; <?>
;; <.>
;; </>
;; <\>
;; <">
;; <:>
;; <~>
;; <**>
;; <<^
;; <!
;; <@
;; <#
;; <%
;; <^
;; <&
;; <?
;; <.
;; </
;; <\
;; <"
;; <:
;; <->
;; <!--
;; <--
;; <~<
;; <==>
;; ==<
;; ==
;; ===
;; ==>
;; =>
;; =~
;; =>>
;; =/=
;; ≡≡
;; ≡≡≡
;; ≡:≡
;; >-
;; >=
;; >>
;; >>-
;; >==
;; >>>
;; >=>
;; >>^
;; ??
;; ?~
;; ?=
;; ?>
;; ???
;; ^=
;; ^.
;; ^?
;; ^..
;; ^<<
;; ^>>
;; ^>
;; \\
;; \>
;; \/-
;; @>
;; |=
;; ||
;; |>
;; |||
;; |+|
;; |->
;; |-->
;; |=>
;; |==>
;; ~=
;; ~>
;; ~~>
;; ~>>
;; ">
@DeLaGuardo
Copy link
Author

@thegeorgeous Can you provide more information about your troubles?
Also please take a look at another solution that i just added to this gist. It use font-locking mechanism integrated into emacs instead of prettify-symbols.

@OkanEsen
Copy link

OkanEsen commented Jun 2, 2017

Here's the modified version for the 0.825 release:

;; For emacs25
(setq prettify-symbols-unprettify-at-point 'right-edge)

(defconst pragmatapro-prettify-symbols-alist
  (mapcar (lambda (s)
            `(,(car s)
              .
              ,(vconcat
                (apply 'vconcat (make-list (- (length (car s)) 1) (vector (decode-char 'ucs #X0020) '(Br . Bl))))
                (vector (decode-char 'ucs (cadr s))))))
          '(("[ERROR]"   #XE380)
            ("[DEBUG]"   #XE381)
            ("[INFO]"    #XE382)
            ("[WARN]"    #XE383)
            ("[WARNING]" #XE384)
            ("[ERR]"     #XE385)
            ("[FATAL]"   #XE386)
            ("[TRACE]"   #XE387)
            ("[FIXME]"   #XE388)
            ("[TODO]"    #XE389)
            ("[BUG]"     #XE38A)
            ("[NOTE]"    #XE38B)
            ("[HACK]"    #XE38C)
            ("[MARK]"    #XE38D)
            ("!!"        #XE900)
            ("!="        #XE901)
            ("!=="       #XE902)
            ("!!!"       #XE903)
            ("!≡"        #XE904)
            ("!≡≡"       #XE905)
            ("!>"        #XE906)
            ("#("        #XE920)
            ("#_"        #XE921)
            ("#{"        #XE922)
            ("#?"        #XE923)
            ("#>"        #XE924)
            ("##"        #XE925)
            ("%="        #XE930)
            ("%>"        #XE931)
            ("<~"        #XE932)
            ("&%"        #XE940)
            ("&&"        #XE941)
            ("&*"        #XE942)
            ("&+"        #XE943)
            ("&-"        #XE944)
            ("&/"        #XE945)
            ("&="        #XE946)
            ("&&&"       #XE947)
            ("&>"        #XE948)
            ("***"       #XE960)
            ("*="        #XE961)
            ("*/"        #XE962)
            ("*>"        #XE963)
            ("++"        #XE970)
            ("+++"       #XE971)
            ("+="        #XE972)
            ("+>"        #XE973)
            ("++="       #XE974)
            ("--"        #XE980)
            ("-<"        #XE981)
            ("-<<"       #XE982)
            ("-="        #XE983)
            ("->"        #XE984)
            ("->>"       #XE985)
            ("---"       #XE986)
            ("-->"       #XE987)
            ("-+-"       #XE988)
            ("-\\/"      #XE989)
            (".."        #XE990)
            ("..."       #XE991)
            ("..<"       #XE992)
            (".>"        #XE993)
            (".~"        #XE994)
            (".="        #XE995)
            ("/*"        #XE9A0)
            ("//"        #XE9A1)
            ("/>"        #XE9A2)
            ("/="        #XE9A3)
            ("/=="       #XE9A4)
            ("///"       #XE9A5)
            ("/**"       #XE9A6)
            ("::"        #XE9B0)
            (":="        #XE9B1)
            (":≡"        #XE9B2)
            (":>"        #XE9B3)
            (":=>"       #XE9B4)
            (":("        #XE9B5)
            (":-("       #XE9B6)
            (":)"        #XE9B7)
            (":-)"       #XE9B8)
            (":/"        #XE9B9)
            (":\\"       #XE9BA)
            (":3"        #XE9BB)
            (":D"        #XE9BC)
            (":P"        #XE9BD)
            (":>:"       #XE9BE)
            (":<:"       #XE9BF)
            ("<$>"       #XE9C0)
            ("<*"        #XE9C1)
            ("<*>"       #XE9C2)
            ("<+>"       #XE9C3)
            ("<-"        #XE9C4)
            ("<<"        #XE9C5)
            ("<<<"       #XE9C6)
            ("<<="       #XE9C7)
            ("<="        #XE9C8)
            ("<=>"       #XE9C9)
            ("<>"        #XE9CA)
            ("<|>"       #XE9CB)
            ("<<-"       #XE9CC)
            ("<|"        #XE9CD)
            ("<=<"       #XE9CE)
            ("<~"        #XE9CF)
            ("<~~"       #XE9D0)
            ("<<~"       #XE9D1)
            ("<$"        #XE9D2)
            ("<+"        #XE9D3)
            ("<!>"       #XE9D4)
            ("<@>"       #XE9D5)
            ("<#>"       #XE9D6)
            ("<%>"       #XE9D7)
            ("<^>"       #XE9D8)
            ("<&>"       #XE9D9)
            ("<?>"       #XE9DA)
            ("<.>"       #XE9DB)
            ("</>"       #XE9DC)
            ("<\\>"      #XE9DD)
            ("<\">"      #XE9DE)
            ("<:>"       #XE9DF)
            ("<~>"       #XE9E0)
            ("<**>"      #XE9E1)
            ("<<^"       #XE9E2)
            ("<!"        #XE9E3)
            ("<@"        #XE9E4)
            ("<#"        #XE9E5)
            ("<%"        #XE9E6)
            ("<^"        #XE9E7)
            ("<&"        #XE9E8)
            ("<?"        #XE9E9)
            ("<."        #XE9EA)
            ("</"        #XE9EB)
            ("<\\"       #XE9EC)
            ("<\""       #XE9ED)
            ("<:"        #XE9EE)
            ("<->"       #XE9EF)
            ("<!--"      #XE9F0)
            ("<--"       #XE9F1)
            ("<~<"       #XE9F2)
            ("<==>"      #XE9F3)
            ("==<"       #XEA00)
            ("=="        #XEA01)
            ("==="       #XEA02)
            ("==>"       #XEA03)
            ("=>"        #XEA04)
            ("=~"        #XEA05)
            ("=>>"       #XEA06)
            ("=/="       #XEA07)
            ("≡≡"        #XEA10)
            ("≡≡≡"       #XEA11)
            ("≡:≡"       #XEA12)
            (">-"        #XEA20)
            (">="        #XEA21)
            (">>"        #XEA22)
            (">>-"       #XEA23)
            (">=="       #XEA24)
            (">>>"       #XEA25)
            (">=>"       #XEA26)
            (">>^"       #XEA27)
            ("??"        #XEA40)
            ("?~"        #XEA41)
            ("?="        #XEA42)
            ("?>"        #XEA43)
            ("???"       #XEA44)
            ("^="        #XEA48)
            ("^."        #XEA49)
            ("^?"        #XEA4A)
            ("^.."       #XEA4B)
            ("^<<"       #XEA4C)
            ("^>>"       #XEA4D)
            ("^>"        #XEA4E)
            ("\\\\"      #XEA50)
            ("\\>"       #XEA51)
            ("\\/-"      #XEA52)
            ("@>"        #XEA57)
            ("|="        #XEA60)
            ("||"        #XEA61)
            ("|>"        #XEA62)
            ("|||"       #XEA63)
            ("|+|"       #XEA64)
            ("|->"       #XEA65)
            ("|-->"      #XEA66)
            ("|=>"       #XEA67)
            ("|==>"      #XEA68)
            ("~="        #XEA70)
            ("~>"        #XEA71)
            ("~~>"       #XEA72)
            ("~>>"       #XEA73)
            ("\">"       #XEA90))))

(defun add-pragmatapro-prettify-symbols-alist ()
  (dolist (alias pragmatapro-prettify-symbols-alist)
    (push alias prettify-symbols-alist)))

(add-hook 'prog-mode-hook
          #'add-pragmatapro-prettify-symbols-alist)

(global-prettify-symbols-mode +1)

@x-ji
Copy link

x-ji commented Apr 22, 2018

@OkanEsen Thanks for the update. Apparently the mappings have changed for version 0.825 and the original gist doesn't work anymore. The only annoyance I have is that when I move the cursor onto the ligature it reverts back to separate characters. Guess one can't do anything about that for now then.

@i-am-the-slime
Copy link

@x-ji That's intentional as far as I know. This option turns this on: (setq prettify-symbols-unprettify-at-point 'right-edge).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment