zizhongyan / StataImproved

Improved Stata Editor for macOS : a sublime text 3 plugin
MIT License
46 stars 15 forks source link

Bug in the use of global macros #21

Open andrehofmeyr opened 3 years ago

andrehofmeyr commented 3 years ago

Hello

And thanks again for your package. I noticed some weird behaviour with global macros when I'm just free typing and want to reference a global macro. For example, suppose I want to write an "if" statement that evaluates a global. If I type "if $" then I get this: "if{newline}." Notice that the space after "if" disappears and the "}" appears on a new line. I found a workaround for this which is to type the name of the global first and then hit "$" but there are other instances where this doesn't work as I'd hoped. For example, suppose I want to use a global to open a particular dataset. I would usually type this "use Data$datano.dta, clear". But if I use the "trick" above, it does this "${Datadatano}", which is clearly not what I want.

A friend helped me to develop the following kludge to "solve" the problem:

    class StataMacro(sublime_plugin.TextCommand):
        def run(self,edit):
            sels = self.view.sel()
            for sel in sels:
                if len(sel) == 0:
                    word_sel = self.view.word(sel.a)
                else:
                    word_sel = sel
                word_str = self.view.substr(word_sel)
                lspace   = word_str.startswith(" ")
                enline   = word_str.endswith("\n")
                word_str = word_str.strip()
                word_str = "$"+word_str+""
                if lspace:
                    word_str = " " + word_str
                if enline:
                    word_str = word_str + "\n"
                self.view.replace(edit,word_sel,word_str)

I've always preferred to refer to globals just as "$globalname" and didn't actually know that one could use the syntax "${globalname}," hence that small change above.

The issue appears to be with "self.view.substr(word_sel)" so just wanted to let you know.

zizhongyan commented 3 years ago

Thanks a lot. Just a small comment on "${globalname}".

The curly brackets can be useful in some cases, so I guess it would be helpful to use ${} --- for instance, one use global to define a path (or an object) with a space (or some special) character --- in this case, one has to use ${} instead of just $. Just wonder if you have any further suggestion on including also the curly brackets?

Many thanks again.

andrehofmeyr commented 3 years ago

Ah, now I understand why you might want to use the curly brackets. @bamonroe helped me solve the issue above, and he thinks that the "real issue" lies with this: self.view.substr(word_sel). I'm not sure if you can work directly on this "self.view.substr(word_sel)", but if you can then perhaps you won't need to use the kludge that he wrote above?

Thanks again for your wonderful package.

bamonroe commented 3 years ago

Hi, I actually don't use sublime (I'm a neovim user), so I'm unfamiliar with the underlying code other than what @andrehofmeyr has pointed out to me. One can include the curly brackets in the above example, and they will show without the buggy newline wrapping, but the cursor isn't placed between them. I believe the API here expects that there will only be a single character appended to word_str for the closing pair - which makes sense in every other situation - and so after doing the replace, it moves the cursor left one character. In order to get the cursor in the right position with curly braces, the cursor needs to move left 2 characters to compensate for the newline character that is stripped from word_str, and then appended after the braces are added.

Does the edit object contain any field that determines the cursor position that can be changed to accommodate the special case here? If so, that change should be added to the if enline: block and you're good to go I think.