Sublime Forum

[SOLVED] Problem with settings.get() inside from regex

#1

Hi guys,

i have a problem with regex and using the settings.get() function together.

My User Settings looks like:

{
	"ignored_packages":
	
		"DocBlockr",
		"Vintage"
	],
	"Username"	: "my username",
	"Company"	: "company name"

}

I created a new plugin with the following code:

import sublime, sublime_plugin
import re

# Provide completions that match just after typing an opening angle bracket
class myReplaceCompletions(sublime_plugin.EventListener):
    
    def on_query_completions(self, view, prefix, locations):
        # Only trigger within js
        if not view.match_selector(locations[0],
                "source.js"):
            return ]

        ### initialize config
        myConfig        = sublime.load_settings("Preferences.sublime-settings")
        
        ### test to return an value from the settings
        config          = myConfig.get("Username")

        ### some to return an value from the setting
        ### which uses an external variable to get the key
        config_value    = "Username"
        config2         = myConfig.get(config_value)

        ### string to replace
        string          = "/** * * @author: {{Setting:Username}} * @company: {{Setting:Company}} ***/"
        
        ### pattern
        regex           = "{{Setting:(.*?)}}"

        #test with get() as string
        myReplace       = re.sub(regex, "myConfig.get("r'\1'")", string)
        
        ### test with get() as function - use config_value (static)
        myReplace2      = re.sub(regex, myConfig.get(config_value), string)

        ### test with get as function - use regex repsonse
        ### not working
        #myReplace3      = re.sub(regex, myConfig.get(r'\1'), string)

        return (
            ("myReplace", myReplace),
            ("myReplace2", myReplace2),
            #("myReplace3", myReplace3),
            ("myConfigValue", "this is config 1: "+config),
            ("myConfigValue2", "this is config 2: "+config2)
        ], sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)

This code is copied and modified from the HTML Tab Completions.

Why I want this?

I started with snippets(1) and tmPreferences files. But there are some problems with the file permissions in Sublime Text 3.
So i began to use sublime-completions, which are good for small code snippets.

Now i want to use the code from my old snippets(1) and replace the variables, which are defined as $MY_COMPANY in the snippet file.

My idea was to use the placeholders like {Setting:Username} in my new code snippets and replace it dynamicly at execution.

Example:

{Setting:Username} will be replaced with myConfig.get(“Username”). Username is in this case \1 from my regex.

I hope you know what i mean.

Thanks for any response and feedback.

//EDIT
Sorry, forgot to paste the first part :blush:

Regards,
Marcus

0 Likes

#2

Why don’t you retrieve the value, then use that as your key in 2 steps. How you are doing it won’t work. re.sub takes 3 arguments, a regex, a replacement, and a string to run on. You have the first and last points down, but I think you are confused for the second. For myReplace3, you are effectively getting a string from myConfig with a key of r’\1’. This is likely returning None, which isn’t what you want. If there is a match, you can access the groups by doing something like the following.

match = re.search(regex, string)
if match:
    key = match.group(1)
    myReplace3 = re.sub(regex, myConfig.get(key), string)
0 Likes

#3

Hi,

yeah this works :smile:

But i have now the problem, that each placeholder will be replaced with the values from the first match.

Any idea? I checked the regex (via an online regex tool) and this shows me both placeholder entries.

Output:


//myReplace
/**
 *
 * @author: my username
 * @company: my username
 *
**/

//myKey
Username

Plugin:

import sublime, sublime_plugin
import re

# Provide completions that match just after typing an opening angle bracket
class myReplaceCompletions(sublime_plugin.EventListener):
    
    def on_query_completions(self, view, prefix, locations):
        # Only trigger within js
        if not view.match_selector(locations[0],
                "source.js"):
            return ]

        ### initialize config
        myConfig        = sublime.load_settings("Preferences.sublime-settings")

        ### string to replace
        string          = "/**\n *\n * @author: {{Setting:Username}}\n * @company: {{Setting:Company}}\n *\n**/"
        
        ### pattern
        regex           = "{{Setting:(.*?)}}"
        
        match = re.search(regex, string)
        if match:
            key = match.group(1)
            myReplace = re.sub(regex, myConfig.get(key), string) 

        return (
            ("myReplace", myReplace),
            ("myKey", key),
        ], sublime.INHIBIT_WORD_COMPLETIONS | sublime.INHIBIT_EXPLICIT_COMPLETIONS)
0 Likes

#4

Instead of match = re.search(regex, string) use for match in re.finditer(regex, string):. Of course, adjust your indents as you need to.

Err actually, this isn’t what you want. I’ll update it later when I have some time. You might be able to keep iterating over your snippet after each replace, continuing till match returns None.

0 Likes

#5

Try replacing the content after your regex definition and before the return statement with this.

for match in re.finditer(regex, string): key = match.group(1) string = re.sub(regex, myConfig.get(key), string, 1) myReplace = string

0 Likes

#6

Hi,

sorry for the delay.

It works perfect.

Thanks a lot!

Greets,
Marcus

0 Likes