Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embedded languages #71

Open
felipeochoa opened this issue Apr 26, 2018 · 22 comments
Open

Embedded languages #71

felipeochoa opened this issue Apr 26, 2018 · 22 comments

Comments

@felipeochoa
Copy link
Owner

There have been a several requests for this before (#70, #69, #63), and I've closed them because I felt them to be out of scope for rjsx. However, given this is a recurring issue, I'm now thinking it might make sense to add this to rjsx.

This wouldn't be an easy task, and is not something I use, so there would need be significant community support for getting this done. There are a few things that would help move this along without having to sit and code the entire thing start to finish, so please weigh in with information/opinions on these topics:

  • What languages would people like to support?
  • What features are important to support in each language? (syntax highlighting, formatting, linting, autocomplete, etc.)
  • What do other editors/IDEs offer in this area?
  • Are there existing tools we could leverage (e.g., LSP) to help build this support?
  • Should languages be supported directly or should there be a pluggable API?
@carloscheddar
Copy link

  • What languages would people like to support?
    css-in-js syntax from styled-components.

  • What features are important to support in each language? (syntax highlighting, formatting, linting, autocomplete, etc.)
    For me the most important would be formatting such as indentation. Syntax highlighting would be an awesome plus.

  • What do other editors/IDEs offer in this area?

  • Are there existing tools we could leverage (e.g., LSP) to help build this support?
    The syntax is very similar to scss so we could see how it's implemented in scss-mode.

  • Should languages be supported directly or should there be a pluggable API?
    A pluggable API would be great for extensibility and would help keep these "minor modes" in their own repos.

@Wesitos
Copy link

Wesitos commented Jun 2, 2018

  • What languages would people like to support?
    css-in-js sintax from styled-jsx (Similar to styled-components) and graphql queries (graphql-tag)
  • What features are important to support in each language? (syntax highlighting, formatting, linting, autocomplete, etc.)
    I agree with @carloscheddar. Indentation is fundamental. But Syntax highlight would be perfect for me.
  • Should languages be supported directly or should there be a pluggable API?
    I think it could be cool to be able to assign a "submode" to tagged templates strings based in the tag-name.

@LaloHao
Copy link

LaloHao commented Jun 6, 2018

mooz/js2-mode#288
I know the parser is not this plugin's area and it shouldn't be when focus is on the front/editor. But i've been gathering info on the subject and the babel parser AST seems well-defined [1]. The plugin handbook [2] gave me a good crash course, and i think it could be useful to perform semantic analysis (even on a project basis) instead of relying on complex/nested regex in emacs [9].

It could solve the jsx indentation issue , since it has "start", "end" character wise location and even "line" and "column" [3]
<div>

                    "type": "JSXIdentifier",
                    "start": 277,
                    "end": 280,
                    "loc": {
                      "start": {
                        "line": 16,
                        "column": 11
                      },
                      "end": {
                        "line": 16,
                        "column": 14
                      }
                    },
                    "name": "div"

^ also useful for coloring tokens/keywords

IMHO using external tools ie node shouldn't be a problem since we are already developing jsx and most likely already using the babel transpiler directly or indirectly, else we wouldn't be using rjsx-mode.

css ast [4] @Wesitos

[9] Connecting emacs to a node process is already done:
https://github.com/kiwanami/emacs-epc
https://github.com/kiwanami/node-elrpc

[1] https://github.com/babel/babel/blob/master/packages/babel-parser/ast/spec.md
[2] https://github.com/jamiebuilds/babel-handbook/blob/master/translations/en/plugin-handbook.md#toc-building-nodes
[3] https://github.com/facebook/jsx/blob/master/AST.md
[4] https://github.com/csstree/csstree/blob/master/docs/ast.md

@haywirez
Copy link

Support for styled-components 👍

@LaloHao
Copy link

LaloHao commented Jul 21, 2018

Here's a quick hack for editing in another buffer like org-mode does, using fence-edit and rx

(modify-syntax-entry ?` "\"" js-mode-syntax-table)

(setq
 styled-component-start
 (rx-to-string '(: (1+ (and (+ word) (0+ "\.") (0+ "(" (+ alpha) ")"))) "`" eol)))

(setq
 styled-component-end
 (rx-to-string '(: "`;" eol)))

(setq
 fence-edit-blocks `((,styled-component-start ,styled-component-end)))

(setq fence-edit-default-mode 'css-mode)

with cursor inside string template call fence-edit-code-at-point

minor-mode maybe?

EDIT:

Catches;
objects, properties and their method calls

export const Container = styled.div`
`;
Container.Settings = Container.Row.extend`
`;
export const Scrollbar = styled(Scrollbars)`
`;
export const Scrollbar = aaaa.styled(Scrollbars)`
`;

@Wesitos
Copy link

Wesitos commented Mar 15, 2019

I was trying to implement this with polymode. Indentation works, but syntax highlighting does not.
Looks like mmm-mode has the same problem with rjsx-mode (and js2-mode).

@mnewt
Copy link

mnewt commented Apr 4, 2019

+1 for graphql.

I'm currently using fence-edit like this:

(add-to-list 'fence-edit-blocks '("graphql[ \t\n]*(?`" "`" graphql))

(bind-key "C-c '" #'fence-edit-dwim)

My full config: https://gitlab.com/mnewt/dotemacs/blob/master/.emacs.d/init.el#L2777

@wyuenho
Copy link
Contributor

wyuenho commented Jul 22, 2019

Polymode works for me, despite its documentation claims otherwise. I just have to make sure polymode is loaded after rjsx-mode, otherwise the graphql block will still be using rjsx-mode's string face.

This is my config:

(use-package polymode
  :after rjsx-mode
  :config
  (define-hostmode poly-rjsx-hostmode nil
    "RJSX hostmode."
    :mode 'rjsx-mode)
  (define-innermode poly-rjsx-graphql-innermode nil
    :mode 'graphql-mode
    :head-matcher "graphql\`"
    :tail-matcher "\`"
    :head-mode 'host
    :tail-mode 'host)
  (define-polymode poly-rjsx-mode
    :hostmode 'poly-rjsx-hostmode
    :innermodes '(poly-rjsx-graphql-innermode))
  (add-to-list 'auto-mode-alist '("\\.jsx?\\'" . poly-rjsx-mode)))

(use-package rjsx-mode
  :mode ("\\.jsx?\\'" "\\.mjs\\'"))

@littlehome-eugene
Copy link

Based on wyuenho's answer

styled-components or emotion.js css-in-js can be done via


(use-package polymode
   :ensure t
   :after rjsx-mode
   :config
   (define-hostmode poly-rjsx-hostmode nil
     "RJSX hostmode."
     :mode 'rjsx-mode)
   (define-innermode poly-rjsx-cssinjs-innermode nil
     :mode 'css-mode
     :head-matcher "css\`\\|styled\.[[:alnum:]]+\`"
     :tail-matcher "\`"
     :head-mode 'host
     :tail-mode 'host)
   (define-polymode poly-rjsx-mode
     :hostmode 'poly-rjsx-hostmode
     :innermodes '(poly-rjsx-cssinjs-innermode))
   (add-to-list 'auto-mode-alist '("\\.jsx?\\'" . poly-rjsx-mode)))

@wyuenho
Copy link
Contributor

wyuenho commented Oct 13, 2019

I might have spoken too soon. While that's the correct way to set up a poly mode, it doesn't work very well since every time rjsx reparses, the font lock will be wiped out

@rangeoshun
Copy link

rangeoshun commented Oct 22, 2019

I opted to use typescript-mode instead of rjsx-mode and augmented its JSX handling with web-mode. Used css-mode for styled components and added graphql-mode. I used mmm-mode, but this could be done with polymode I guess. But I had issues with polymode only highlighting the first block. Actual mode switch worked tho, but I like fancy colors. Here's my gist:
https://gist.github.com/rangeoshun/67cb17392c523579bc6cbd758b2315c1

@deviantfero
Copy link

@rangeoshun, I was taking a look at your snippet, any idea of how this could work with something like tide?, I often use variables defined in typescript sections of my code on JSX, any help would be appreciated, I currently use web-mode with tide as a completion engine

@rangeoshun
Copy link

rangeoshun commented Dec 4, 2019

@deviantfero, I think it just works as far as I can tell:

Screenshot 2019-12-04 at 12 55 52

Screenshot 2019-12-04 at 12 56 16

Also tide-fix works with one little caveat. When applied, mmm does not repaint the block right away. But it starts working again when you edit the block. This could be fixed by forcing mmm to reapply the modes if tide has a hook for this. I did not have the time to look into this tho.

Also by adding an after-save-hook, you can reapply mmm mode by toggling it. There may be a better way, but that was the one I came up with with the little time I put into this just now. This also allows prettier to do its thing and not screw up highlighting at all. My complete doom config is here, if you're interested: https://github.com/rangeoshun/dot-doom-d/blob/master/config.el

Hope I answered your question :)

@deviantfero
Copy link

deviantfero commented Dec 4, 2019 via email

@JacksonGariety
Copy link

JacksonGariety commented Apr 4, 2020

I'm using @rangeoshun's solution for .tsx files and it works except for inline functions:

function foo() {
  return (
    <MyComponent>
      {() => (
      <div> {/* <- indentation fails here */}
        <div></div>
      </div> 
      )()}
    </MyComponent>
  )
}

Is it possible to modify the RegExp to use web mode for the entire return block? Web-mode is quite unperformant when using it on the whole file for some reason.

EDIT: @deviantfero did you ever manage so solve your performance issues?

@rangeoshun
Copy link

@JacksonGariety I see now what you mean! To be honest, I had issues with tide, so in work, we opted to just use typescript-mode for JSX, which is subpar compared to web-mode but still does some highlighting, with a bit of autocomplete.

I have tried to create multiple mmm-class to cover this, but have not succeeded with emacs' regexp.

@rangeoshun
Copy link

@JacksonGariety Also, we use prettier-js, so I did not even notice the indentation issue.

@JacksonGariety
Copy link

@rangeoshun how do you get typescript-mode to indent JSX? For me it doesn't indent at all.

@rangeoshun
Copy link

@JacksonGariety I simply turned on prettier-js-mode for typescript-mode like so:

(add-hook 'typescript-mode-hook 'prettier-js-mode)

@Sleepful
Copy link

@rangeoshun how does it fare with string interpolation inside template literals?

@rangeoshun
Copy link

@rangeoshun how does it fare with string interpolation inside template literals?

If I understand your question correctly, you'll lose some company-mode features. But generally, I like to define my functions outside the literal, and interpolate the function by reference. Please tell me if I got your question wrong 😄

@rangeoshun
Copy link

Also anyone checking this topic, it might worth to try this repo here:

https://github.com/orzechowskid/css-in-js.el

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

No branches or pull requests