Sublime Forum

Get syntax associated with file extension

#1

Is there any way to retrieve the syntax path associated with a specific file extension?

Note that all of the following return the syntax path of the current file.

active_view = self.window.active_view()
syntax = active_view.settings().get("syntax", {"extension": "cpp"})
syntax = active_view.settings().get("syntax", {"default_extension": "cpp"})
syntax = active_view.settings().get("syntax", {"ext": "cpp"})
syntax = active_view.settings().get("syntax", {"type": "cpp"})
syntax = active_view.settings().get("syntax", "cpp")

Please note that clearly a user can change the syntax associated with a file extension so parsing the syntax files for their default extensions is not a viable solution.

Thanks.

3 Likes

#2

my guess would be you’d have to find and manually parse all the syntax specific overrides to find out

2 Likes

#3

Where are they stored? They are not in Preferences.sublime-settings.

1 Like

#4

in Packages/User/, and the settings file is the name of the syntax

i.e. Packages/User/JSON.sublime-settings

{
    "extensions":
    [
        "sublime-commands"
    ]
}

so may be a job of parsing the syntax defs and then all the syntax specific settings overrides to get all extensions

1 Like

#5

Thanks Keith.

A bit of a pain for what would be - in all probability - a couple of lines in the API. Oh well…

1 Like

#6

It’s worse than I thought. Here’s what I reckon is needed (probably incomplete).

  1. Iterate through the default packages in the ST install directory opening each of the (currently) 50 .sublime-package (zip) files and parsing the YAML in its .sublime-syntax file to build a list from the file_extensions key. During this process create a dictionary of syntax paths and their associated file extensions.
  2. Iterate through the .sublime-settings files in Packages/User parsing the JSON and storing the file extensions in the extensions key (if it has one) and associating them with the basename of the .sublime-settings filename.
    • If this basename is the name of an existing syntax in the dictionary created in 1) update the dictionary.
    • If this basename is not the name of an existing syntax then look for a directory in Packages with the same name and/or a .sublime-package file in Installed Packages with the same basename. Look for a file in the directory / zip structure (which could be buried in further subdir levels) with the same basename but with either a .sublime-syntax or a .tmLanguage extension and then build the syntax path based on its location and file extension. e.g. Packages/MagicPython/grammars/MagicPython.tmLanguage.
  3. Use the data gathered in 1) and 2) to work out the correct syntax file to use for the required file extension.

This is going to be way too slow to do on the fly during a plugin’s execution (50 zips!). Part 1) could be done in advance and stored in a file to be loaded as needed by the plugin but this would be version dependant or a version of the file would be needed for all supported versions of ST. --Just remembered (well looked up) sublime-syntax was added in version 3084, so 1) would need to handle .tmLanguage file extensions to support earlier versions than that.

As I said before; “Oh well…” :cry:

1 Like

API Suggestions
#7

eek! I can has API please, k thx bai :wink:

a new API wouldn’t help with older builds though, but these days supporting only the since the second latest non-dev build seems reasonable enough to me

1 Like

#8

Added to API Suggestions.

Sounds reasonable to me too. I usually upgrade on day-of-release (but ignore all dev builds beyond occasionally looking to see what’s been added - never yet actually installed one).

1 Like

#9

I came up with a hack to solve the problem, which unfortunately has a major downside.

  1. Create a temp file with the file extension of the desired syntax
  2. Open the temp file in ST with the API open_file() method
  3. Retrieve the syntax ST has assigned to the view’s settings
  4. Close the temp file’s ST buffer; close() is undocumented API
  5. Delete the temp file

Hey presto, the syntax for any file extension can be retrieved.

MAJOR DOWNSIDE:

The sequence of ST creating and then immediately closing the new buffer results in a visual ‘slide effect’ on the tab bar depending on how many tabs are showing and where the current tab is positioned within them. Most noticeably in a full tab bar when the furthest right hand tab is visible. Annoyingly passing the sublime.TRANSIENT flag to open_file() results in the failure of close(), i.e. the temp file buffer remains open and with the focus albeit tabless. I’m pretty sure there’s no way around this - making this syntax retrieval technique redundant for actual use in a plugin - unless anyone can think of a way of getting around this?

Proof of concept code - clearly barebones rough’n’ready:

import sublime, sublime_plugin
import os, tempfile

class TempTestCodeCommand(sublime_plugin.WindowCommand):

    def run(self):

        ext = ".cpp"
        temp_file = tempfile.NamedTemporaryFile(suffix = ext, delete = False)
        new_buffer = self.window.open_file(temp_file.name)
        syntax = new_buffer.settings().get("syntax", None)
        new_buffer.close()
        os.remove(temp_file.name)
        sublime.status_message("Syntax: " + syntax)
1 Like

#10

The problem was solved easily, View.close() fails but window.run_command("close") does not.

The following demo class works fine with one caveat; with Windows XP running as a virtual machine in VirtualBox a very brief flicker can OCCASIONALLY be seen in the title bar when the new buffer is created and then closed but only from an untitled buffer and it was hard to reproduce (appearing only a few times in dozens of runs trying to reproduce). Other than that ancient OS in a virtual environment, it has only been tested on my powerful Linux desktop and I was only able to get the brief flicker to show by calling GetFileExtensionSyntax() in a 50 iterations loop (a loop of 40 iterations and the flicker repeatedly did not show). I suppose the flicker may be visible in some circumstances on some platforms.

The code for the demo class (updated) is in this Gist…

1 Like

#11

Hi

I meet the similar requirement as well and what I have done is as follows:

  1. Store ext_name syntax mapping to preferences whenever open a new file using event listener on_load.
  2. Read syntax = mapping[ext_name] from preferences and done.

pros: no flicker
cons: big user settings file

I hope this helps.

3 Likes