Skip to content

add windows support #4

Open
jlegewie opened this Issue Apr 12, 2012 · 36 comments

5 participants

@jlegewie
Owner

sublime.platform(): Returns the platform, which may be "osx", "linux" or "windows"

@FichteFoll

I can get notifications for issues / repos without having to reply to it (see "Notifications for new comments on this Issue are on/off." below) btw.

Anyway, reference link.

@jlegewie
Owner

It should be possible to add Windows support based on maComfort. Could you install maComfort version 1.5 or later (available at http://rafaelklaus.com/macomfort/) and try a couple of python commands?
I just need to know how it specify the different arguments. E.g. do I have to escape the \ for the filepath and for the executable? Is the '-ql' option correct? Note that you might have to change the location of the executable (particularly if your windows installation is not english). Let me know if I should clarify anything...

import subprocess

filepath = 'ADD PATH TO A HTML FILE HERE'
executable = ['C:\\Program Files\\maComfort\\maComfort.exe', '-ql']
args = executable + [filepath]
subprocess.Popen(args)
@FichteFoll

Works pretty well. Except that it does not display CSS background-color: rgba(); and opens IE when I click a link in there.

import subprocess

subprocess.Popen([
    r'C:\Program Files (x86)\maComfort\maComfort.exe',
    '-ql',
    r'c:\some\path\to\my.html'
])

But really, I scanned your code a bit. (Besides some really odd bits of code) it seems that your only real problem here is that you use a Mac OS-internal method for displaying an HTML file; and that distutils. There are a hundret ways of doing so, the easiest would be to just ShellExecute them and let Windows take care of running the associated application (FireFox in my case).
I have no problem with that, I don't need some special program that can preview HTML files and closes them nicely but in exchange does not support clicking any links in it (srsly, what should I do with IE?) and even blocks my Ctrl-Left/Right hotkeys for browsing my edited text in every other program. I didn't even realize that I use this so often until I couldn't use it.

Anyway, what I'm saying is: Don't use maComfort. Don't force Windows users to install an application they probably don't like (well, I don't) just for this purpose. Imagine how someone using Linux would react to that.
If you want you can even let the user specify his own program which is being run with the generated HTML as parameter.

@FichteFoll

Besides, if your generated HTML is not special or can be conveyed in textform just as well (I don't know), you could also use a sublime-internal output panel (and maybe set an invisible syntax to it if there are patterns).
For an example on that see Packages/Diff/diff.py.

@jlegewie
Owner
@FichteFoll
os.startfile(r'c:\some\path\to\my.html')

or

os.system(r'"c:\some\path\to\my.html"')

But note that these functions return immediately and do not return any object for threading or whatsoever.

I would consider forking and making a pull request by myself but unfortunately I don't really have the time for that.

@jlegewie
Owner

So I assume
subprocess.Popen([r'c:\some\path\to\my.html'])
also works? That would just make the code cleaner for cross-platform support...

@FichteFoll

No, I'm afraid.

>>> subprocess.Popen([r'"c:\some\path\to\my.html"'])
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File ".\subprocess.py", line 633, in __init__
  File ".\subprocess.py", line 842, in _execute_child
WindowsError: [Error 5] Zugriff verweigert

Translates to "Access denied".
Also note the " around the actual filepath; I have a space in my test path and when I don't use them I just get WindowsError: with no message. With os.system it just does not work with spaces but without " enclosing the parameter/file (because of the way windows handles commands). os.startfile works though.

@jlegewie
Owner

The dev branch now contains a version with initial windows and linux support. Windows support is based on os.startfile but can be changed to any executable using the custom_executable option. I am not sure that I got the whole escaping of the file location right. So it might not work at this point but you can give it a try. The relevant code is at line 151 and 175.

@FichteFoll

Some notes:

  • os.startfile('c:/some/path/to.html') works on Windows (/), you just need to be careful with os.system.
  • You can use os.path.sep or os.sep for the current OS's path separator. But I recommend to use os.path.join where possible.

And there is a problem with distutils on Windows. I don't yet understand distutils's purpose and what it does but it fails to load on my machine.

Reloading plugin C:\Users\user\AppData\Roaming\Sublime Text 2\Packages\SublimePeek\SublimePeek.py
Traceback (most recent call last):
  File ".\sublime_plugin.py", line 62, in reload_plugin
  File ".\SublimePeek.py", line 12, in <module>
    import distutils.dir_util
ImportError: No module named distutils.dir_util

See also SublimeText/PackageDev#7

@jlegewie
Owner

okay, I am now using os.path.join throughout the plugin (if I didn't miss something) and replaced distutils with shutil.copytree to copy the style files. Does that work?
It would be good to know which languages work, whether the help files for HTML, css... are created correctly, and whether the help overview feature works. I assume that python and ruby do not work because pydoc and ri. Do you know how to get that to work?

@FichteFoll

Well, nothing worked at all. I did some debugging and I was rather surprised at what level your plugin was failing.
It's in line #44, where not self.lang in self.languages would always be true - because self.get_language() does not work as expected. Here is what I used:

def get_language(self):
    lang_file = self.view.settings().get('syntax')
    _, fname  = os.path.split(lang_file)
    lang, _   = os.path.splitext(fname)
    # ...

Then, I don't have pydoc in my PATH. Configuring the launch parameter to args = ['python', r'c:\Python32\Lib\pydoc.py', '-w', keyword] worked. (Note: I have Python3.2 on my machine)
However, os.startfile(repr(self.filepath))is definitely the wrong way to go because this gives u'C:\\\\Users\\\\<me>\\\\AppData\\\\Roaming\\\\Sublime Text 2\\\\Packages\\\\SublimePeek\\\\print.html'. Yeah. Just delete the repr() call, os.startfile works with spaces.
Now it works at least. Though, modifying the self.path variable does not seem to work that well with Python syntax ... it's always C:\Users\<me>\AppData\Roaming\Sublime Text 2\Packages\SublimePeek at your os.chdir call.


Generating PHP doc worked for a while, then I got

Exception in thread Thread-15:
Traceback (most recent call last):
  File ".\threading.py", line 532, in __bootstrap_inner
  File ".\SublimePeek.py", line 543, in run
    f = open(os.path.join(self.path, id + ".html"), "w")
IOError: [Errno 22] invalid mode ('w') or filename: u'C:\\Users\\<me>\\AppData\\Roaming\\Sublime Text 2\\Packages\\SublimePeek-PHP-help\\HttpDeflateStream::__construct.html'

There are some helpfiles in the directory but sadly clicking their links does not work because they have a different naming scheme than they are named, actually.
/SublimePeek-PHP-help/function_exists.html for example links to method_exists() as SublimePeek-PHP-help/function.method-exists.php (note the "function.").


Btw I tried importing pydoc but this seems to be rather ... odd and behaves somewhat weird. But you might want to check it out at least, that would not require any cmd line call for Python help. Source: http://hg.python.org/cpython/file/2.6/Lib/pydoc.py

@jlegewie
Owner

okay, I fixed most of these problems. For pydoc, I have added a setting pydoc_call so that the user can easily set up the correct path. The default is ["pydoc", "-w"] for mac os (should also work on Linux). Just set it to
["python", r"c:\Python32\Lib\pydoc.py", "-w"] and it should work on your system. (there is also a similar ri_call setting)
The settings are now accessible through Pref.->Package Settings...

I am not sure what you mean with "modifying the self.path variable does not seem to work that well with Python syntax". For python, self.path simply sets the location where the help files are temporarily saved.

The PHP problem seems to be related to invalid filenames on windows. E.g. HttpDeflateStream::__construct.html is not valid as a filename (on mac os, the filename is changed to HttpDeflateStream\\__construct.html). I will think about a fix for that and post again. (note for myself: http://stackoverflow.com/questions/295135/turn-a-string-into-a-valid-filename-in-python)

I never tried to make the links in the help files work. I have added a ticket ( #15) for that but I probably won't get into it right now.

@jlegewie
Owner

Any opinion about encoding the filenames like this? The files itself would not be human readability though.

import base64

filename=r'HttpDeflateStream::__construct'

base64.urlsafe_b64encode(filename)
base64.urlsafe_b64decode(base64.urlsafe_b64encode(filename))

here is the output from the last two lines:
'SHR0cERlZmxhdGVTdHJlYW06Ol9fY29uc3RydWN0'
'HttpDeflateStream::__construct'

@FichteFoll

I am not sure what you mean with "modifying the self.path variable does not seem to work that well with Python syntax".

I mean that the files generated by pydoc -w are saved in /Packages/SublimePeek. I don't think this is intended. If it is, you should change it. Temp dir should be appropriate - these files are generated on the fly and there is no user access needed.

Regarding the filenames: Try just replacing invalid characters (with like _). That should work in most (if not all) cases, would be human readable and would imply the same consequences as with base64 filenames (they are not linked automatically, if they are by default that is).

@jlegewie
Owner

just a quick update: I did some changes in the background for the filename stuff but now have to finish up some other stuff and will get back to this in a while...

@cmartininfosol

Heyo, i too would love windows support, and i see progress is being made. Very awesome! So far I've simply installed the package via package control. I assume then keymap to get this going is "windowskey+shift+h"? I'm assuming that "super" could mean either the apple key for apple and the windows key for windows. I tried changing this to something simple like "f2" just to get it to work the first time, and nothing happened. I modified the Default (OSX).sublime-keymap file to read

[
{ "keys": ["f2"], "command": "sublime_peek" }
]

Restarted sublime text and still didn't get the help to show up. I figured now that the problem isn't the key binding, but something else. Then i read the above post from FichteFoll about the pydoc command not being in the path setting in windows. I see you've updated so users can configure the path to this command, but I don't know where to put it. I tried putting it into the location that you referenced "Pref.->Package Settings...." in the "Settings - Default" file, but kept getting a syntax error. Not sure what the proper syntax is, or if i'm even in the right spot. My google searches are coming up with some sort of Python.settings file maybe. But I'm not sure. Figure i better ask for some help :)

Any help would be appreciated. Looking forward to using this package with Sublime Text 2

@cmartininfosol

Okay, i'm moving closer to getting this working. I found your dev branch and installed it instead of the one from the master. Now i have the work that you've done so far to get windows supported. Right now i'm in the process of downloading the dev version of Sublime Text 2 so i can get around my issue with 'module' object has no attribute 'ok_cancel_dialog'.

@cmartininfosol

All right, seems to be working okay now. I'm sure i'm at the same point now as FichteFoll. I'll be keeping an eye for when this is "officially" released. Thanks for all your hard work. This is really sweet! :D

@jlegewie
Owner

good that you managed to run it! Maybe you can provide a short description of the steps (excluding the dev branch stuff) so that I could put that in the readme?
I assume that python works after setting the pydoc path and the other languages don't work because the downloading of the help files still fails, right? I will fix that but it might still take some time.

@cmartininfosol

Sure, until you release these changes to master people will want to start off by grabbing it from your dev branch

https://github.com/jlegewie/SublimePeek/tree/dev

After that they'll want to make sure they have Sublime Text 2 build 2187 or later. at the time i wrote this the latest stable version was 2181. See this thread for why: http://www.sublimetext.com/forum/viewtopic.php?f=3&t=7031

For me after i did those two things, i was able to use SublimePeek. Maybe pydoc was already in my path folder on my system. I didn't have to do anything. I think i had to get the python dll in my path folder for WinCVS and Mercurial migration plugin that i did a while ago.

Seems css and javascript are not working though. I'm getting the following errors in the console for Sublime Text 2

Traceback (most recent call last):
File ".\sublime_plugin.py", line 362, in run_
File ".\SublimePeek.py", line 70, in run
IOError: [Errno 2] No such file or directory: u'C:\Users\cmartin\AppData\Roaming\Sublime Text 2\Packages\SublimePeek-JavaScript-help\JavaScript-mapping.json'

and

Traceback (most recent call last):
File ".\threading.py", line 532, in __bootstrap_inner
File ".\SublimePeek.py", line 536, in run
IOError: [Errno 22] invalid mode ('w') or filename: u'C:\Users\cmartin\AppData\Roaming\Sublime Text 2\Packages\SublimePeek-CSS-help\background-clip | -moz-background-clip.html'

Seems to be related to the path thing that was mentioned above?

@cmartininfosol

Ahh i see what happened with the generated help files for javascript. It's trying to find C:\Users\cmartin\AppData\Roaming\Sublime Text 2\Packages\SublimePeek-JavaScript-help\JavaScript-mapping.json, but on my system the .json file is at:

C:\Users\cmartin\AppData\Roaming\Sublime Text 2\Packages\SublimePeek-JavaScript-helpJavaScript-mapping.json

Seems there was a missing concatenation of the '\' character when building out the JavaScript-mapping.json file

Still now sure about the css error though

@jlegewie
Owner

I fixed that particular problem (untested but it should work). So you can reinstall the dev branch version and try again. Note that you have to delete the ...\Packages\SublimePeek-JavaScript-help folder before retrying. Let me know whether it works. I think that PHP fails because of file name issues but Javascript, CSS and HTML might work. Let me know what your experience is...

@cmartininfosol

The fix you applied was for when Python help files were generated. I made your changes for javascript generation and received this error:

IOError: [Errno 2] No such file or directory: u'C:\Users\cmartin\AppData\Roaming\Sublime Text 2\Packages\SublimePeek-JavaScript-help\JavaScript-mapping.json\w'

I noted a missplaced parenthesis, so i changed the line 567 to read:

f_map = open(os.path.join(self.path, "JavaScript-mapping.json"), "w")

And it's working great now.

Still having issues with css though. Seems it's not generating the whole html set. The error is while it's generating the html when it's trying to build the file for the background-clip attribute.

@cmartininfosol

and fixed my css issue too. You had starting at line 550

#filename_valid = re.sub(r"[\\/:\"*?<>|]+", "", id)
f = open(os.path.join(self.path, id + ".html"), "w")
f.write((html_page % (id, id, html, note_content)).encode('utf-8'))
f.close()

So i changed it to:

filename_valid = re.sub(r"[\\/:\"*?<>|]+", "", id)
f = open(os.path.join(self.path, filename_valid + ".html"), "w")
f.write((html_page % (id, id, html, note_content)).encode('utf-8'))
f.close()

And that gave me the ability to generate the html file for "background-clip | -mox-backround-clip" attribute.

I suspect this code might still be experimental so I've reverted it after getting the full set of css html files :)

Now i'm not a python developer so I tried to generate the help files for that language as well. Ran into this error:

Traceback (most recent call last):
  File ".\sublime_plugin.py", line 362, in run_
  File ".\SublimePeek.py", line 68, in run
    keyword = self.create_help_file(keyword)
  File ".\SublimePeek.py", line 250, in create_help_file
    output = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0]
  File ".\subprocess.py", line 633, in __init__
  File ".\subprocess.py", line 842, in _execute_child
WindowsError: [Error 2] The system cannot find the file specified
@jlegewie
Owner

Couple of comments:
1) Good catch with the parenthesis and python. I fixed both...
2) Your fix for css might partly work but in general is not a good idea! The problem is that the plugin won't find any help file that was changed by this regular expression (re.sub line). That is the part I still have the fix for windows. The problem is further complicated because I would like to preserve the full name of the help topic for the overview, which shows up when no help is found (not for Python and Ruby though).
3) The last problem is not related with generating help files. For Python I now create the help files on the fly (the code for python in GetHelpFiles is obsolete). Does the Python help work for other keywords? Based on the error message I would rather think that the setting pydoc_call is not correct.

@cmartininfosol

Yeah, I noted that as well. I just ended up taking the one generated html file "background-clip -moz-background-clip.html" and copying it to two html files. One "background-clip.html" and the other "-moz-background-clip.html". Now i'm able to find either attribute

For the python help generation, that makes sense. So i suppose my pydoc is not setup right. When i try to use the suggested setting i get a parse error when i save the settings file.

@cmartininfosol

Okay, here's what i've found for Python for windows

I tried this setting:

"pydoc_call":["C:\\Python27\\Lib\\pydoc.py", "-w"],

But then i'd end up getting the following error:

Traceback (most recent call last):
  File ".\sublime_plugin.py", line 362, in run_
  File ".\SublimePeek.py", line 68, in run
    keyword = self.create_help_file(keyword)
  File ".\SublimePeek.py", line 257, in create_help_file
    output = subprocess.Popen([args[1], keyword], stdout=subprocess.PIPE).communicate()[0]
  File ".\subprocess.py", line 633, in __init__
  File ".\subprocess.py", line 842, in _execute_child
WindowsError: [Error 193] %1 is not a valid Win32 application

So based on the suggested I ended up using the following which started to make some progress

"pydoc_call":["C:\\Python27\\python","C:\\Python27\\Lib\\pydoc.py", "-w"],

Now i get a popup window with html that only contains the keyword. it doesn't have any "content". So i started to dig a little

I noted we'd fall into this condition check in python due to the bug of 'no Python documentation found for' because of the '-w' switch.

starting at line 256:

if 'no Python documentation found for' in output:
    output = subprocess.Popen([args[0], keyword], stdout=subprocess.PIPE).communicate()[0]
    # exit if no help found
    if 'no Python documentation found for' in output:
        return keyword
    # write html file
    output = output.replace('\n', '<br>').replace(' ', '&nbsp;')
    write_html_file(keyword, keyword, output, 'python')

return keyword

I noted that subprocess.Popen was being called with only the first value out of the new pdoc_call setting. So in my case it'd call Python.exe and it'd pass the keyword as an argument. Of course we were expecting to be passing the keyword to pydoc.py. So when i changed the script to this:

if 'no Python documentation found for' in output:
    output = subprocess.Popen([args[0], args[1], keyword], stdout=subprocess.PIPE).communicate()[0]
    # exit if no help found
    if 'no Python documentation found for' in output:
        return keyword
    # write html file
    output = output.replace('\n', '<br>').replace(' ', '&nbsp;')
    write_html_file(keyword, keyword, output, 'python')

return keyword

Of course this does mean that i've now broken it for compatibility for mac, as in that environment we're only expecting to have two values for the pydoc_call setting.

Not sure how to get all values out of a python array except the value that is "-w"

So right now I am getting python documentation to popup. Maybe using this pandoc thing might be the better option for windows users? Not sure what to set pandoc_path to.

@soulhakr

I'm not sure I understand why Windows support requires maComfort; so I'm not sure if my enhancement request to support Windows without maComfort needs to be entered as a separate issue or not. I have a windows machine at work on which I may be able to to implement this. What is needed?

@jlegewie
Owner

The maComfort thing is a little outdated. If you are on ST3, SublimePeek might already work. Just give it a try and let me know how it goes. I think PHP makes problems but the other languages work. But I am not sure...

@miguelhughes

I'm interested in having this under windows too! I think this is a great plugin and I miss having documentation inside the IDE, compared to other IDES this bridges that batch very nicely! I see these comments are a bit old. Are you interested in rekindeling this?

I ran it on windows using st3 and it runs, partially:

  • On one end: the inline help is not inline, but opens a browser. I'm ok with that, as the quick access and having it locally is more than enough.
  • On the other end, it seems that the help files I need were not entirely compiled. I use php, and some basic functions are not there, such as "mysql_num_rows" or "isset". Here is the output:

    Exception in thread Thread-6:
    Traceback (most recent call last):
    File "./threading.py", line 901, in _bootstrap_inner
    File "C:\Users\Miguel\AppData\Roaming\Sublime Text 3\Packages\SublimePeek\SublimePeek.py", line 689, in run
    f = open(os.path.join(self.path, id + ".html"), "wb")
    OSError: [Errno 22] Invalid argument: 'C:\Users\Miguel\AppData\Roaming\Sublime Text 3\Packages\SublimePeek-PHP-help\HttpDeflateStream::__construct.html'

Any suggestions?

@jlegewie
Owner

I am not going to put any major work into this right now but I am happy when others send pull requests.
By the way, you can now get the help as a tooltip. Just use the show_popup option. It's not perfect because the full html is converted to ST's mini html. Personally, I also use the Source Code Pro font, which make the tooltip look much better (see my css file below). I hope that in the future ST3 will provide an API for the new release note window (try it be clicking on "Sublime Text -> Changelog"). I think that would be the optimal solution without any external dependencies.

body {
    font-family: "Source Code Pro Light";
    color: #444444;
}
h1, h2 {
    font-family: "Source Code Pro Light";
    font-weight: Regular;
    color: #444444;
    font-size: 1.4em;
}
h3 {
    font-family: "Source Code Pro Semibold";
    color: #444444;
    font-size: 1.2em;
}
h4 {
    font-family: "Source Code Pro Medium";
    color: #444444;
    font-size: 1.2em;
}
.code {
    font-family: "Source Code Pro";
    background-color: #F2F2F2;
    color: #000000;
}
.pre {
    font-family: "Source Code Pro";
    display: block;
    background-color: #F6F6F6;
    color: #000000;
}
@miguelhughes

Thanks! Now I see it inside ST, this is awesome!
I tried your css and it looks nicer now. It corresponds in SublimePeek/css/tooltip.css, right?

Is there any chance you can provide any feedback on what could be causing the error above? Or maybe you can post a compiled php doc as you did for "R"? Or I could try and build it myself externally but it looks like the compiler doesn't work ok on windows.

@jlegewie
Owner

There is some discussion about that problem in earlier posts in the threat. Windows is not happy with the filename HttpDeflateStream::__construct.html. I never got around to fix that. The compiled php docs won't help because they would include filenames that are invalid for windows. Feel free to give it a shot!

@miguelhughes
@miguelhughes

cmartinfosol's fix worked for fixing the help file compile error. May 22, 2012. I understand it's not a good idea because those help files won't be found, but at least I get most of the functions I normally use documented.
Maybe I'll chip in in the future when I'm more familiarized with python, I'd love to help, this is so close to working on windows...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.