0

How can i get current programming language at current cursor. For example, if my cursor is inside script tag, then it should return js or javascript and if it is inside style tag, then it should be css and if it is outside both of this tag, then it should be inside html so it should also return html.

<html>
    <script>
    ...
    </script>

    <style>
    ...
    </style>
</html>
  • What do you want to do after getting the language at point? – xuchunyang May 30 at 11:02
  • @xuchunyang, I want to enable emmet only inside html or css block not js or another stuff. I know it might be archive using web-mode as mention in the answer but I don't really use web-mode but another mode instead from time to time + lsp-mode so it will be a big deal. – cuhabaho May 31 at 2:19
2

web-mode-language-at-pos function is what are your looking for. Although it is not documented.

Single function to get language at pos that will work across different modes might look like this:

(defun my/language-at-pos (pos)
  "Message language at POS."
  (interactive "d")
  (let ((lang (cond
               ;; web-mode
               ((eq major-mode 'web-mode)
                (web-mode-language-at-pos pos))
               ;; mhtml-mode
               ((derived-mode-p 'mhtml-mode) "HTML")
               ((eq major-mode 'js-mode) "JS")
               ((eq major-mode 'css-mode) "CSS")
               ;; html-mode
               ((derived-mode-p 'html-mode)
                (let ((submode (get-text-property pos 'mhtml-submode)))
                  (if submode
                      (mhtml--submode-name submode)
                    "HTML")))
               ;TODO: rjsx-mode and other
               (t
                (message "Don't know how to get language in %s" major-mode)
                nil))))
    (when lang
      (message "Language at point is %s" lang))))

It will work for vue-mode because vue-mode is derived from html-mode.

  • I have tried this but the problem is that i need to use web-mode while i am not always using web-mode in my case. – cuhabaho May 30 at 10:20
  • You can try temporarily switching to web-mode, forcing it to font-lock the buffer and then running this function. – DoMiNeLa10 May 30 at 12:28
  • @DoMiNeLa10, it might be a good idea but the problem is that i connect to lsp-mode so switch between mode might stop lsp-mode from work and re-enable it back and ford might slow down emacs indeed. – cuhabaho May 31 at 2:23
  • @cuhabaho web-mode is in your question tags so i thought you are asking about particular mode and my answer is related to web-mode. Please, provide more details of your problem in the question. – muffinmad May 31 at 6:49
  • @muffinmad, I am using emmet and i enable it globally in programming mode. The problem come when it is inside js file which include both html, css, js. It always complete my js code as emmet. So, my point is that, getting the programming language at point and then if it is html or css, then enable emmet and i do so by hook to point changed hook and i re-check. Not sure if it is a good solution though. – cuhabaho May 31 at 10:12
1

Emacs 26.1 uses mhtml-mode for HTML files by default, the new mode supports JavaScript and CSS within HTML. Here is the NEWS from C-u C-h n 26.1:

*** A new submode of 'html-mode', 'mhtml-mode', is now the default mode for *.html files. This mode handles indentation, fontification, and commenting for embedded JavaScript and CSS.

You can use the text properties at the point to get the language, the following returns one of "HTML", "CSS" and "JS".

(pcase (get-text-property (point) 'mhtml-submode)
  ('nil "HTML")
  (submode (mhtml--submode-name submode)))
  • But in my case, i do work in vuejs=>vue-mode, reactjs=>rjsx-mode as well as .blade.php template so mhtml mode might not work in all case i need. – cuhabaho May 30 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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