0

I am using pine-script-mode with a 4 space TAB. Here is an inner block of an if statement that is already aligned. How can I prevent adding a TAB char (or 4 space chars) when I press TAB?

pine file:

if x == 1
    true

Here when cursor is at the beginning of the true line and I press TAB it adds 4 spaces. Instead, since it is already aligned I want it to do nothing.


basic emacs config file:

(require 'package)
(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/"))
(package-initialize)
(fset 'yes-or-no-p 'y-or-n-p)

(use-package pine-script-mode
  :ensure t
  :pin melpa-stable
  :mode (("\\.pine" . pine-script-mode)))

(defun pine-custom-settings ()
  (setq indent-tabs-mode nil)
  (setq tab-width 4))

(defun c/pinescript-indent ()
  "Just do dumb indentation rather than emacs' relative indentation."
  (setq indent-tabs-mode nil)
  (setq tab-width 4)  ; this can be omitted if standard-indent is 4
  (setq indent-line-function 'insert-tab))

(add-to-list 'indent-line-ignored-functions 'insert-tab)
(add-hook 'pine-script-mode-hook 'c/pinescript-indent)

1 Answer 1

1
+50

I think with the below setup you get close to what you want. A caveat is that pine-script-indent-line doesn't work properly with electric-indent-mode, so it is disabled. I think to have an indent function that plays nice with that mode one needs to make it properly aware of keywords like if, else, for, etc. I also added pine-script-backtab since otherwise using pine-script-indent-line is a bit cumbersome.

(defun pine-script-indent-line ()
  "Set indentation based on indentation of previous line."
  (interactive)
  (let ((cpos (current-column))
    (col (current-indentation))
    (pcol (save-excursion (previous-line)(current-indentation))))
    (cond
     ((< col pcol) 
      (indent-line-to pcol))
     ((< col (+ pcol tab-width))
      (indent-line-to (+ pcol tab-width)))
     (t
      (back-to-indentation)
      (delete-region (point) (- (point) (- col (+ pcol tab-width))))))))

(defun pine-script-backtab ()
  (interactive)
  (indent-line-to 
   (max 0 (- (current-indentation) tab-width))))

(defun c/pinescript-indent ()
  (setq indent-tabs-mode nil)
  (setq tab-width 4)
  (setq indent-line-function 'pine-script-indent-line)
  (electric-indent-mode -1)
  (local-set-key [backtab] 'pine-script-backtab))

(add-hook 'pine-script-mode-hook 'c/pinescript-indent)

Edit: Below is an attempt at a better indent function, which also almost works with electric-indent-mode:

(defcustom pine-script-indent-pattern "\\(if \\|else[ \n]\\|for \\)"
  "Regex pattern after which to add indentation.")

(defun pine-script-indent-line ()
  "Set indentation based on indentation of previous line."
  (interactive)
  (let ((ccol (current-indentation))
        pcol indp tcol)
    (save-excursion
      (beginning-of-line-text 0)
      (setq pcol (current-column))
      (setq indp (looking-at-p pine-script-indent-pattern))
      (setq tcol (+ pcol (if indp tab-width 0))))
    (if (equal ccol tcol)
      (when (< (current-column) tcol)
        (back-to-indentation))
     (indent-line-to tcol))))
6
  • Seems like Set indentation based on indentation of previous line. approach does not work properly when there is multiple lines under if statement. For example for if x == 1 line_1 = 10 line_2 = 20 additional tab is added before second line line_2 = 20 // it is also possible to prevent that as well?
    – alper
    Commented Jan 4, 2023 at 10:53
  • It is possible, but then how would you add a tab in the cases where you actually want a tab? I only know about pine-script syntax from the image in the Github repo you linked, but from that it looks like one would want further indentation quite often, e.g. after a nested if or for, so again one would have to make the script know about all keywords/syntax structures after which there should be extra indentation (maybe they are not too many?). On the other hand, indenting more than one level compared to the previous one seems never allowed so that is easy to implement.
    – orgtre
    Commented Jan 4, 2023 at 13:01
  • Inside if or else if block indenting one level would be enough for the complete block. I think there is only if , else if and else. In python-mode this issue was handled but I was not able to make it what was working in python mode into pine-script. Indentation based on indentation of previous line is not helpful since there could be multiple lines in a condition block. I can ask new question related to this related to handle indention multiple lines for the if block.
    – alper
    Commented Jan 4, 2023 at 13:24
  • I edited the response with a version that tries to account for some keywords, but I think to do this properly takes more time.
    – orgtre
    Commented Jan 4, 2023 at 13:54
  • 1
    Ok, I edited it to move when there is nothing to do and point is before beginning of text (like in lisp mode). If you also want it to move when in text, remove the (when (< (current-column) tcol) part and its closing parenthesis.
    – orgtre
    Commented Jan 4, 2023 at 14:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.