#-*- mode: org -*-
#+TITLE: Emacs Setup for the TCL/TK Programming Language
#+AUTHOR: Volker Edelmann
#+EMAIL:  vedelmann@gmx.de
#+STARTUP: indent
#+OPTIONS:  toc:nil
#+OPTIONS:   ^:{}

#+begin_src emacs-lisp
  ;; -*- coding: utf-8; lexical-binding: t -*-
#+end_src

* TCL/TK
Category: Others

A TCL program follows very simple grammatical rules. It is very easy to
write a parser.
There is no language-server or tree-sitter grammar available as there seems to be no
need for it.a TCL is considered a homoiconic language.

** REPL

** Selections

#+begin_src emacs-lisp
  (use-package expand-region
    :config
    ;; patch expand-region for TCL
    (defun my/add-tcl-mode-expansions ()
      (make-variable-buffer-local 'er/try-expand-list)
      (setq er/try-expand-list (append
				er/try-expand-list
				'(er/mark-word
				  er/mark-defun
				  er/mark-paragraph)
				)
	    )
      )
    (er/enable-mode-expansions 'tcl-mode 'er/add-tcl-mode-expansions)
    )
#+end_src

** Folding

Best option is to use the built-in hideshow package.
I would like the namespaces to be left unfolded if hs-fold-all is executed. 

#+begin_src emacs-lisp
  (use-package hideshow
    :custom
    (hs-isearch-open t)
    )
#+end_src

** Static Checker
flycheck uses nagelfar. Put it on the PATH.

#+begin_src emacs-lisp
  (add-to-list 'display-buffer-alist
	       `(,(rx bos "*Flycheck errors*" eos)
		 (display-buffer-reuse-window
		  display-buffer-in-side-window)
		 (side            . bottom)
		 (reusable-frames . visible)
		 (window-height   . 0.33)))
#+end_src

  
** TCL/TK
#+begin_src emacs-lisp
  (use-package tcl
    :mode (("\\.tcl\\'" . tcl-mode)
           ("\\.tcons\\'" . tcl-mode)
           ("\\.svcf\\'" . tcl-mode)
           ("\\.exp\\'" . tcl-mode))
    :bind (
  	 :map tcl-mode-map
           ("C-c C-z"      . inferior-tcl)  	
  	 ("C-c c"        . consult-flycheck)
  	 ("<f9>"         . consult-flycheck)
  	 ("C-="          . yas-insert-snippet)
           ("M-SPC"        . completion-at-point)
           ("<f4>"         . complete-symbol)
  	 ("<f5>"         . mark-paragraph)
           ("C-<f5>"       . mark-defun)
  	 ("M-<f5>"       . mark-whole-buffer)
           ("<f12>"        . indent-paragraph)
           ("C-<f12>"      . indent-defun)
  	 ("M-<f12>"      . indent-buffer)
           ("C-<return>"   . my/tcl-eval-region-or-line) 
           ("C-S-<return>" . my/tcl-eval-defun)
  	 ("C-M-<return>" . my/tcl-eval-buffer)
           ("C-c C-t"      . nil)
           )
    :init
    (env-setup "tcl")

    (defun my/tcl-eval-region-or-line ()
      (interactive)
      (if (region-active-p)
    	(progn
            (tcl-eval-region (region-beginning) (region-end))
    	  (deactivate-mark)
    	  )
        (tcl-eval-region (progn
                           (beginning-of-line) (point))
                         (progn
                           (end-of-line) (point))
                         )
        )
      )           
    
    (defun my/tcl-eval-defun ()
      (interactive)
      (message "buffer")
      (mark-defun)
      (my/tcl-eval-region-or-line)
      ) 
    (defun my/tcl-eval-buffer ()
      (interactive)
      (message "buffer")
      (tcl-eval-region (point-min) (point-max))
      )
    (defun my/tcl-keyword-completion ()
      "This is the function to be used for the hook `completion-at-point-functions'."
      (interactive)
      (let ((bds (bounds-of-thing-at-point 'symbol))
  	  start
  	  end)
        (setq start (car bds))
        (setq end (cdr bds))
        (if start
        (list start end tcl-keyword-list . nil)
  	nil)
  	  ))
    
    (defun my/tcl-mode-customization ()
      "My customization for 'tcl-mode'."
      (setq-local completion-at-point-functions
  		(list 'tempel-complete
  		      'my/tcl-keyword-completion
  		              'cape-dabbrev
  		      ))
      )
    
    (defun my/outline-tcl ()
      "Fold only definitions for TCL buffers."
      (setq outline-regexp
            (rx (or
                 ;; Definitions
                 (group (group (* space)) bow (or "proc" "namespace") eow)

                 ;; Decorators
                 (group (group (* space)) "@"))))
      )
    (defun my/eglot-tcl-setup ()
      (with-eval-after-load 'eglot
        (add-to-list 'eglot-server-programs '(tcl-mode . ("/opt/volker/projects/tcl_lsp/lsp/lsp.tcl"))))
      (setq eglot-events-buffer-config (list :size 2000000 :format `lisp))
      (setq eglot-connect-timeout nil)
      )

    :config
    (setq tcl-indent-level 4
          tcl-continued-indent-level 8)

    (setq tcl-interpreters (list "tclsh" "wish" "jimsh"))
    (setq tcl-application (nth 1 tcl-interpreters))

    (setq flycheck-check-syntax-automatically '(save mode-enabled))
    (setq tcl-help-directory-list '("/usr/lib/tclx8.6/help"))

    :hook
    (tcl-mode . yas-minor-mode)
    (tcl-mode . flycheck-mode)
    (tcl-mode . hs-minor-mode)
    (tcl-mode . outline-minor-mode)

  ;;    (tcl-mode . my/eglot-tcl-setup)
    (tcl-mode . my/tcl-mode-customization)
    (tcl-mode . my/outline-tcl)
    (tcl-mode . electric-pair-mode)
    (tcl-mode . electric-indent-mode)
    )

 #+end_src


** 

* TODO Expect