Sublime Forum

How to easily comment out lines that are a mix of HTML and PHP?

#1

I frequently want to comment out a line of code that is a mix of HTML and PHP, e.g.

<span class="item"><?php get_the_title(); ?></span>

My usual Sublime Text shortcut of ctrl+/ does not handle this well–I still have to manually comment out the PHP code. Are there ways around this that would allow a keyboard shortcut to comment out the entire line?

Or is this type of coding bad practice? Perhaps I should always separate HTML and PHP onto different lines?

Thanks in advance.

1 Like

#2

I don’t know about whether it is bad practice or not, but you can write a plugin to do this: (split selection by scope - text (HTML) or source (PHP) and then invoke the toggle_comment command.)

  1. Tools menu -> Developer -> New Plugin
  2. Select all and replace with the following:
import sublime
import sublime_plugin


class ToggleCommentSourceTextCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        original_sel = [sel for sel in self.view.sel()]
        regions = list()
        for sel in self.view.sel():
            if sel.empty():
                sel = self.view.line(sel)
            region_start = None
            for pos in range(sel.begin(), sel.end() + 1):
                if region_start is None or self.view.match_selector(pos, 'source') != self.view.match_selector(region_start, 'source') or self.view.match_selector(pos, 'punctuation.section.embedded'):
                    if region_start is not None:
                        regions.append(sublime.Region(region_start, pos - (1 if self.view.match_selector(pos, 'punctuation.section.embedded.end') else 0))) # the minus one works around a `toggle_comment` command bug
                        region_start = None
                    if not self.view.match_selector(pos, 'punctuation.section.embedded'):
                        region_start = pos
            print(pos, region_start)
            if region_start != pos:
                regions.append(sublime.Region(region_start, pos))
        
        self.view.sel().clear()
        self.view.sel().add_all(regions)
        self.view.run_command('toggle_comment', { 'block': True })
        self.view.sel().clear()
        self.view.sel().add_all(original_sel)
  1. Save it as toggle_comment_cag8f.py in the folder ST recommends (Packages/User/)
  2. Create a keybinding to use the toggle_comment_source_text command (optionally replace the default block comment key combination)
  3. Optionally update the Edit -> Comment menu entry to use this command

Note that due to a bug in the toggle_comment command, it requires whitespace between the end of the PHP code and the ?> - you can see this if you manually select everything between the <?php and ?> and try to use the toggle_comment command with arguments block true - nothing happens.

1 Like

#3

Sorry for the late reply. Thanks for the instructions. I gave it a shot, but ran into an issue with the keybind step. How exactly do I replace the existing keybind with this new plugin? I know that I can open Preferences–>Key Bindings, and the syntax of the existing keybind is:

{ "keys": ["ctrl+/"], "command": "toggle_comment", "args": { "block": false } },

But how do I modify that to point to my new plugin?

Thanks!

0 Likes

#4

Works fine on ST3131 with default HTML syntax.

Just pasted your line and can comment/uncomment using the default shortcut.

0 Likes

#5

@deathaxe: Yep, I see that. The same is true for mine–if I use HTML syntax there is no issue. But if I’m using PHP syntax, the issue occurs.

Works fine on ST3131

What is 3131? Is that the build number? If so, how are you using that? My build number is 3126. I just checked for updates and the program said there were none.

0 Likes

#6

Yes it’s the latest DEV built. I don’t know whether it is published via automatic update, if you run a version from stable branch.

I just double checked with ST3 built 3126 and it works fine, too. I can comment/uncomment your line.

The comment/uncomment feature uses certain rules defined in *.tmPreferences files which work only for a predefined set of syntax.

If you use a custom HTML syntax package it might define different scopes which are not handled by default rules and may not come with its own set of rules

0 Likes

#7

In the default HTML package you’ll find a Comments.tmPreferences

<?xml version="1.0" encoding="UTF-8"?>
<plist version="1.0">
<dict>
	<key>name</key>
	<string>Comments</string>
	<key>scope</key>
	<string>text.html</string>   <!-- this is the scope the rules apply to -->
	<key>settings</key>
	<dict>
		<key>shellVariables</key>
		<array>
			<dict>
				<key>name</key>
				<string>TM_COMMENT_START</string>
				<key>value</key>
				<string>&lt;!-- </string>
			</dict>
			<dict>
				<key>name</key>
				<string>TM_COMMENT_END</string>
				<key>value</key>
				<string> --&gt;</string>
			</dict>
		</array>
	</dict>
</dict>
</plist>
0 Likes

#8

OK thanks for all this. But what exactly does it mean for my situation? I see that the commenting works as expected when I’m in HTML syntax. But I want to continue to work in the PHP syntax. Aside from the custom plugin suggested by @kingkeith, is there anything I can do? Could I create a macro that switches to HTML syntax, comments the line, then quickly switches back to PHP syntax?

0 Likes

#9

With PHP syntax a commented out line looks like this?

The php block keeps rendered uncommented as it is a dedicated scope which is injected into HTML and thus can’t see the commented surroundings.

I didn’t work with PHP for years, so please help me: Is the PHP block still parsed and run? Or is it just a visual issue. I this case we might need to update syntax files.

0 Likes

#10

As @kingkeith pointed out in my previous thread, the PHP in this case is still evaluated by the server. In my case, I would like for both the HTML and PHP to be commented out and not evaluated.

It sounds like @kingkeith gave me instructions for a suitable workaround earlier in this thread. I just need to apply the keybind properly so I can test it.

0 Likes

#11

With information from your link, I agree with @kingkeith. You need an plugin to handle it as ST’s built-in commenting feature can’t handle multiple scopes at once. It can’t know whether the embedded PHP block needs separate commenting or not.

0 Likes

#12

OK thanks for that. But I was trying to implement @kingkeith’s solution and ran into an issue. He suggested I create a new plugin with the code he provided, then create a keybind for it. But how exactly do I replace the existing comment keybind with this new plugin? I know that I can open Preferences–>Key Bindings, and the syntax of the existing keybind is:

{ "keys": ["ctrl+/"], "command": "toggle_comment", "args": { "block": false } },

But how do I modify that to point to my new plugin? Thanks!

0 Likes

#13

just replace toggle_comment with toggle_comment_source_text

0 Likes

#14

OK thanks for that. I’ve made that change, but the keybind is still unresponsive. To revisit your previous instructions, where exactly should I save toggle_comment_cag8f.py? I have it saved in C:\Program Files\Sublime Text 3\Packages\User (I’m on Win 10). Unfortunately the folder suggested by Sublime text was D:\temp for some reason.

Thanks.

0 Likes

#15

Go to the Preferences menu in ST -> Browse Packages, and then it should open the Sublime Text 3\Packages folder under your roaming user profile - put the file in the User subfolder there.

0 Likes

#16

OK gotcha. The .py folder is indeed in that location. In ST–>Preferences–>Key Bindings I have:

{ "keys": ["ctrl+/"], "command": "toggle_comment_source_text", "args": { "block": false } }

Yet when I enter the code:

<span class="item"><?php get_the_title(); ?></span>

and switch to PHP syntax, the key bind is unresponsive. If I remove my entry in Preferences–>Key Bindings, the keybind reverts back to its default functionality. Thoughts?

0 Likes

#17

any related errors in the ST console? View menu -> Show Console

0 Likes

#18

Nothing that seems out of the ordinary. The console has many entries for ‘reloading plugin,’ e.g.

reloading plugin Default.side_bar

One is my custom plugin:

reloading plugin User.toggle_comment_cag8f

Thoughts? Is that an indicator of the issue?

0 Likes

#19

that just indicates the plugin was reloaded without any errors. Maybe add some print('on line 5') style debug logging to the custom command, to help track down what’s happening - all I can say is that it works for me.

0 Likes

#20

OK thanks very much for the help so far. It’s not terribly urgent, but I’d like to resolve this if possible.

Maybe add some print(‘on line 5’) style debug logging to the custom command, to help track down what’s

How/where exactly would I add this debugging code?

0 Likes