diff --git a/Main.sublime-menu b/Main.sublime-menu index c42a5e2..8dbf4fc 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -1,96 +1,43 @@ [ - { - "caption": "Tools", - "mnemonic": "T", - "id": "tools", - "children": - [ - { - "command": "view_in_browser", - "caption": "View in Browser" - } - ] - }, - { - "caption": "Preferences", - "mnemonic": "n", - "id": "preferences", - "children": - [ - { - "caption": "Package Settings", - "mnemonic": "P", - "id": "package-settings", - "children": - [ - { - "caption": "View in Browser", - "children": - [ - { - "command": "open_file", - "args": {"file": "${packages}/View In Browser/View In Browser.sublime-settings"}, - "caption": "Settings – Default" - }, - { - "command": "open_file", - "args": {"file": "${packages}/User/View In Browser.sublime-settings"}, - "caption": "Settings – User" - }, - { "caption": "-" }, - { - "command": "open_file", - "args": { - "file": "${packages}/View in Browser/Default (OSX).sublime-keymap", - "platform": "OSX" - }, - "caption": "Key Bindings – Default" - }, - { - "command": "open_file", - "args": { - "file": "${packages}/View in Browser/Default (Linux).sublime-keymap", - "platform": "Linux" - }, - "caption": "Key Bindings – Default" - }, - { - "command": "open_file", - "args": { - "file": "${packages}/View in Browser/Default (Windows).sublime-keymap", - "platform": "Windows" - }, - "caption": "Key Bindings – Default" - }, - { - "command": "open_file", - "args": { - "file": "${packages}/User/Default (OSX).sublime-keymap", - "platform": "OSX" - }, - "caption": "Key Bindings – User" - }, - { - "command": "open_file", - "args": { - "file": "${packages}/User/Default (Linux).sublime-keymap", - "platform": "Linux" - }, - "caption": "Key Bindings – User" - }, - { - "command": "open_file", - "args": { - "file": "${packages}/User/Default (Windows).sublime-keymap", - "platform": "Windows" - }, - "caption": "Key Bindings – User" - }, - { "caption": "-" } - ] - } - ] - } - ] - } + { + "caption": "Tools", + "mnemonic": "T", + "id": "tools", + "children": [ + { + "command": "view_in_browser", + "caption": "View in Browser" + } + ] + }, + { + "caption": "Preferences", + "mnemonic": "n", + "id": "preferences", + "children": [ + { + "caption": "Package Settings", + "mnemonic": "P", + "id": "package-settings", + "children": [ + { + "caption": "View in Browser", + "children": [ + { + "command": "open_file", + "args": {"file": "${packages}/View In Browser/View In Browser.sublime-settings"}, + "caption": "Settings – Default" + }, + { + "command": "open_file", + "args": {"file": "${packages}/User/View In Browser.sublime-settings"}, + "caption": "Settings – User" + }, + { "caption": "-" } + ] + } + ] + } + ] + } ] diff --git a/README.md b/README.md index 99f8e23..a0d124e 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,35 @@ # Sublime Text - View In Browser *View In Browser* is a Sublime Text plugin that will open whatever is in your -current view/tab. If the file current open is new and has not been saved a temporary -file is created (in your default temp directory for your OS) with the extension of -**.htm** and your browser will open it. However if the current open file is saved -and has a name this plugin will open it in whatever you have set to handle -its type. +current view/tab. If the file current open is new and has not been saved a temporary file is created (in your default temp directory for your OS) with the extension of **.htm** and your browser will open it. However if the current open file is saved and has a name this plugin will open it in whatever you have set to handle its type. By default the keystroke assigned to this plugin is *CTRL + ALT + V*. ## Installation -Using the Sublime Text Package Control plugin (http://wbond.net/sublime_packages/package_control) -press *CTRL + SHIFT + P* and find **Package Control: Install Package** and press *Enter*. -Find this plugin in the list by name **View In Browser**. +Using the Sublime Text Package Control plugin (http://wbond.net/sublime_packages/package_control) press *CTRL + SHIFT + P* and find **Package Control: Install Package** and press *Enter*. Find this plugin in the list by name **View In Browser**. ## Configuring Browsers By default this plugin will open files in Firefox. You can configure it to open using another browser of your choice. To do this, choose *Settings - User* from *Preferences > Package Settings > View In Browser*. -The browser you wish to use to open files is set in the key named **selectedBrowser**. The list of browsers -you can use and configure are in the key named **supportedBrowsers**. +The browser you wish to use to open files is set in the key named **browser**. The following is a list of browsers configured for use out of the box. -The **supportedBrowsers** values can be configured to have paths to your browser installations. -Each browser listed is an array (list) of configurations that allow you to setup a browser -for multiple operating systems. For example under *chrome* there are two configurations. -The first is for your average Linux system. The second is for Windows. +* Firefox - Mac OS, Linux, Windows +* Chrome - Mac OS, Linux, Windows +* Chrome64 - Windows +* Safari - Mac OS +* Internet Explorer - Windows +* Chromium - Linux ## Other Browsers -View In Browser also provides key bindings to open your current view in browser other than -your **selectedBrowser**. Below is a listing of the keys and what browser open with -those key bindings. +View In Browser also provides key bindings to open your current view in browser other than your **browser** setting. Below is a listing of the keys and what browser open with those key bindings. * *CTRL + ALT + F* - Firefox * *CTRL + ALT + C* - Chrome * *CTRL + ALT + I* - Internet Explorer * *CTRL + ALT + S* - Safari -Like any other key binding in Sublime these can be changed. Below is an example of the -key configuration. You can remap these in your User key bindings configuration file. +Like any other key binding in Sublime these can be changed. Below is an example of the key configuration. You can remap these in your User key bindings configuration file. ```javascript [ @@ -50,11 +42,7 @@ key configuration. You can remap these in your User key bindings configuration f ``` ### Windows Considerations -One of the things you may notice in the Windows configuration for *chrome* is a variable in -the command path that looks like: **%Local AppData%**. This is a reference to your Windows -installation's **AppData** folder in your user profile directory. There is a variable -there because this value will differ for each user on your computer, and Chrome installs -to your **AppData** folder. +One of the things you may notice in the Windows configuration for *chrome* is a variable in the command path that looks like: **%Local AppData%**. This is a reference to your Windows installation's **AppData** folder in your user profile directory. There is a variable there because this value will differ for each user on your computer, and Chrome installs to your **AppData** folder. Here is a list of supported variables: @@ -67,19 +55,12 @@ Here is a list of supported variables: * **My Pictures** - Path to your pictures location * **My Music** - Path to your music location -Note that many of these are not terribly useful for determining browser location, unless you -have decided to install Firefox in your My Music folder. - +Note that many of these are not terribly useful for determining browser location, unless you have decided to install Firefox in your My Music folder. ## Configure to View on Local Server -The View In Browser plugin also supports the ability to view files in the context of -a local server. So if you have a local Apache, Tomcat, or some other server application running -you can configure this plugin to open your file prefixed with a URL. +The View In Browser plugin also supports the ability to view files in the context of a local server. So if you have a local Apache, Tomcat, or some other server application running you can configure this plugin to open your file prefixed with a URL. -To configure this the View In Browser plugin reads the configuration of your currently -loaded project. You can edit a project file by opening the *sublime-project* file -by choosing **Project** -> **Edit Project**. In your project file you will need to specify -two things: +To configure this the View In Browser plugin reads the configuration of your currently loaded project. You can edit a project file by opening the *sublime-project* file by choosing **Project** -> **Edit Project**. In your project file you will need to specify two things: * **baseUrl** - The root URL to prefix files with * **basePath** - The base path where your site/application lives @@ -103,15 +84,16 @@ Here's how that looks. } ``` -Notice the key named **settings** which is a dictionary that contains another key named -**sublime-view-in-browser**. This is where you will put your **baseUrl** and **basePath** -settings. +Notice the key named **settings** which is a dictionary that contains another key named **sublime-view-in-browser**. This is where you will put your **baseUrl** and **basePath** settings. -Now when you activate View In Browser your file will open with the HTTP protocol instead -of the FILE protocol. +Now when you activate View In Browser your file will open with the HTTP protocol instead of the FILE protocol. ## Change History +* 10/06/2014: + * Rewrite for version 2.0.0 + * Using subprocess instead of webbrowser. Seems to solve #19 + * Smaller, simplier sublime-settings file * 05/15/2014: * Current view only saves if there are modifications * 07/03/2013: diff --git a/View In Browser.sublime-settings b/View In Browser.sublime-settings index 0e26057..93db388 100644 --- a/View In Browser.sublime-settings +++ b/View In Browser.sublime-settings @@ -1,61 +1,27 @@ { - "supportedBrowsers": { - "firefox": [ - { - "osname": "posix", - "platform": ".*", - "command": "firefox" - }, - { - "osname": "posix", - "platform": "darwin", - "command": "open -a \"/Applications/Firefox.app\"" - }, - { - "osname": "nt", - "platform": "win32", - "command": "C:/Program Files (x86)/Mozilla Firefox/firefox.exe" - } - ], - "safari": [ - { - "osname": "posix", - "platform": "darwin", - "command": "open -a \"/Applications/Safari.app\"" - } - ], - "iexplore": [ - { - "osname": "nt", - "platform": "win32", - "command": "C:/Program Files/Internet Explorer/iexplore.exe" - } - ], - "chrome": [ - { - "osname": "posix", - "platform": "darwin", - "command": "open -a \"/Applications/Google Chrome.app\"" - }, - { - "osname": "posix", - "platform": "linux.*", - "command": "google-chrome" - }, - { - "osname": "nt", - "platform": "win32", - "command": "%Local AppData%/Google/Chrome/Application/chrome.exe" - } - ], - "chromium": [ - { - "osname": "posix", - "platform": "linux.*", - "command": "chromium" - } - ] + "posix": { + "linux": { + "firefox": "firefox -new-tab", + "chrome": "google-chrome", + "chrome64": "google-chrome", + "chromium": "chromium" + }, + + "darwin": { + "firefox": "open -a \"/Applications/Firefox.app\"", + "safari": "open -a \"/Applications/Safari.app\"", + "chrome": "open -a \"/Applications/Google Chrome.app\"", + "chrome64": "open -a \"/Applications/Google Chrome.app\"" + } + }, + "nt": { + "win32": { + "firefox": "C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe -new-tab", + "iexplore": "C:\\Program Files\\Internet Explorer\\iexplore.exe", + "chrome": "%Local AppData%\\Google\\Chrome\\Application\\chrome.exe", + "chrome64": "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" + } }, - "selectedBrowser": "firefox" + "browser": "firefox" } \ No newline at end of file diff --git a/ViewInBrowser.sublime-commands b/ViewInBrowser.sublime-commands index f880011..b079551 100644 --- a/ViewInBrowser.sublime-commands +++ b/ViewInBrowser.sublime-commands @@ -1,3 +1,3 @@ [ - { "caption": "View In Browser", "command": "view_in_browser" } + { "caption": "View In Browser", "command": "view_in_browser" } ] diff --git a/ViewInBrowserCommand.py b/ViewInBrowserCommand.py index 64cabf4..bcaf41f 100644 --- a/ViewInBrowserCommand.py +++ b/ViewInBrowserCommand.py @@ -1,6 +1,11 @@ # # History: # +# 10/06/2014: +# - Rewrite for version 2.0.0 +# - Using subprocess instead of webbrowser. Seems to solve #19 +# - Smaller, simplier sublime-settings file +# # 05/15/2014: # - Current view only saves if there are modifications # @@ -34,149 +39,69 @@ # - Initial code # import os -import re import sys +import re import json +import urllib import sublime import tempfile +import subprocess import sublime_plugin import webbrowser -PLUGIN_DIRECTORY = os.getcwd() +PLUGIN_VERSION = "2.0.0" class ViewInBrowserCommand(sublime_plugin.TextCommand): - _settings = None - _browserCommand = "" - _windowsFolders = {} - _requestedBrowser = None - _pythonVersion = sys.version_info[0] - def run(self, edit, browser=None): - print("Python version {0}".format(self._pythonVersion)) - - projectSettings = self.view.settings().get("sublime-view-in-browser") - self._requestedBrowser = browser - - # - # Load settings, if any - # - self._loadSettings(self.view) - - # - # Attempt to open the file in the selected view. If there isn't a saved - # file there save it to a temporary location. - # - fileToOpen = self.view.file_name() - - # - # If we've specified settings for a local server environment - # use them - # - if projectSettings: - fileToOpen = re.sub(r"\\", "/", fileToOpen.replace(projectSettings["basePath"], projectSettings["baseUrl"])) - - if fileToOpen == None: - # - # Create a temporary file to hold our contents - # - tempFile = tempfile.NamedTemporaryFile(suffix = ".htm", delete = False) - - # - # Get the contents of the current view - # - region = sublime.Region(0, self.view.size()) - text = self.view.substr(region) - - tempFile.write(text.encode('utf-8')) - tempFile.close() - - fileToOpen = tempFile.name - else: - # - # Ensure the current view is saved - # - if self.view.is_dirty(): - print("File %s is dirty. Saving..." % (fileToOpen,)) - self.view.window().run_command("save") - - - # - # And open. If the settings file contains a valid selected browser use that - # command to open this file. Otherwise use the system default. - # - print("Opening ", fileToOpen) - - if self._browserCommand: - command = "%s %%s" % self._browserCommand - print(command) + # + # Takes a Windows variable, such as %APPDATA% and get the + # proper path. + # + def expandWindowsUserShellFolder(self, command): + browserCommand = "" - if self._pythonVersion < 3: - b = webbrowser.get(command.encode()) - b.open_new_tab(fileToOpen.encode()) - else: - b = webbrowser.get(command) - b.open_new_tab(fileToOpen) + windowsFolders = self.getWindowsUserShellFolders() + specialFolder = re.sub(r"%([A-Za-z\s]+)%.*", "\\1", command) + if specialFolder != command: + expandedFolder = windowsFolders[specialFolder].replace("\\", "\\\\") + browserCommand = re.sub(r"%[A-Za-z\s]+%(.*)", "%s\\1" % expandedFolder, command) else: - if self._pythonVersion < 3: - webbrowser.open_new_tab(fileToOpen.encode()) - else: - webbrowser.open_new_tab(fileToOpen) + browserCommand = command - def _loadSettings(self, view): - self._browserCommand = "" - self._settings = sublime.load_settings("View In Browser.sublime-settings") + return browserCommand.encode("ascii", "ignore") if self._pythonVersion < 3 else browserCommand - if self._settings: - if self._settings.has("selectedBrowser"): - osname = os.name - platform = sys.platform - - # - # If a specific browser was requested through the keystroke command - # use it. Otherwise default to the browser in the settings. - # - if self._requestedBrowser is not None: - selectedBrowser = self._requestedBrowser - else: - selectedBrowser = self._settings.get("selectedBrowser") - - - supportedBrowsers = self._settings.get("supportedBrowsers") - - if not selectedBrowser in supportedBrowsers: - raise Exception("The selected browser '%s' is not supported" % selectedBrowser) - - for env in supportedBrowsers[selectedBrowser]: - print("OS name: %s, Platform: %s" % (env["osname"], env["platform"])) + # + # Returns the correct base command. + # + def getBaseCommand(self, command, osName): + baseCommand = command - if type(env["command"]) == list: - for cmd in env["command"]: - if os.path.exists(cmd): - env["command"] = cmd - break + if osName == "nt": + baseCommand = self.expandWindowsUserShellFolder(baseCommand) - if re.match(env["osname"], osname) and re.match(env["platform"], platform): - print("Match! %s" % env["command"]) + return baseCommand - if env["osname"] == "nt": - self._windowsFolders = self.getUserShellFolders() - specialFolder = re.sub(r"%([A-Za-z\s]+)%.*", "\\1", env["command"]) + # + # Return the name of the running operating system. + # i.e. darwin, nt, linux + # + def getOsName(self): + return os.name - if specialFolder != env["command"]: - browserCommand = re.sub(r"%[A-Za-z\s]+%(.*)", "%s\\1" % self._windowsFolders[specialFolder], env["command"]) - else: - browserCommand = env["command"] - self._browserCommand = re.sub(r"\\", "/", browserCommand) - else: - self._browserCommand = env["command"] + # + # Get the current running platform. i.e. + # posix, win32 + # + def getPlatform(self): + return sys.platform # # Thanks to the Python for Windows site for this snippet. # http://win32com.goermezer.de/content/view/221/285/ # - def getUserShellFolders(self): + def getWindowsUserShellFolders(self): # Routine to grab all the Windows Shell Folder locations from the registry. If successful, returns dictionary # of shell folder locations indexed on Windows keyword for each; otherwise, returns an empty dictionary. if self._pythonVersion < 3: @@ -206,7 +131,7 @@ def getUserShellFolders(self): try: for i in range(0, _winreg.QueryInfoKey(Key)[1]): name, value, val_type = _winreg.EnumValue(Key, i) - return_dict[name] = value + return_dict[name] = value.encode("ascii") i += 1 _winreg.CloseKey(Key) # Only use with for loop _winreg.CloseKey(Hive) # Only use with for loop @@ -217,3 +142,117 @@ def getUserShellFolders(self): _winreg.CloseKey(Key) _winreg.CloseKey(Hive) return {} + + def giveFileAProjectPath(self, fileToOpen, basePath, baseUrl): + return re.sub(r"\\", "/", fileToOpen.replace(basePath, baseUrl)) + + def loadPluginSettings(self, defaultBrowser): + result = { + "browser": "", + "baseCommand": "" + } + + # + # Load default/user settings. The browser choice may + # be overridden by custom commands. + # + settings = sublime.load_settings("View In Browser.sublime-settings") + + if not defaultBrowser: + result["browser"] = settings.get("browser") + else: + result["browser"] = defaultBrowser + + # + # Get the correct command based on platform and OS + # + osName = self.getOsName() + platform = self.getPlatform() + + selectedOs = settings.get(osName) + result["baseCommand"] = self.getBaseCommand(selectedOs[platform][result["browser"]], osName) + + return result + + def loadProjectSettings(self, view): + return view.settings().get("sublime-view-in-browser") + + def normalizePath(self, fileToOpen): + fileToOpen = fileToOpen.replace("\\", "/") + fileToOpen = "file:///%s" % fileToOpen.replace(" ", "%20") + + return fileToOpen + + def openBrowser(self, command, osName): + useShell = False if osName != "posix" else True + subprocess.Popen(command, shell=useShell) + + def run(self, edit, browser=None): + print("View In Browser plugin v{0}, Python {1}".format(PLUGIN_VERSION, self._pythonVersion)) + + # + # Load plugin settings and project settings, if any. A project settings may + # affect the file to open based on local server + # environment settings. + # + pluginSettings = self.loadPluginSettings(browser) + projectSettings = self.loadProjectSettings(self.view) + + fileToOpen = self.view.file_name() + + # + # If we've specified settings for a local server environment + # use them + # + if projectSettings: + fileToOpen = self.giveFileAProjectPath(fileToOpen, projectSettings["basePath"], projectSettings["baseUrl"]) + + # + # If the current view has not been saved, put it into + # a temp file and open that instead. If the view + # DOES have a name make sure it is save before + # opening. + # + if fileToOpen == None: + fileToOpen = self.normalizePath(self.saveCurrentViewInTempFile(self.view)) + + else: + if self.view.is_dirty(): + print("File %s is dirty. Saving..." % (fileToOpen,)) + self.view.window().run_command("save") + + if not projectSettings: + fileToOpen = self.normalizePath(fileToOpen) + + # + # And open. If the settings file contains a valid selected browser use that + # command to open this file. Otherwise use the system default. + # + if pluginSettings["baseCommand"]: + command = "%s %s" % (pluginSettings["baseCommand"], fileToOpen.encode(sys.getfilesystemencoding()) if self._pythonVersion < 3 else fileToOpen,) + + print(command) + self.openBrowser(command, self.getOsName()) + + else: + if self._pythonVersion < 3: + webbrowser.open_new_tab(fileToOpen.encode(sys.getfilesystemencoding())) + else: + webbrowser.open_new_tab(fileToOpen) + + def saveCurrentViewInTempFile(self, view): + # + # Create a temporary file to hold our contents + # + tempFile = tempfile.NamedTemporaryFile(suffix = ".htm", delete = False) + + # + # Get the contents of the current view + # + region = sublime.Region(0, view.size()) + text = view.substr(region) + + tempFile.write(text.encode("utf-8")) + tempFile.close() + + return tempFile.name diff --git a/messages.json b/messages.json new file mode 100644 index 0000000..aac6513 --- /dev/null +++ b/messages.json @@ -0,0 +1,3 @@ +{ + "2.0.0": "messages/2.0.0.txt" +} \ No newline at end of file diff --git a/messages/2.0.0.txt b/messages/2.0.0.txt new file mode 100644 index 0000000..60b3727 --- /dev/null +++ b/messages/2.0.0.txt @@ -0,0 +1,3 @@ +This version is reworked to address issues where Sublime would hang when opening new browser windows. The format for the sublime-settings file is also new and more compact and efficient. Please note that if you had any customization against this they may no longer function. User settings files may need to be redone against the new format. + +I apologize for any inconvenience and thank you for using View In Browser! \ No newline at end of file diff --git a/settings.json b/settings.json deleted file mode 100644 index ca4afd8..0000000 --- a/settings.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "supportedBrowsers": { - "firefox": [ - { - "osname": ".*", - "platform": ".*", - "command": "firefox" - } - ], - "safari": [ - { - "osname": "posix", - "platform": "darwin", - "command": "open -a safari" - } - ], - "iexplore": [ - { - "osname": "nt", - "platform": "win32", - "command": "%PROGRAMFILES%/Internet Explorer/iexplore.exe" - } - ], - "chrome": [ - { - "osname": "posix", - "platform": "linux.*", - "command": "google-chrome" - }, - { - "osname": "nt", - "platform": "win32", - "command": "%USERPROFILE%/AppData/Local/Google/Chrome/Application/chrome.exe" - } - ], - "chromium": [ - { - "osname": "posix", - "platform": "linux.*", - "command": "chromium" - } - ] - }, - - "selectedBrowser": "firefox" -}