Sublime Forum

Soft tabs, selection wrap and switch syntax

#1

Hi guys. I’m new to Sublime (former E user) and I’m trying to add to Sublime features that I had in E.

Soft Tabs
First thing that was annoying to me was the soft tabs. I tried to mess with all settings but with no luck.
So i made this custom shortcut/key bind:

	{ "keys": "tab"], "command": "move", "args": { "by": "words", "forward": true }, "context":
		{	"key": 	"following_text", "operator": "regex_contains", "operand": "^\\t", "match_all":true }
	]}

(sublime-keymap)

Selection Wrap
I found there was a package with a lot of stuff that had this thing too, but was for Sublime 1. So i made this key bind:

	{ 
		"keys"		:	"alt+shift+w"], 
		"command"	:	"insert_snippet",
		"args"	:	{
			"contents": "<${1:p}>${0:$SELECTION}</${1/\\s.*//}>"
		}
	}

Tada! Works! :smile:

Switch Syntax

this is the initial version, read below
[size=85]
This is kind of tricky. It may be a shorter version for this, but i didn’t get it how to do it. All i found was this. Unfortunately, I didn’t understand too much from that thing and what should i do with it. I was stuck at this:

{ "keys": "alt+1"], "command": "set_file_type", "args":{ ***** } }

With no clue on what should i put where astericses are.

So i did this keybinds:

	{ "keys": "alt+1"], "command": "set_js_syntax" },
	{ "keys": "alt+2"], "command": "set_html_syntax" },
	{ "keys": "alt+3"], "command": "set_php_syntax" },
	{ "keys": "alt+4"], "command": "set_css_syntax" }

And for all syntax i created a new plugin that contains this:

import sublime, sublime_plugin

class set_css_syntax(sublime_plugin.TextCommand):
	def run(self, edit):
		self.view.settings().set('syntax', 'Packages/CSS/CSS.tmLanguage')

[/size]

Updated (10x to jbjornson)

{ "keys": "alt+1"], "command": "set_file_type", "args":{ "syntax" : "Packages/JavaScript/JavaScript.tmLanguage" } }, { "keys": "alt+2"], "command": "set_file_type", "args":{ "syntax" : "Packages/HTML/HTML.tmLanguage" } }, { "keys": "alt+3"], "command": "set_file_type", "args":{ "syntax" : "Packages/PHP/PHP.tmLanguage" } }, { "keys": "alt+4"], "command": "set_file_type", "args":{ "syntax" : "Packages/CSS/CSS.tmLanguage" } },

(you can replace CSS with any syntax you want)

So, what do you think guys? :smiley:

The only two thing that I need to replace E completely is: translate all snippets from E to ST and make ctrl+tab to behave (is very redundant right now). Go to last active tab would be great. Any clues?
(oh, and a history tree would be nice to have)

0 Likes

Useless tab triggers
How to set file type with key binding
#2

I like the “switch syntax” idea, but I’m not sure that having so many similar plugins is ideal. How about this instead (see below)? It also allows for the user to choose a syntax if one isn’t defined in the shortcut. Ideally (in the future), we could have access to the quick panel API and present a filterable list of syntaxes to choose from (if one isn’t defined in the shortcut).

import sublime, sublime_plugin, os, fnmatch

class SetFileSyntaxCommand(sublime_plugin.TextCommand):

    def run(self, edit, syntax=''):
        """Set the syntax for this view as specified, or, if not specified, ask the user for the syntax type to change to"""
        self.populate_map()
        if not syntax in syntaxMap:
            message = 'Please type the name of the syntax type to switch the view to: '
            sublime.active_window().show_input_panel(message, 'java', lambda s: self.set_syntax(s), None, None)
        else:
            self.set_syntax(syntax)

    def set_syntax(self, syntax):
        """Set the syntax for this view if it matches a key in the map"""
        syntax = syntax.lower()
        if syntax in syntaxMap:
            self.view.settings().set('syntax', syntaxMap[syntax])

    def populate_map(self):
        """Get a list of valid syntax highlighting options"""
        if not hasattr(self, 'syntaxMap'):
            self.syntaxMap = {}
            for root, dirnames, filenames in os.walk(sublime.packages_path()):
                for filename in fnmatch.filter(filenames, '*.tmLanguage'):
                    name = os.path.splitext(filename)[0].lower()
                    full_path = os.path.join(root, filename)
                    relative_path = full_path.replace(sublime.packages_path(), 'Packages')
                    self.syntaxMap[name] = relative_path

You could then setup your shortcuts as follows:

   { "keys": "alt+1"], "command": "set_file_syntax", "args": {"syntax": "javascript"}},
   { "keys": "alt+2"], "command": "set_file_syntax", "args": {"syntax": "html"}},
   { "keys": "alt+3"], "command": "set_file_syntax", "args": {"syntax": "php"}},
   { "keys": "alt+4"], "command": "set_file_syntax", "args": {"syntax": "css"}}
0 Likes

#3

I know that plugin work around is not a good idea, but I kind of needed something that… works. And the json thing didn’t worked for me (doesn’t work with your code either).

And about your code: my py skillz are zero. On my … plugins i was sort of a code monkey :smiley:

Wondering if is possible to add a selector for each key bind, like so:
http://content.screencast.com/users/iamntz/folders/Jing/media/81fd9cfc-80e1-4fa5-92d5-2545c61123cc/2011-05-16_1424.png

0 Likes

#4

Ok, try this updated version. If it doesn’t work have a look in the console for error messages, etc…

import sublime, sublime_plugin, os, fnmatch

class SetFileSyntaxCommand(sublime_plugin.TextCommand):

    def run(self, edit, syntax=''):
        """Set the syntax for this view as specified, or, if not specified, ask the user for the syntax type to change to"""
        self.populate_map()
        if not syntax in self.syntaxMap:
            message = 'Please type the name of the syntax type to switch the view to: '
            sublime.active_window().show_input_panel(message, self.get_current_syntax(), lambda s: self.set_syntax(s), None, None)
        else:
            self.set_syntax(syntax)

    def set_syntax(self, syntax):
        """Set the syntax for this view if it matches a key in the map"""
        if syntax in self.syntaxMap:
            self.view.set_syntax_file(self.syntaxMap[syntax.lower()])
        else:
            print '"%s" is not a known syntax highlighting' % (syntax)
            print self.syntaxMap

    def populate_map(self):
        """Get a list of valid syntax highlighting options"""
        # if not hasattr(self, 'syntaxMap'):
        self.syntaxMap = {}
        for root, dirnames, filenames in os.walk(sublime.packages_path()):
            for filename in fnmatch.filter(filenames, '*.tmLanguage'):
                name = os.path.splitext(filename)[0]
                full_path = os.path.join(root, filename)
                relative_path = full_path.replace(sublime.packages_path(), 'Packages')
                relative_path = relative_path.replace('\\', '/') # fix windows paths
                self.syntaxMap[name.lower()] = relative_path
                print 'Syntax: %-20s -> "%s" (%s)' % (name, relative_path, full_path)

    def get_current_syntax(self):
        current_syntax = self.view.settings().get('syntax')
        (path, filename) = os.path.split(current_syntax)
        (shortname, extension) = os.path.splitext(filename)
        return shortname

By the way, these key mappings work for me:

    { "keys": "alt+1"], "command": "set_file_type", "args":{ "syntax" : "Packages/Java/Java.tmLanguage" } },
    { "keys": "alt+2"], "command": "set_file_type", "args":{ "syntax" : "Packages/Python/Python.tmLanguage" } },

On Windows at least, it looks like the above doesn’t work if you use backslashes (), but it works fine if you use (unix style) forward slashes. Maybe your key-mappings weren’t working because you were using backslashes?

As a side note, “alt+1”…“alt+0” are mapped by default to quickly switch between views so if you want that functionality you may want to change your key mappings.

0 Likes

#5

YES! It works. Great, thanks!

Unfortunately, i didn’t fully understand how to call custom plugins. I saw there are plugins named in a way, saved with another name and called with a totally different name. How is this possible? :open_mouth:

0 Likes

Dev Build 2063
#6

Sublime Text converts camel-case plugin names (eg SetFileSyntaxCommand), removed the “Command” at the end and separates the capitalized words with underscores. So in this case, “SetFileSyntaxCommand” becomes “set_file_syntax”.

From the “Conventions for Command Names” section in the documentation (http://sublimetext.info/docs/reference/plugins.html)):

0 Likes

#7

Sweet! Now make a lot of sense.

Thanks!

0 Likes

#8

Thank you really much, very usefull extensions.

0 Likes

#9

…an updated version using the quick panel introduced in build 2069:

import sublime, sublime_plugin, os, fnmatch

class SetFileSyntaxCommand(sublime_plugin.WindowCommand):
    def callback(self, index):
        if index >= 0:
            self.window.active_view().set_syntax_file(self.syntaxList[index][1])

    def run(self):
        self.populate_map()
        self.window.show_quick_panel(self.syntaxList, self.callback)

    def populate_map(self):
        """Get a list of valid syntax highlighting options"""
        self.syntaxList = ]
        for root, dirnames, filenames in os.walk(sublime.packages_path()):
            for filename in fnmatch.filter(filenames, '*.tmLanguage'):
                name = os.path.splitext(filename)[0]
                full_path = os.path.join(root, filename)
                relative_path = full_path.replace(sublime.packages_path(), 'Packages')
                relative_path = relative_path.replace('\\', '/') # fix windows paths

                self.syntaxList.append([name, relative_path])

Updated callback to correctly handle no highlight being selected

0 Likes

#10

Isn’t it redundant with the new Command Palette ?

I tried this key binding:

    { "keys": "ctrl+shift+y"], "command": "show_overlay", "args": {"overlay": "command_palette", "text": "Set Syntax:"} }
]

but it doesn’t work properly, look like the “text” parameter is ignored. Maybe Jon could make it work.

0 Likes

#11

Right you are, this is totally redundant now. I hadn’t really played with the command palette yet but it looks quite cool!

0 Likes

#12

[quote=“iamntz”]First thing that was annoying to me was the soft tabs.

The only two thing that I need to replace E completely is: translate all snippets from E to ST and make ctrl+tab to behave (is very redundant right now). Go to last active tab would be great. Any clues?[/quote]

I’m a bit late here, but could you explain what you mean by soft tabs? It’s generally used in text editor parlance to mean inserting spaces when you press tab, which is done in Sublime Text with the translate_tabs_to_spaces setting.

Ctrl+tab behaves just as it does is almost every other application: it cycles through a stack of files, with the most recently selected one on top. “Go to last active tab” is done by pressing ctrl+tab once.

0 Likes

#13

@Jps: fortunately, i migrated to ST without these things. i like the release cycle and your activity on the forums, which compensate somehow :mrgreen:

Ctrl+tab doesnt behave normally. Let me explain.

If we have 5 files opened ( a, B, c, D, e, f ). If B is active and previous active was D, when i press ctrl+tab, it goes to D, but now, the last active tab should be B. No? (just noticed is working like it should if i press ctrl+tab, release ctrl+tab then press again)

And about soft tabs, check out this video, should be explicit enough: screencast.com/t/5JziAePQGrY4

0 Likes

#14

That’s right, the stack of recent files is only updated when you let go of the ctrl key - alt tab (or command tab on osx) works the same way.

0 Likes

#15

Yes, you are right.
I guess i was… familiar with the editor that we don’t name it ( :ugeek: ) and i thought that is normal. Now, if I’m thinking a little at this, it kind of make sense…

0 Likes

#16

[quote=“bizoo”]Isn’t it redundant with the new Command Palette ?

I tried this key binding:

    { "keys": "ctrl+shift+y"], "command": "show_overlay", "args": {"overlay": "command_palette", "text": "Set Syntax:"} }
]

but it doesn’t work properly, look like the “text” parameter is ignored. Maybe Jon could make it work.[/quote]

Note that it work now with Build 2070.

0 Likes

#17

@jps: any news with soft tabs thing? screencast.com/t/5JziAePQGrY4
I’m using the following key shortcut config:

{ "keys": "tab"], "command": "move_to", "args": { "to": "bol", "forward":true }, "context": { "key": "following_text", "operator": "regex_contains", "operand": "\t", "match_all": false } ] }

But there are some issues if the code is like this:

[tab][tab]some things[tab] {

and translate_tabs_to_spaces setting doesn’t really do anything. Any hint please?

thanks!

0 Likes

#18

Can you explain exactly what you mean by soft tabs? Different programs use the phrase to mean different things.

0 Likes

#19

Look at the movie posted at start there is no smart tab and at 0:15 there are. (i just remembered they are called SMART tabs not soft tabs. Sorry about this confusion.)

Long story short, when i have tabs after current cursor position is not inserting new tabs.

So if i have this:

[cursor][tab]{

and i press tab key, the cursor will jump just before { without inserting any new tabs. The problem is, however, the key i used is considering all tabs in that line, not all tabs untill first non-tab char. I tried to use \t\b as operand with no luck.

0 Likes

#20

If I understand what you want correctly, you may be able to get by with the move by words command, which will advance the cursor to the start of the next word:

"command": "move", "args": {"by": "words", "forward": true} }

If that doesn’t do it, then you’ll likely have to resort to a plugin.

0 Likes