sublimehq / Packages

Syntax highlighting files shipped with Sublime Text and Sublime Merge
https://sublimetext.com
Other
2.95k stars 585 forks source link

[TSX] Toggle comment doesn't work in react render children function #2840

Open predragnikolic opened 3 years ago

predragnikolic commented 3 years ago

Try to press toggle comment cmd+/ on the paragraf tag:

function Form() {
  return <Formik>
    <div>
      <p>You can successfully comment the paragraph</p>
      {/*<p>Paragraph</p>*/}
    </div>
  </Formik>
}

function Form() {
  return <Formik>
    { () => <div>
      <p>You cannot successfully comment the paragraph</p>
      /*<p>Paragraph</p>*/
    </div>}
  </Formik>
}

Kapture 2021-05-28 at 20 35 46

Thom1729 commented 3 years ago

This is caused by https://github.com/sublimehq/sublime_text/issues/2152. (See also https://github.com/babel/babel-sublime/issues/390#issuecomment-820516000.)

In this case, the problem is that there are two comment specs that match the scope at the cursor in the second example:

  1. meta.jsx from JSX Comments.tmPreferences
  2. source.js, source.jsx, source.ts, source.tsx, meta.jsx meta.tag.name, meta.jsx meta.tag.attributes from Comments.tmPreferences

Intuitively, meta.jsx should be the better match, but there's a quirk. When score_selector could match in multiple positions, it matches the earliest rather than the latest — that is, the lowest possible score rather than the highest. So when the scope source.jsx meta.jsx source.js meta.jsx is matched against the selector meta.jsx, the score is based on the leftmost/outermost meta.jsx, not the rightmost/innermost.

This combined with a piece of good behavior: score_selector(<scope>, 'X, Y, Z') seems to match X, Y, and Z separately and return the best match (the highest number). So score_selector('source.jsx meta.jsx source.js meta.jsx', 'source.jsx, source.js') actually scores based on source.js, even though source.jsx is the leftmost possible match.

I'm probably explaining this confusingly. The point is that a longstanding bug in the selector scoring algorithm is causing the toggle_comment command to think that regular JS comments are a better match at the cursor than JSX comments. Fundamentally, this is an issue that should be addressed in core. (Nitpick: toggle_comment isn't actually invoking the score_selector API function, but rather calling view.meta_info, which seems to use the same algorithm behind the scenes.)

It may also be possible to improve behavior in this case by tweaking the comment rules. This would likely come at the expense of worse behavior in other cases.

predragnikolic commented 3 years ago

Thomas mention a workaround on discord, and that is to override the JSX Comments.tmPreferences file.

in the Sublime Text User directory, create a JSX Comments.tmPreferences file, with the following content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>name</key>
    <string>JSX Comments</string>
    <key>scope</key>
    <string>meta.function meta.block meta.group meta.jsx</string>
    <key>settings</key>
    <dict>
        <key>shellVariables</key>
        <array>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_START</string>
                <key>value</key>
                <string>{/*</string>
            </dict>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_END</string>
                <key>value</key>
                <string>*/}</string>
            </dict>
        </array>
    </dict>
</dict>
</plist>

This solution work for me now. So I will close this.

Thanks!

predragnikolic commented 3 years ago

I reopenex the issue, because I fixed it for myself, but other people might run into this as well.

It would be better to fix it it the default packages. But not sure if the above fix that works for me, breaks something else.

deathaxe commented 3 years ago

I've tried to improve the situation a little bit via the following files, but it still fails as soon as comments are to be added in deeper nested code blocks. So I must second @Thom1729's statement about us being not able to find properly working solution via changes within this repository.

Comments.tmPreferences

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>scope</key>
    <string>
        source.js - meta.jsx,
        source.jsx - meta.jsx,
        source.ts - meta.jsx,
        source.tsx - meta.jsx,
        meta.jsx meta.tag.name,
        meta.jsx meta.tag.attributes
    </string>
    <key>settings</key>
    <dict>
        <key>shellVariables</key>
        <array>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_START</string>
                <key>value</key>
                <string>// </string>
            </dict>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_START_2</string>
                <key>value</key>
                <string>/*</string>
            </dict>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_END_2</string>
                <key>value</key>
                <string>*/</string>
            </dict>
        </array>
    </dict>
</dict>
</plist>

JSX Comments.tmPreferences

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
    <key>scope</key>
    <string>
        meta.jsx - (meta.jsx source.js.embedded - source.js.embedded meta.jsx),
        meta.jsx comment.block.js
    </string>
    <key>settings</key>
    <dict>
        <key>shellVariables</key>
        <array>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_START</string>
                <key>value</key>
                <string>{/*</string>
            </dict>
            <dict>
                <key>name</key>
                <string>TM_COMMENT_END</string>
                <key>value</key>
                <string>*/}</string>
            </dict>
        </array>
    </dict>
</dict>
</plist>