;;; typst-ts-embedding-lang-settings.el --- Embedding Languages Settings  -*- lexical-binding: t; -*-

;; Copyright (C) 2023-2025 The typst-ts-mode Project Contributors

;; This file is NOT part of GNU Emacs.
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; Functionality to embed other languages in typst documentation.

;;; Code:
(require 'treesit)
(require 'typst-ts-core)

;; Generated by `cargo run' (i.e. `src/main.rs')
;; We here use print expression to create hash table, see `(elisp) Creating Hash'
(defvar typst-ts-els-tag-lang-map
  #s(hash-table
     size 588
     test equal
     data
     ("txt" txt "asp" asp "asa" asp
      "actionscript" actionscript "as" actionscript "script editor" applescript
      "applescript" applescript "bat" bat "cmd" bat
      "build" build "c#" c-sharp "cs" c-sharp
      "csx" c-sharp "cxx" c++ "hpp" c++
      "inl" c++ "ipp" c++ "cc" c++
      "hh" c++ "hxx" c++ "cpp" c++
      "h++" c++ "c++" c++ "cp" c++
      "c" c "css.liquid" css "css.erb" css
      "css" css "edn" clojure "clojure" clojure
      "clj" clojure "cljc" clojure "cljs" clojure
      "d" d "di" d "diff" diff
      "patch" diff "erl" erlang "escript" erlang
      "erlang" erlang "hrl" erlang "emakefile" erlang
      "yaws" yaws "attributes" attributes ".gitattributes" attributes
      "gitattributes" attributes "merge_msg" commit_editmsg "commit_editmsg" commit_editmsg
      "tag_editmsg" commit_editmsg ".gitmodules" gitconfig "gitconfig" gitconfig
      ".gitconfig" gitconfig "gitignore" exclude "exclude" exclude
      ".gitignore" exclude ".git" .git "gitlog" gitlog
      "mailmap" .mailmap ".mailmap" .mailmap "git-rebase-todo" git-rebase-todo
      "go" go "gv" dot "dot" dot
      "jenkinsfile" groovy "groovy" groovy "gvy" groovy
      "gradle" groovy "html" html "shtml" html
      "htm" html "xhtml" html "haskell" haskell
      "hs" haskell "lhs" lhs "sublime-commands" json
      "sublime-menu" json "json" json "sublime-color-scheme" json
      "sublime-build" json "sublime-settings" json "sublime-completions" json
      "sublime-theme" json "ipynb" json "sublime-keymap" json
      "pipfile.lock" json "sublime-mousemap" json "sublime-macro" json
      "sublime-project" json "jsp" jsp "java" java
      "bsh" java "javadoc" javadoc "properties" properties
      "js" js "htc" js "javascript" js
      "bibtex" bibtex "bib" bibtex "latex" latex
      "ltx" latex "tex" tex "cls" tex
      "sty" tex "clisp" common-lisp "el" emacs-lisp
      "l" lisp "lsp" lisp "scm" lisp
      "ss" lisp "lisp" lisp "mud" lisp
      "fasl" lisp "cl" lisp "lua" lua
      "gnumakefile" makefile "mk" makefile "makefile.am" makefile
      "mak" makefile "makefile.in" makefile "make" makefile
      "makefile" makefile "ocamlmakefile" makefile "md" markdown
      "markdown" markdown "mdown" markdown "markdn" markdown
      "multimarkdown" multimarkdown "matlab" matlab "mli" ocaml
      "ocaml" ocaml "ml" ocaml "mll" ocamllex
      "ocamllex" ocamllex "mly" ocamlyacc "ocamlyacc" ocamlyacc
      "camlp4" camlp4 "mm" objective-c++ "objective-c++" objective-c++
      "h" objective-c "objective-c" objective-c "m" objective-c
      "php3" php "php7" php "phps" php
      "phpt" php "php4" php "php" php
      "phtml" php "php5" php "p" pascal
      "dpr" pascal "pascal" pascal "pas" pascal
      "pc" perl "t" perl "pm" perl
      "perl" perl "pod" perl "pmc" perl
      "pl" perl "python" python "wscript" python
      "pxi.in" python "snakefile" python "vpy" python
      "py" python "cpy" python "gyp" python
      "sconstruct" python "rpy" python "pxi" python
      "pyx.in" python "pyi" python "gypi" python
      "bazel" python "pyw" python "sconscript" python
      "pxd.in" python "py3" python "bzl" python
      "pyx" python "pxd" python "r" r
      "rprofile" r "rd" rd "rails" rails
      "rhtml" rails "erb" rails "html.erb" rails
      "js.erb" js.erb "haml" haml "sass" haml
      "builder" rxml "rxml" rxml "sql.erb" erbsql
      "erbsql" erbsql "re" re "rst" restructuredtext
      "rest" restructuredtext "restructuredtext" restructuredtext "gemfile" ruby
      "jbuilder" ruby "irbrc" ruby "prawn" ruby
      "rbx" ruby "gemspec" ruby "cheffile" ruby
      "config.ru" ruby "guardfile" ruby "podfile" ruby
      "rantfile" ruby "fastfile" ruby "capfile" ruby
      "vagrantfile" ruby "ruby" ruby "simplecov" ruby
      "scanfile" ruby "rjs" ruby "brewfile" ruby
      "rakefile" ruby "cgi" ruby "rabl" ruby
      "snapfile" ruby "appraisals" ruby "fcgi" ruby
      "appfile" ruby "deliverfile" ruby "berksfile" ruby
      "podspec" ruby "ruby.rail" ruby "rake" ruby
      "thorfile" ruby "rb" ruby "thor" ruby
      "rs" rust "rust" rust "dml" sql
      "ddl" sql "sql" sql "sbt" scala
      "scala" scala "sc" scala ".zprofile" bash
      ".textmate_init" bash "sh" bash ".zshenv" bash
      "ebuild" bash "eclass" bash ".bash_completions" bash
      ".zshrc" bash "pkgbuild" bash ".bash_profile" bash
      ".bash_functions" bash ".bash_login" bash ".bash_logout" bash
      "zsh" bash "ash" bash ".bashrc" bash
      "bash" bash ".bash_aliases" bash ".profile" bash
      ".zlogin" bash ".zlogout" bash ".bash_variables" bash
      "shell-unix-generic" shell-unix-generic "commands-builtin-shell-bash" commands-builtin-shell-bash "adp" adp
      "tcl" tcl "textile" textile "opml" xml
      "rng" xml "xsd" xml "xml" xml
      "rss" xml "svg" xml "xslt" xml
      "xaml" xml "tld" xml "dtml" xml
      "yaml" yaml "yml" yaml "sublime-syntax" yaml
      "awk" awk "ads" ada "ada" ada
      "gpr" ada "adb" ada ".htgroups" envvars
      ".htpasswd" envvars ".htaccess" envvars "htpasswd" envvars
      "envvars" envvars "htgroups" envvars "htaccess" envvars
      "asciidoc" adoc "adoc" adoc "ad" adoc
      "yasm" yasm "mac" yasm "nasm" yasm
      "asm" yasm "inc" yasm "h.in" h.in
      "h++.in" hh.in "hh.in" hh.in "hxx.in" hh.in
      "hpp.in" hh.in "cmake" cmake "cmakelists.txt" cmake
      "cmakecache" cmakecache "cmakecache.txt" cmakecache "cmakecommands" cmakecommands
      "csv" csv "tsv" csv "cabal" cabal
      "cakefile" coffeescript "coffee" coffeescript "coffee.erb" coffeescript
      "cson" coffeescript "coffeescript" coffeescript "cpuinfo" cpuinfo
      "tab" crontab "crontab" crontab "cron.d" crontab
      "cr" crystal "crystal" crystal "dart" dart
      "dockerfile" dockerfile ".env.example" dotenv ".env.production.local" dotenv
      ".env.default" dotenv "env" dotenv ".envrc" dotenv
      ".env.test" dotenv ".env" dotenv ".env.testing" dotenv
      ".env.dev" dotenv ".env.sample" dotenv ".env.prod" dotenv
      ".env.staging" dotenv ".env.defaults" dotenv ".env.production" dotenv
      ".env.local" dotenv "env.example" dotenv ".env.dist" dotenv
      ".env.dusk.local" dotenv "env.sample" dotenv ".env.development" dotenv
      ".env.test.local" dotenv "dotenv" dotenv ".flaskenv" dotenv
      ".env.development.local" dotenv "env.template" dotenv ".env.template" dotenv
      "elixir" elixir "ex" elixir "exs" elixir
      "html.eex" html.eex "html.leex" html.eex "elm" elm
      "msg" email "mboxz" email "eml" email
      "mbx" email "email" email "fsi" fs
      "f#" fs "fsx" fs "fish" fish
      "fpp" f "for" f "f" f
      "f77" f "f90" f90 "f08" f90
      "f95" f90 "f03" f90 "namelist" namelist
      "mtab" fstab "fstab" fstab "crypttab" fstab
      "fsh" glsl "vshader" glsl "vs" glsl
      "fshader" glsl "gshader" glsl "gsh" glsl
      "vsh" glsl "vert" glsl "task" glsl
      "comp" glsl "gs" glsl "geom" glsl
      "rahit" glsl "rmiss" glsl "fs" glsl
      "frag" glsl "rchit" glsl "glsl" glsl
      "tesc" glsl "tese" glsl "mesh" glsl
      "rint" glsl "rgen" glsl "rcall" glsl
      "graphql" graphql "graphqls" graphql "gql" graphql
      "groff" groff/troff "troff" groff/troff "4" groff/troff
      "9" groff/troff "1" groff/troff "2" groff/troff
      "7" groff/troff "6" groff/troff "3" groff/troff
      "groff/troff" groff/troff "5" groff/troff "8" groff/troff
      "group" group "twig" twig "html.twig" twig
      "hosts" hosts ".pylintrc" ini "desktop" ini
      ".editorconfig" ini ".gitlint" ini ".hgrc" ini
      "lng" ini "hgrc" ini "inf" ini
      "reg" ini ".coveragerc" ini "ini" ini
      "url" ini "cfg" ini "htm.j2" htm.j2
      "xml.j2" htm.j2 "html.j2" htm.j2 "xhtml.j2" htm.j2
      "jinja" jinja2 "jinja2" jinja2 "j2" jinja2
      "libsonnet" jsonnet "libjsonnet" jsonnet "jsonnet" jsonnet
      "jl" julia "julia" julia "kts" kotlin
      "kt" kotlin "kotlin" kotlin "less" less
      "css.less" less "ll" llvm "llvm" llvm
      "lean" lean "manpage" manpage "man" manpage
      "mediawikerpanel" mediawikerpanel "wikipedia" mediawiki "wiki" mediawiki
      "mediawiki" mediawiki "meminfo" meminfo "uwsgi_params" nginx
      "mime.types" nginx "nginx.conf" nginx "conf" nginx
      "conf.erb" nginx "fastcgi_params" nginx "nginx" nginx
      "scgi_params" nginx "nim" nim "nimble" nim
      "nims" nim "ninja" ninja "nix" nix
      "org" orgmode "orgmode" orgmode "passwd" passwd
      "protodevel" proto "proto" proto "pb.txt" pb.txt
      "prototxt" pb.txt "proto.text" pb.txt "pbtxt" pb.txt
      "textpb" pb.txt "epp" puppet "pp" puppet
      "puppet" puppet "purs" purescript "purescript" purescript
      "qml" qml "qmlproject" qml "rkt" racket
      "racket" racket "rego" rego "pip" requirements.txt
      "requirements.in" requirements.txt "requirements.txt" requirements.txt "resolv" resolv
      "resolv.conf" resolv "robot" robot "resource" robot
      "scss" scss "sig" sml "sml" sml
      "cm" sml "skim" slim "slim" slim
      "strace" strace "styl" stylus "stylus" stylus
      "solidity" solidity "sol" solidity "vy" vyper
      "vyper" vyper "jq" jq "svlt" svelte
      "svelte" svelte "swift" swift "sv" systemverilog
      "svh" systemverilog "systemverilog" systemverilog "vh" systemverilog
      "cargo.lock" toml "toml" toml "pipfile" toml
      "poetry.lock" toml "tml" toml "gopkg.lock" toml
      "pdm.lock" toml "tfstate" tfstate "tfvars" terraform
      "tf" terraform "hcl" terraform "terraform" terraform
      "todo.txt" todo.txt "done.txt" todo.txt "mts" typescript
      "ts" typescript "cts" typescript "typescript" typescript
      "typescriptreact" typescriptreact "tsx" typescriptreact "v" verilog
      "verilog" verilog ".vimrc" viml "_gvimrc" viml
      "gvimrc" viml "_vimrc" viml "vimrc" viml
      "viml" viml "vim" viml ".gvimrc" viml
      "vue" vue "zig" zig "plot" gnuplot
      "gnuplot" gnuplot "gpl" gnuplot "gp" gnuplot
      "gnu" gnuplot "plt" gnuplot "http" http
      "log" log "show-nonprintable" show-nonprintable "pub" authorized_keys
      "authorized_keys2" authorized_keys "authorized_keys" authorized_keys "known_hosts" known_hosts
      "known_hosts.old" known_hosts "ssh_config" ssh_config "sshd_config" sshd_config
      "syslog" syslog "varlink" varlink "typ" typst
      "typc" typst "typst" typst))
  "Raw block tag -> tree sitter language map.")


;; refer to markdown-get-lang-mode
(defun typst-ts-els-get-lang-mode (lang)
  "Return major mode that should be used for LANG.
LANG is a string, and the returned major mode is a symbol."
  (let ((lang-norm (downcase lang)))
    (cl-find-if
     (lambda (mode) (and mode (fboundp mode)))
     (list
      (and (treesit-language-available-p (intern lang-norm))
           (intern (concat lang-norm "-ts-mode")))
      (intern (concat lang-norm "-mode"))))))

;; refer to `markdown-fontify-code-block-natively'
(defun typst-ts-els-fontify-raw-block (lang-mode start end)
  "Fontify a raw block using traditional approach.
LANG-MODE START END."
  (let ((string (buffer-substring-no-properties start end))
        (modified (buffer-modified-p))
        (typst-doc-buffer (current-buffer)) pos next)
    (remove-text-properties start end '(face nil))
    (with-current-buffer
        (get-buffer-create
         (concat " *typst-raw_blck-fontification:" (symbol-name lang-mode)))
      ;; Make sure that modification hooks are not inhibited in
      ;; the org-src-fontification buffer in case we're called
      ;; from `jit-lock-function' (Bug#25132).
      (let ((inhibit-modification-hooks nil))
        (delete-region (point-min) (point-max))
        (insert string " ")) ;  so there's a final property change
      (unless (eq major-mode lang-mode) (funcall lang-mode))
      (font-lock-ensure)
      (setq pos (point-min))
      (while (setq next (next-single-property-change pos 'face))
        (let ((val (get-text-property pos 'face)))
          (when val
            (put-text-property
             (+ start (1- pos)) (1- (+ start next)) 'face
             val typst-doc-buffer)))
        (setq pos next)))
    (set-buffer-modified-p modified)))

(provide 'typst-ts-embedding-lang-settings)

;;; typst-ts-embedding-lang-settings.el ends here
