rjsx-mode icon indicating copy to clipboard operation
rjsx-mode copied to clipboard

Embedded languages

Open felipeochoa opened this issue 6 years ago • 22 comments

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?

felipeochoa avatar Apr 26 '18 21:04 felipeochoa

  • 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?

    • VSCode plugin https://github.com/styled-components/vscode-styled-components.
    • Vim plugin https://github.com/styled-components/vim-styled-components
  • 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.

carloscheddar avatar May 25 '18 15:05 carloscheddar

  • 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.

Wesitos avatar Jun 02 '18 18:06 Wesitos

https://github.com/mooz/js2-mode/issues/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

LaloHao avatar Jun 06 '18 09:06 LaloHao

Support for styled-components 👍

haywirez avatar Jun 11 '18 08:06 haywirez

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)`
`;

LaloHao avatar Jul 21 '18 17:07 LaloHao

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).

Wesitos avatar Mar 15 '19 01:03 Wesitos

+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

mnewt avatar Apr 04 '19 19:04 mnewt

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\\'"))

wyuenho avatar Jul 22 '19 23:07 wyuenho

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)))

littlehome-eugene avatar Oct 13 '19 15:10 littlehome-eugene

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

wyuenho avatar Oct 13 '19 15:10 wyuenho

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

rangeoshun avatar Oct 22 '19 09:10 rangeoshun

@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

deviantfero avatar Dec 03 '19 15:12 deviantfero

@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 :)

rangeoshun avatar Dec 04 '19 12:12 rangeoshun

Thank you so much, I'll have a look, I've been looking into improving performance when editing JSX and this seems to be the appropriate answer

On Wed, 4 Dec 2019 at 06:02, rangeoshun [email protected] wrote:

@deviantfero https://github.com/deviantfero, I think it just works as far as I can tell:

[image: Screenshot 2019-12-04 at 12 55 52] https://user-images.githubusercontent.com/1267842/70140799-cf2d1d80-1695-11ea-8003-544c62ddfb73.png

[image: Screenshot 2019-12-04 at 12 56 16] https://user-images.githubusercontent.com/1267842/70140801-d0f6e100-1695-11ea-9c6a-35a67cbd66cd.png

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.

My complete doom config is here, if you're interested: https://github.com/rangeoshun/dot-doom-d/blob/master/config.el

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/felipeochoa/rjsx-mode/issues/71?email_source=notifications&email_token=ACVCGSO27LA6OA7MNF43IK3QW6L5VA5CNFSM4E47FAOKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEF4Y3XY#issuecomment-561614303, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACVCGSOW6UTE3OW3KDPGZULQW6L5VANCNFSM4E47FAOA .

deviantfero avatar Dec 04 '19 13:12 deviantfero

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?

JacksonGariety avatar Apr 04 '20 03:04 JacksonGariety

@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 avatar Apr 05 '20 08:04 rangeoshun

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

rangeoshun avatar Apr 05 '20 08:04 rangeoshun

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

JacksonGariety avatar Apr 05 '20 08:04 JacksonGariety

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

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

rangeoshun avatar Apr 05 '20 09:04 rangeoshun

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

Sleepful avatar Nov 10 '20 17:11 Sleepful

@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 avatar Nov 10 '20 17:11 rangeoshun

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

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

rangeoshun avatar Nov 10 '20 17:11 rangeoshun