├── .travis.yml ├── Conda (Linux).sublime-settings ├── Conda (OSX).sublime-settings ├── Conda (Windows).sublime-settings ├── Conda.sublime-build ├── Default.sublime-commands ├── LICENSE ├── Main.sublime-menu ├── README.rst ├── commands.py ├── dependencies.json ├── header.png ├── messages.json └── messages ├── install.txt ├── v0.1.2.txt ├── v0.1.3.txt ├── v0.1.4.txt ├── v0.2.0.txt ├── v0.2.1.txt ├── v0.3.0.txt ├── v0.3.1.txt ├── v0.4.0.txt ├── v0.4.1.txt ├── v0.4.2.txt ├── v0.4.3.txt ├── v0.4.4.txt ├── v0.4.5.txt ├── v0.4.6.txt ├── v0.5.0.txt ├── v0.5.1.txt ├── v0.5.2.txt ├── v0.6.0.txt ├── v0.6.1.txt ├── v0.7.0.txt ├── v0.8.0.txt ├── v0.9.0.txt └── v0.9.1.txt /.travis.yml: -------------------------------------------------------------------------------- 1 | notifications: 2 | email: false 3 | 4 | language: python 5 | 6 | python: 7 | - '3.5' 8 | - '3.6' 9 | - '3.7' 10 | - '3.8' 11 | 12 | install: 13 | - pip install st-package-reviewer 14 | 15 | script: 16 | - st_package_reviewer . -------------------------------------------------------------------------------- /Conda (Linux).sublime-settings: -------------------------------------------------------------------------------- 1 | // Default Linux settings for sublime-text-conda: 2 | { 3 | // executable is the path to anaconda's python 4 | // this python executable is used in order to find conda 5 | "executable": "~/anaconda3/bin/python3", 6 | 7 | // Directory in which the conda envs are stored 8 | // Default location is the user's home directory 9 | "environment_directory": "~/anaconda3/envs/", 10 | 11 | // System architecture for Python installation 12 | // options: 32 or 64 bit 13 | "architecture": "64", 14 | 15 | // configuration is the path to conda's configuration file 16 | "configuration": "~/.condarc", 17 | 18 | // open repl in second row tab below current file, 19 | // closing any existing tabs in that area 20 | // assumes files are kept in group 0 (typical) 21 | "repl_open_row": false, 22 | 23 | // when opening a repl using repl_open_row, close any 24 | // existing conda repls in the second row first 25 | "repl_row_close_existing": false, 26 | 27 | // save the current file (if dirty) when opening repl 28 | "repl_save_dirty": true, 29 | 30 | // syntax highlighting for Open REPL command 31 | // choice between 'python' and 'plaintext' 32 | "repl_syntax": "python" 33 | } 34 | -------------------------------------------------------------------------------- /Conda (OSX).sublime-settings: -------------------------------------------------------------------------------- 1 | // Default OSX settings for sublime-text-conda: 2 | { 3 | // executable is the path to anaconda's python 4 | // this python executable is used in order to find conda 5 | "executable": "~/anaconda3/bin/python3", 6 | 7 | // Directory in which the conda envs are stored 8 | // Default location is the user's home directory 9 | "environment_directory": "~/anaconda3/envs/", 10 | 11 | // System architecture for Python installation 12 | // options: 32 or 64 bit 13 | "architecture": "64", 14 | 15 | // configuration is the path to conda's configuration file 16 | "configuration": "~/.condarc", 17 | 18 | // open repl in second row tab below current file, 19 | // closing any existing tabs in that area 20 | // assumes files are kept in group 0 (typical) 21 | "repl_open_row": false, 22 | 23 | // when opening a repl using repl_open_row, close any 24 | // existing conda repls in the second row first 25 | "repl_row_close_existing": false, 26 | 27 | // save the current file (if dirty) when opening repl 28 | "repl_save_dirty": true, 29 | 30 | // syntax highlighting for Open REPL command 31 | // choice between 'python' and 'plaintext' 32 | "repl_syntax": "python" 33 | } 34 | -------------------------------------------------------------------------------- /Conda (Windows).sublime-settings: -------------------------------------------------------------------------------- 1 | // Default Windows settings for sublime-text-conda: 2 | { 3 | // executable is the path to anaconda's python 4 | // this python executable is used in order to find conda 5 | "executable": "~\\Anaconda3\\python.exe", 6 | 7 | // Directory in which the conda envs are stored 8 | // Default location is the user's home directory 9 | "environment_directory": "~\\Anaconda3\\envs\\", 10 | 11 | // System architecture for Python installation 12 | // options: 32 or 64 bit 13 | "architecture": "64", 14 | 15 | // configuration is the path to conda's configuration file 16 | "configuration": "~\\.condarc", 17 | 18 | // when true, the scripts will be run through the shell 19 | // If your code has a GUI (e.g. a matplotlib plot), 20 | // this needs to be true, otherwise Windows suppresses it. 21 | "run_through_shell": false, 22 | 23 | // when true, the script execution will be handed over to 24 | // the pythonw executable, instead of python 25 | "use_pythonw": false, 26 | 27 | // open repl in second row tab below current file, 28 | // closing any existing tabs in that area 29 | // assumes files are kept in group 0 (typical) 30 | "repl_open_row": false, 31 | 32 | // when opening a repl using repl_open_row, close any 33 | // existing conda repls in the second row first 34 | "repl_row_close_existing": false, 35 | 36 | // save the current file (if dirty) when opening repl 37 | "repl_save_dirty": true, 38 | 39 | // syntax highlighting for Open REPL command 40 | // choice between 'python' and 'plaintext' 41 | "repl_syntax": "python" 42 | } 43 | -------------------------------------------------------------------------------- /Conda.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | // target uses the ExecuteCondaEnvironmentCommand found in commands.py 3 | "target": "execute_conda_environment", 4 | "cmd": ["python", "-u", "$file"], 5 | "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)", 6 | "selector": "source.python", 7 | "env": {"PYTHONIOENCODING": "utf-8"}, 8 | "cancel": {"kill": true} 9 | } 10 | -------------------------------------------------------------------------------- /Default.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | { "caption": "Conda: Create Environment", "command": "create_conda_environment" }, 3 | { "caption": "Conda: Remove Environment", "command": "remove_conda_environment" }, 4 | { "caption": "Conda: List Environments", "command": "list_conda_environment" }, 5 | { "caption": "Conda: Activate Environment", "command": "activate_conda_environment" }, 6 | { "caption": "Conda: Deactivate Environment", "command": "deactivate_conda_environment" }, 7 | { "caption": "Conda: Open REPL", "command": "open_conda_repl" }, 8 | { "caption": "Conda: List Packages", "command": "list_conda_package" }, 9 | { "caption": "Conda: Install Package", "command": "install_conda_package" }, 10 | { "caption": "Conda: Remove Package", "command": "remove_conda_package" }, 11 | { "caption": "Conda: Search Package", "command": "search_conda_package" }, 12 | { "caption": "Conda: List Channel Sources", "command": "list_conda_channels" }, 13 | { "caption": "Conda: Add Channel Source", "command": "add_conda_channel" }, 14 | { "caption": "Conda: Remove Channel Source", "command": "remove_conda_channel" } 15 | ] 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Mandeep Bhutani 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /Main.sublime-menu: -------------------------------------------------------------------------------- 1 | [{ 2 | "caption": "Preferences", 3 | "id": "preferences", 4 | "mnemonic": "n", 5 | "children": [{ 6 | "caption": "Package Settings", 7 | "id": "package-settings", 8 | "mnemonic": "P", 9 | "children": [{ 10 | "caption": "Conda", 11 | "children": [ 12 | { 13 | "caption": "Settings", 14 | "command": "edit_settings", 15 | "args": 16 | { 17 | "base_file": "${packages}/Conda/Conda (${platform}).sublime-settings", 18 | "default": "{\n\t$0\n}\n" 19 | } 20 | } 21 | ] 22 | }] 23 | }] 24 | }] 25 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | .. image:: header.png 2 | 3 | |travis| |release| |downloads| |license| 4 | 5 | sublime-text-conda is a Sublime Text plugin that allows users to work with conda 6 | directly within Sublime Text. Features include creating and removing conda environments, 7 | activating and deactivating conda environments, and installing and removing conda 8 | packages. 9 | 10 | Installation 11 | ============ 12 | 13 | sublime-text-conda can be found on the Package Control repository. To install the plugin 14 | via Package Control, open the command palette, select `Package Control: Install Package` 15 | and search for `conda`. Package Control will then install the plugin and the plugin 16 | settings will be located in the `Package Settings` submenu. 17 | 18 | If you would rather install from source, simply run:: 19 | 20 | $ git clone git@github.com:mandeep/sublime-text-conda.git Conda 21 | 22 | inside the Sublime Text packages folder. To find this folder, open Sublime Text and click 23 | on `Preferences->Browse Packages`. Cloning in this directory will manually install the plugin. 24 | 25 | For more information please visit https://www.sublimetext.com/docs/3/packages.html 26 | 27 | Settings 28 | ======== 29 | 30 | The settings file can be found in `Preferences->Package Settings->Conda->Settings - Default`. The 31 | paths may need to be changed depending on where you've installed anaconda/miniconda. For Windows 32 | users, the additional settings of `run_through_shell` and `use_pythonw` are available for when 33 | working on projects that require a GUI to open (such as showing a matplotlib plot). 34 | 35 | Usage 36 | ===== 37 | 38 | Once installed, a ``Conda`` build system will appear in the build sytem menu and conda's commands will be located inside the command palette. The ``Conda`` build system must be selected in order to use the commands. These commands include ``Create Environment``, ``Remove Environment``, ``List Environments``, ``Activate Environment``, ``Deactivate Environment`` ``Open REPL``, ``Install Package``, ``Remove Package``, ``List Packages``, ``Add Channel Source``, ``Remove Channel Source``, and ``List Channel Sources``. Command names for key bindings can be found `here `_. 39 | 40 | **Conda: Create Environment** 41 | 42 | When selected from the command palette, `Conda: Create Environment` will provide an 43 | input box for the name of the desired conda environment to create. Next, the command 44 | palette will show the allowed Python versions to be used in the environment. Once the 45 | Python version is selected, conda will create the specified environment. 46 | 47 | **Conda: Remove Environment** 48 | 49 | When selected from the command palette, `Conda: Remove Environment` will show all 50 | available conda environments that are able to be removed. Once the environment 51 | is selected, the build output will show the progress of the removal. 52 | 53 | **Conda: List Environments** 54 | 55 | When selected from the command palette, `Conda: List Environments` will display 56 | inside the command palette all available conda environments. 57 | 58 | **Conda: Activate Environment** 59 | 60 | When selected from the command palette, `Conda: Activate Environment` will 61 | display in the command pallete a list of available conda environments to be 62 | activated. The selected conda environment will then be used in the build system. 63 | 64 | **Conda: Deactivate Environment** 65 | 66 | When selected from the command palette, `Conda: Dectivate Environment` will 67 | display in the command palette the current active environment. When the environment 68 | is selected, the build system will revert back to the Python that is located on PATH. 69 | 70 | **Conda: Open REPL** 71 | 72 | When selected from the command palette, `Conda: Open REPL` will 73 | open a REPL tab with the currently opened file within the activated Conda 74 | environment. 75 | 76 | **Conda: Install Package** 77 | 78 | When selected from the command palette, `Conda: Install Package` will provide an 79 | input box for the name of the desired package to install. Once the package name 80 | is typed, the build output will show the package installation progress. 81 | 82 | **Conda: Remove Package** 83 | 84 | When selected from the command palette, `Conda: Remove Package` will display in 85 | the command palette, all available packages in the current conda environment. Once 86 | the package is selected, the build output will show the package removal progress. 87 | 88 | **Conda: List Packages** 89 | 90 | When selected from the command palette, `Conda: List Packages` will display 91 | inside the command palette all available packages inside the current conda 92 | environment. 93 | 94 | **Conda: Add Channel Source** 95 | 96 | When selected from the command palette, `Conda: Add Channel Source` will provide an 97 | input box for the name of the desired channel to add. Once the channel 98 | is typed, the build output will show the channel source progress. 99 | 100 | **Conda: Remove Channel Source** 101 | 102 | When selected from the command palette, `Conda: Remove Channel Source` will display 103 | inside the command palette all available channel sources to remove. Once clicked, 104 | the selected channel source remove from the conda configuration file. 105 | 106 | **Conda: List Channel Sources** 107 | 108 | When selected from the command palette, `Conda: List Channel Sources` will display 109 | inside the command palette all channel sources listed inside the conda configuration 110 | file. 111 | 112 | .. |travis| image:: https://img.shields.io/travis/mandeep/sublime-text-conda/master.svg?style=flat-square 113 | :target: https://travis-ci.org/mandeep/sublime-text-conda 114 | 115 | .. |release| image:: https://img.shields.io/github/release/mandeep/sublime-text-conda.svg?style=flat-square 116 | :target: https://github.com/mandeep/sublime-text-conda/releases 117 | 118 | .. |license| image:: https://img.shields.io/github/license/mandeep/sublime-text-conda.svg?style=flat-square 119 | :target: https://github.com/mandeep/sublime-text-conda/blob/master/LICENSE 120 | 121 | .. |downloads| image:: https://img.shields.io/packagecontrol/dt/Conda.svg?style=flat-square 122 | :alt: Package Control 123 | :target: https://packagecontrol.io/packages/Conda 124 | -------------------------------------------------------------------------------- /commands.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | import platform 5 | 6 | import json 7 | import requests 8 | import re 9 | 10 | import sublime 11 | import sublime_plugin 12 | 13 | 14 | class CondaCommand(sublime_plugin.WindowCommand): 15 | """Contains all of the attributes that will be inherited by other commands.""" 16 | 17 | @property 18 | def settings(self): 19 | """Load the platform-specific plugin settings for commands to use.""" 20 | env_vars = self.window.extract_variables() 21 | filename = 'Conda (${platform}).sublime-settings' 22 | expanded = sublime.expand_variables(filename, env_vars) 23 | return sublime.load_settings(expanded) 24 | 25 | @property 26 | def executable(self): 27 | """Retrieve the python executable path from settings.""" 28 | return os.path.expanduser(self.settings.get('executable')) 29 | 30 | @property 31 | def configuration(self): 32 | """Retrieve the conda configuration file from settings.""" 33 | return os.path.expanduser(self.settings.get('configuration')) 34 | 35 | @property 36 | def base_directory(self): 37 | """Retrieve the directory of conda's base environment.""" 38 | if sys.platform == 'win32': 39 | base_directory = os.path.dirname(self.executable) 40 | else: 41 | base_directory = os.path.dirname(self.executable).rstrip('bin') 42 | 43 | return base_directory 44 | 45 | @property 46 | def conda_environments(self): 47 | """Find all conda environments in the specified directory.""" 48 | try: 49 | directory = os.path.expanduser(self.settings.get('environment_directory')) 50 | 51 | environments = [['base', self.base_directory]] 52 | environments.extend([[environment, os.path.join(directory, environment)] 53 | for environment in os.listdir(directory)]) 54 | 55 | return environments 56 | 57 | except FileNotFoundError: 58 | return [['base', self.base_directory]] 59 | 60 | @property 61 | def project_data(self): 62 | """Retrieve the project data to be used in the current window.""" 63 | if self.window.project_data() is None: 64 | return {} 65 | else: 66 | return self.window.project_data() 67 | 68 | @property 69 | def startupinfo(self): 70 | """Property used to hide command prompts when on Windows platforms.""" 71 | startupinfo = None 72 | 73 | if sys.platform == 'win32': 74 | startupinfo = subprocess.STARTUPINFO() 75 | 76 | if sys.version_info.major == 3: 77 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW 78 | else: 79 | startupinfo.dwFlags |= subprocess._subprocess.STARTF_USESHOWWINDOW 80 | 81 | return startupinfo 82 | 83 | def retrieve_environment_name(self, path): 84 | """Retrieve the environment name from the active environment path. 85 | 86 | If the active environment is the base environment, 'base' must be 87 | returned instead of the basename from the environment path. 88 | """ 89 | if path == self.base_directory: 90 | return 'base' 91 | else: 92 | return os.path.basename(path) 93 | 94 | 95 | class CreateCondaEnvironmentCommand(CondaCommand): 96 | """Contains the methods needed to create a conda environment.""" 97 | 98 | @property 99 | def python_versions(self): 100 | """Get list of python versions from online conda repo.""" 101 | shorthand = {'Windows': "win", 'Linux': "linux", 'Darwin': "osx"} 102 | system = shorthand[platform.system()] 103 | 104 | bit = self.settings.get("architecture") 105 | 106 | url = "https://repo.anaconda.com/pkgs/main/"+system+"-"+bit+"/" 107 | r = requests.get(url) 108 | 109 | v_list = re.findall(r"(?:>python-)(\d{1,2}.\d{1,2}.\d{1,2})[^<]+", r.text) 110 | 111 | versions = set() 112 | for each in v_list: 113 | versions.add("Python " + re.search(r"\d{1,2}.\d{1,2}.\d{1,2}", each).group()) 114 | 115 | return sorted(list(versions), reverse=True) 116 | 117 | def run(self): 118 | """Display 'Conda: Create' in Sublime Text's command palette. 119 | 120 | When 'Conda: Create' is clicked by the user, Sublime's text input 121 | box will show allowing the user to input the name of environment. 122 | This environment name is then passed to the create_environment 123 | method. 124 | """ 125 | self.window.show_input_panel('Conda Environment Name:', '', 126 | self.retrieve_python_version, None, None) 127 | 128 | def retrieve_python_version(self, environment): 129 | """Display a list of available Python versions for the environment. 130 | 131 | Forcing the user to select the Python version allows conda to create 132 | a new Python executable inside the environment directory. 133 | """ 134 | self.environment = environment 135 | 136 | self.window.show_quick_panel(self.python_versions, self.create_environment) 137 | 138 | def create_environment(self, index): 139 | """Create a conda environment in the envs directory.""" 140 | if index != -1: 141 | selection = self.python_versions[index] 142 | 143 | python_version = 'python='+selection[7:] 144 | 145 | cmd = [self.executable, '-m', 'conda', 'create', 146 | '--name', self.environment, python_version, '-y', '-q'] 147 | 148 | self.window.run_command('exec', {'cmd': cmd}) 149 | 150 | 151 | class RemoveCondaEnvironmentCommand(CondaCommand): 152 | """Contains the methods needed to remove a conda environment.""" 153 | 154 | def run(self): 155 | """Display 'Conda: Remove' in Sublime Text's command palette. 156 | 157 | When 'Conda: Removed' is clicked by the user, the command 158 | palette whill show all conda environments available for removal. 159 | The index of the selected environment is then passed to the 160 | remove_environment method" 161 | """ 162 | self.window.show_quick_panel(self.conda_environments, 163 | self.remove_environment) 164 | 165 | def remove_environment(self, index): 166 | """Remove a conda environment from the envs directory.""" 167 | if index != -1: 168 | environment = self.conda_environments[index][0] 169 | 170 | cmd = [self.executable, '-m', 'conda', 'remove', 171 | '--name', environment, '--all', '-y', '-q'] 172 | 173 | self.window.run_command('exec', {'cmd': cmd}) 174 | 175 | 176 | class ListCondaEnvironmentCommand(CondaCommand): 177 | """Contains the methods needed to list available conda environments.""" 178 | 179 | def run(self): 180 | """Display 'Conda: List' in Sublime Text's command palette. 181 | 182 | When 'Conda: List' is clicked by the user, the command 183 | palette will show all available conda environments. 184 | """ 185 | self.window.show_quick_panel(self.conda_environments, 186 | None) 187 | 188 | 189 | class ActivateCondaEnvironmentCommand(CondaCommand): 190 | """Contains the methods needed to activate a conda environment.""" 191 | 192 | def run(self): 193 | """Display 'Conda: Activate' in Sublime Text's command palette. 194 | 195 | When 'Conda: Activate' is clicked by the user, the command 196 | palette will show all available conda environments. The 197 | clicked environment will be activated as the current environment. 198 | """ 199 | self.window.show_quick_panel(self.conda_environments, 200 | self.activate_environment) 201 | 202 | def activate_environment(self, index): 203 | """Activate the environment selected from the command palette.""" 204 | if index != -1: 205 | project_data = self.project_data 206 | 207 | project_data['conda_environment'] = self.conda_environments[index][1] 208 | 209 | self.window.set_project_data(project_data) 210 | 211 | sublime.status_message('Activated conda environment: {}' 212 | .format(self.conda_environments[index][0])) 213 | 214 | 215 | class DeactivateCondaEnvironmentCommand(CondaCommand): 216 | """Contains the methods needed to deactivate a conda environment.""" 217 | 218 | def run(self): 219 | """Display 'Conda: Deactivate' in Sublime Text's command palette. 220 | 221 | When 'Conda: Deactivate' is clicked by the user, the command 222 | palette will show all available conda environments. The 223 | clicked environment will be deactivated. 224 | """ 225 | self.window.show_quick_panel(self.active_environment, 226 | self.deactivate_environment) 227 | 228 | @property 229 | def active_environment(self): 230 | """Retrieve the active conda environment.""" 231 | try: 232 | environment_path = self.project_data['conda_environment'] 233 | environment_name = self.retrieve_environment_name(environment_path) 234 | 235 | return [[environment_name, os.path.dirname(environment_path)]] 236 | 237 | except KeyError: 238 | return ['No Active Conda Environment'] 239 | 240 | def deactivate_environment(self, index): 241 | """Deactivate the environment selected in the command palette.""" 242 | if index != -1: 243 | try: 244 | project_data = self.project_data 245 | 246 | del project_data['conda_environment'] 247 | 248 | self.window.set_project_data(project_data) 249 | 250 | sublime.status_message('Deactivated conda environment: {}' 251 | .format(self.conda_environments[index][0])) 252 | except KeyError: 253 | sublime.status_message('No active conda environment') 254 | 255 | 256 | class OpenCondaReplCommand(CondaCommand): 257 | """Open a REPL tab within the activated Conda environment.""" 258 | 259 | def run(self, open_file='$file'): 260 | """Display 'Conda: Open REPL' in Sublime Text's command palette. 261 | 262 | When 'Conda: Open REPL' is clicked by the user, a new tab is opened 263 | with a REPL of the opened file in the current environment. 264 | """ 265 | settings = self.settings 266 | repl_open_row = settings.get('repl_open_row') 267 | repl_row_close_existing = settings.get('repl_row_close_existing') 268 | repl_save_dirty = open_file and settings.get('repl_save_dirty') 269 | repl_syntax = settings.get('repl_syntax') 270 | 271 | if repl_open_row: 272 | # set layout to 2 rows 273 | if (self.window.num_groups() != 2): 274 | self.window.run_command( 275 | 'set_layout', { 276 | 'cols':[0.0, 1.0], 277 | 'rows':[0.0, 0.5, 1.0], 278 | 'cells':[[0, 0, 1, 1], [0, 1, 1, 2]] 279 | } 280 | ) 281 | 282 | # return focus to file 283 | editor_group = 0 284 | self.window.focus_group(editor_group) 285 | 286 | repl_group = 1 287 | index = None 288 | 289 | if repl_row_close_existing: 290 | # close old repls, if any 291 | for view in self.window.views_in_group(repl_group): 292 | settings = view.settings() 293 | if settings.get("conda_repl_new_row", False): 294 | # grab index of first repl, if one exists 295 | index = index or self.window.get_view_index(view) 296 | # make sure close event does not mess with layout 297 | settings.set("conda_repl_new_row", False) 298 | view.close() 299 | # if there's another tab in that group, it will focus 300 | # there after closing, so return focus to main file 301 | self.window.focus_group(editor_group) 302 | 303 | if repl_save_dirty: 304 | # save file (if necessary) in current view 305 | view = self.window.active_view() 306 | if view.is_dirty(): 307 | view.run_command('save') 308 | 309 | # build the command list 310 | if sys.platform == 'win32': 311 | executable = 'python.exe' 312 | else: 313 | executable = os.path.join('bin', 'python') 314 | 315 | environment_path = self.project_data['conda_environment'] 316 | executable_path = os.path.join(os.path.expanduser(environment_path), executable) 317 | environment = self.retrieve_environment_name(environment_path) 318 | cmd_list = [executable_path, '-u', '-i'] 319 | 320 | if open_file: 321 | cmd_list.append(open_file) 322 | 323 | # open the repl 324 | self.repl_open(cmd_list, environment, repl_syntax) 325 | 326 | if repl_open_row: 327 | # move the repl into group, with focus 328 | self.window.run_command( 329 | 'move_to_group', {'group': repl_group} 330 | ) 331 | 332 | view = self.window.active_view() 333 | 334 | # put repl in same spot as old repl if one existed 335 | if index is not None: 336 | self.window.set_view_index(view, *index) 337 | 338 | # set view to top of repl window in case anything is printed above 339 | layout_width, layout_height = view.layout_extent() 340 | window_width, window_height = view.viewport_extent() 341 | new_top = layout_height - window_height 342 | view.set_viewport_position((0, max(new_top, 0))) 343 | view.settings().set("conda_repl_new_row", True) 344 | 345 | def repl_open(self, cmd_list, environment, syntax=None): 346 | """Open a SublimeREPL using provided commands""" 347 | if syntax is None: 348 | syntax = self.settings.get('repl_syntax') 349 | 350 | syntaxname = "Python/Python" # meaningful fallback 351 | if syntax == "python": 352 | syntaxname = "Python/Python" 353 | elif syntax == "plaintext": 354 | syntaxname = "Text/Plain text" 355 | else: 356 | print("Conda Open REPL: Unrecognized syntax '{}'".format(syntax)) 357 | syntaxpath = "Packages/{}.tmLanguage".format(syntaxname) 358 | 359 | self.window.run_command( 360 | 'repl_open', { 361 | 'encoding': 'utf8', 362 | 'type': 'subprocess', 363 | 'cmd': cmd_list, 364 | 'cwd': '$file_path', 365 | 'syntax': syntaxpath, 366 | 'view_id': '*REPL* [python]', 367 | 'external_id': environment, 368 | } 369 | ) 370 | 371 | 372 | class REPLViewEventListener(sublime_plugin.ViewEventListener): 373 | """Event to remove entire row when repl is last tab closed""" 374 | @classmethod 375 | def is_applicable(cls, settings): 376 | """Only activate close event for conda repls in new row""" 377 | return settings.get("conda_repl_new_row", False) 378 | 379 | def __init__(self, view): 380 | """Grab window since it is None during on_close""" 381 | self.window = view.window() 382 | super().__init__(view) 383 | 384 | def on_pre_close(self): 385 | """Determine if row should be removed: 386 | - number groups unchanged 387 | - view in group 388 | - group empty 389 | """ 390 | window, view = self.window, self.view 391 | repl_group = 1 392 | self.remove_row = ( 393 | window.num_groups() == 2 and 394 | window.get_view_index(view)[0] == repl_group and 395 | len(window.sheets_in_group(repl_group)) == 1 396 | ) 397 | 398 | def on_close(self): 399 | """Remove row if conditions are met""" 400 | if self.remove_row: 401 | self.window.run_command( 402 | 'set_layout', { 403 | 'cols':[0.0, 1.0], 404 | 'rows':[0.0, 1.0], 405 | 'cells':[[0, 0, 1, 1]] 406 | } 407 | ) 408 | 409 | 410 | class ListCondaPackageCommand(CondaCommand): 411 | """Contains all of the methods needed to list all installed packages.""" 412 | 413 | def run(self): 414 | """Display 'Conda: List' in Sublime Text's command palette. 415 | 416 | When 'Conda: List' is clicked by the user, the build output 417 | displays all packages installed in the current environment. 418 | """ 419 | self.window.show_quick_panel(self.environment_packages, None) 420 | 421 | @property 422 | def environment_packages(self): 423 | """List each package name and version installed in the environment.""" 424 | try: 425 | environment_path = self.project_data['conda_environment'] 426 | environment = self.retrieve_environment_name(environment_path) 427 | 428 | package_data = subprocess.check_output([self.executable, '-m', 'conda', 'list', 429 | '--name', environment], 430 | startupinfo=self.startupinfo, universal_newlines=True) 431 | 432 | packages = package_data.splitlines()[2:] 433 | package_names = [packages[i].split()[0] for i, _ in enumerate(packages)] 434 | 435 | return package_names 436 | 437 | except KeyError: 438 | return ['No Active Conda Environment'] 439 | 440 | 441 | class InstallCondaPackageCommand(CondaCommand): 442 | """Contains all of the methods needed to install a conda package.""" 443 | 444 | def run(self): 445 | """Display an input box allowing the user to input a package name.""" 446 | self.window.show_input_panel('Package Name:', '', self.install_package, 447 | None, None) 448 | 449 | def install_package(self, package): 450 | """Install the given package name via conda.""" 451 | try: 452 | environment_path = self.project_data['conda_environment'] 453 | environment = self.retrieve_environment_name(environment_path) 454 | cmd = [self.executable, '-m', 'conda', 'install', package, 455 | '--name', environment, '-y', '-q'] 456 | self.window.run_command('exec', {'cmd': cmd}) 457 | 458 | except KeyError: 459 | sublime.status_message('No active conda environment.') 460 | 461 | 462 | class RemoveCondaPackageCommand(CondaCommand): 463 | """Contains all of the methods needed to remove a conda package.""" 464 | 465 | def run(self): 466 | """Display an input box allowing the user to pick a package to remove.""" 467 | self.window.show_quick_panel(self.environment_packages, self.remove_package) 468 | 469 | @property 470 | def environment_packages(self): 471 | """List each package name and version installed in the environment. 472 | 473 | This property had to be duplicated as the attribute from 474 | ListCondaPackageCommand could not be inherited properly. 475 | """ 476 | try: 477 | environment_path = self.project_data['conda_environment'] 478 | environment = self.retrieve_environment_name(environment_path) 479 | 480 | package_data = subprocess.check_output([self.executable, '-m', 'conda', 'list', 481 | '--name', environment], 482 | startupinfo=self.startupinfo, universal_newlines=True) 483 | 484 | packages = package_data.splitlines()[2:] 485 | package_names = [packages[i].split()[0] for i, _ in enumerate(packages)] 486 | 487 | return package_names 488 | 489 | except KeyError: 490 | return ['No Active Conda Environment'] 491 | 492 | def remove_package(self, index): 493 | """Remove the given package name via conda.""" 494 | if index != -1: 495 | package_to_remove = self.environment_packages[index] 496 | 497 | environment_path = self.project_data['conda_environment'] 498 | 499 | environment = self.retrieve_environment_name(environment_path) 500 | 501 | cmd = [self.executable, '-m', 'conda', 'remove', package_to_remove, 502 | '--name', environment, '-y', '-q'] 503 | 504 | self.window.run_command('exec', {'cmd': cmd}) 505 | 506 | 507 | class ListCondaChannelsCommand(CondaCommand): 508 | """Contains all of the methods needed to display conda's channel sources.""" 509 | 510 | def run(self): 511 | """Display 'Conda: List Channel Sources' in Sublime Text's command palette. 512 | 513 | When 'Conda: List Channel Sources' is clicked by the user, 514 | the command palette displays all of the channel sources found 515 | in the condarc configuration file. 516 | """ 517 | self.window.show_quick_panel(self.channel_sources, None) 518 | 519 | @property 520 | def channel_sources(self): 521 | """List each channel source found in the condarc configuration file.""" 522 | sources = subprocess.check_output([self.executable, '-m', 'conda', 'config', 523 | '--show-sources', '--json'], 524 | startupinfo=self.startupinfo) 525 | sources = json.loads(sources.decode()) 526 | 527 | try: 528 | return sources[self.configuration]['channels'] 529 | 530 | except KeyError: 531 | return ['No Channel Sources Available'] 532 | 533 | 534 | class SearchCondaPackageCommand(CondaCommand): 535 | """Contains all of the methods needed to search for a conda package.""" 536 | 537 | def run(self): 538 | """Display an input box allowing the user to input a package name.""" 539 | self.window.show_input_panel('Package Name:', '', self.search_package, 540 | None, None) 541 | 542 | def search_package(self, package): 543 | """Search for a package included in the defaults channel.""" 544 | cmd = [self.executable, '-m', 'conda', 'search', package] 545 | self.window.run_command('exec', {'cmd': cmd}) 546 | 547 | 548 | class AddCondaChannelCommand(CondaCommand): 549 | """Contains all of the methods needed to add a conda channel source.""" 550 | 551 | def run(self): 552 | """Display 'Conda: Add Channel Source' in Sublime Text's command palette. 553 | 554 | When 'Conda: Add Channel Source' is clicked by the user, 555 | an input box will show allowing the user to type the name 556 | of the channel to add. 557 | """ 558 | self.window.show_input_panel('Conda Channel Name:', '', 559 | self.add_channel, None, None) 560 | 561 | def add_channel(self, channel): 562 | """Add the given channel to the condarc configuration file.""" 563 | cmd = [self.executable, '-m', 'conda', 'config', '--add', 564 | 'channels', channel] 565 | 566 | self.window.run_command('exec', {'cmd': cmd}) 567 | 568 | 569 | class RemoveCondaChannelCommand(CondaCommand): 570 | """Contains all of the methods needed to remove a conda channel source.""" 571 | 572 | def run(self): 573 | """Display 'Conda: Remove Channel Source' in Sublime Text's command palette. 574 | 575 | When 'Conda: Remove Channel Source' is clicked by the user, 576 | the command palette will show a list of channel sources 577 | available to be removed by the user. 578 | """ 579 | self.window.show_quick_panel(self.channel_sources, self.remove_channel) 580 | 581 | @property 582 | def channel_sources(self): 583 | """List each channel source found in the condarc configuration file. 584 | 585 | This property had to be duplicated as the attribute from 586 | ListCondaChannelCommand could not be inherited properly. 587 | """ 588 | sources = subprocess.check_output([self.executable, '-m', 'conda', 'config', 589 | '--show-sources', '--json'], 590 | startupinfo=self.startupinfo) 591 | sources = json.loads(sources.decode()) 592 | 593 | try: 594 | return sources[self.configuration]['channels'] 595 | 596 | except KeyError: 597 | return ['No Channel Sources Available'] 598 | 599 | def remove_channel(self, index): 600 | """Remove a channel from the condarc configuration file.""" 601 | if index != -1: 602 | channel = self.channel_sources[index] 603 | 604 | cmd = [self.executable, '-m', 'conda', 'config', '--remove', 605 | 'channels', channel] 606 | 607 | self.window.run_command('exec', {'cmd': cmd}) 608 | 609 | 610 | class ExecuteCondaEnvironmentCommand(CondaCommand): 611 | """Override Sublime Text's default ExecCommand with a targeted build.""" 612 | 613 | # :type tuple[int]: Used to cache conda version number to avoid 614 | # repeated calls to `conda info --json`. 615 | _conda_version = None 616 | 617 | os_env_path = os.environ['PATH'] 618 | 619 | @property 620 | def conda_version(self): 621 | """ 622 | Returns this system's conda version in the form (major, minor, micro). 623 | """ 624 | cls = type(self) 625 | 626 | if cls._conda_version is None: 627 | response = subprocess.check_output( 628 | [self.executable, '-m', 'conda', 'info', '--json'], 629 | startupinfo=self.startupinfo) 630 | 631 | parsed = json.loads(response.decode())['conda_version'] 632 | cls._conda_version = tuple(int(n) for n in parsed.split('.')) 633 | 634 | return cls._conda_version 635 | 636 | def __enter__(self): 637 | """ 638 | Temporarily modifies os.environ['PATH'] to include the target 639 | environment's /bin directory if this is a Windows system using a conda 640 | version >= 4.6. 641 | 642 | Required to address PATH issues that prevent some libraries from finding 643 | compiled dependencies. 644 | """ 645 | if sys.platform == 'win32' and self.conda_version >= (4, 6): 646 | env_path = self.project_data['conda_environment'] 647 | bin_path = os.path.join(env_path, 'Library', 'bin') 648 | os.environ['PATH'] = os.pathsep.join((bin_path, self.os_env_path)) 649 | return self 650 | 651 | def __exit__(self, exc_type, exc_value, traceback): 652 | os.environ['PATH'] = self.os_env_path 653 | 654 | def run(self, **kwargs): 655 | """Run the current Python file with the conda environment's Python executable. 656 | 657 | The activated conda environment is retrieved from the Sublime Text 658 | window project data. The Python executable found in the conda 659 | environment's bin directory is used to build the file. 660 | """ 661 | try: 662 | environment = self.project_data['conda_environment'] 663 | use_pythonw = self.settings.get('use_pythonw', False) 664 | run_through_shell = self.settings.get('run_through_shell', False) 665 | 666 | python_executable = 'pythonw' if use_pythonw else 'python' 667 | 668 | if sys.platform == 'win32': 669 | executable_path = '{}\\{}' .format(environment, python_executable) 670 | else: 671 | executable_path = '{}/bin/{}' .format(environment, python_executable) 672 | 673 | kwargs['cmd'][0] = os.path.normpath(executable_path) 674 | kwargs['shell'] = run_through_shell 675 | 676 | except KeyError: 677 | pass 678 | 679 | if kwargs.get('kill') is not None: 680 | kwargs = {'kill': True} 681 | 682 | with self: 683 | self.window.run_command('exec', kwargs) 684 | -------------------------------------------------------------------------------- /dependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "*": { 3 | ">=3000": [ 4 | "requests" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mandeep/sublime-text-conda/90233fcb76c389ae9703373d0d4a4c1e635b1320/header.png -------------------------------------------------------------------------------- /messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "install": "messages/install.txt", 3 | "0.1.2": "messages/v0.1.2.txt", 4 | "0.1.3": "messages/v0.1.3.txt", 5 | "0.1.4": "messages/v0.1.4.txt", 6 | "0.2.0": "messages/v0.2.0.txt", 7 | "0.2.1": "messages/v0.2.1.txt", 8 | "0.3.0": "messages/v0.3.0.txt", 9 | "0.3.1": "messages/v0.3.1.txt", 10 | "0.4.0": "messages/v0.4.0.txt", 11 | "0.4.1": "messages/v0.4.1.txt", 12 | "0.4.2": "messages/v0.4.2.txt", 13 | "0.4.3": "messages/v0.4.3.txt", 14 | "0.4.4": "messages/v0.4.4.txt", 15 | "0.4.5": "messages/v0.4.5.txt", 16 | "0.4.6": "messages/v0.4.6.txt", 17 | "0.5.0": "messages/v0.5.0.txt", 18 | "0.5.1": "messages/v0.5.1.txt", 19 | "0.5.2": "messages/v0.5.2.txt", 20 | "0.6.0": "messages/v0.6.0.txt", 21 | "0.6.1": "messages/v0.6.1.txt", 22 | "0.7.0": "messages/v0.7.0.txt", 23 | "0.8.0": "messages/v0.8.0.txt", 24 | "0.9.0": "messages/v0.9.0.txt", 25 | "0.9.1": "messages/v0.9.1.txt" 26 | } 27 | -------------------------------------------------------------------------------- /messages/install.txt: -------------------------------------------------------------------------------- 1 | ____ _ _ ___ _ _ _ _ ____ ___ ____ _ _ ___ ____ ____ _ _ ___ ____ 2 | [__ | | |__] | | |\/| |___ __ | |___ \/ | __ | | | |\ | | \ |__| 3 | ___] |__| |__] |___ | | | |___ | |___ _/\_ | |___ |__| | \| |__/ | | 4 | 5 | 6 | https://www.github.com/mandeep/sublime-text-conda 7 | https://packagecontrol.io/packages/Conda 8 | 9 | sublime-text-conda assumes that conda can be found in Anaconda's default install path. 10 | If the install path was changed when installing Anaconda or if you're using Miniconda, 11 | sublime-text-conda's settings will need to be changed in 12 | Preferences -> Package Settings -> Conda 13 | 14 | To start using this plugin, first select the 'Conda' build system 15 | from Tools -> Build System. Once the build system is selected, you can access the Conda 16 | commands via the command palette. 17 | 18 | If you need further help or would like to report an issue, please visit the GitHub repository 19 | and file an issue. -------------------------------------------------------------------------------- /messages/v0.1.2.txt: -------------------------------------------------------------------------------- 1 | Conda 0.1.2 2 | =========== 3 | 4 | - Renamed path in settings file to fix issue with empty settings file -------------------------------------------------------------------------------- /messages/v0.1.3.txt: -------------------------------------------------------------------------------- 1 | Conda v0.1.3 2 | ============ 3 | 4 | - New release that shows installer message -------------------------------------------------------------------------------- /messages/v0.1.4.txt: -------------------------------------------------------------------------------- 1 | Conda v0.1.4 2 | ============ 3 | 4 | - Fixed issue where plugin would fail when project data wasn't in use -------------------------------------------------------------------------------- /messages/v0.2.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.2.0 2 | ============ 3 | 4 | - Added ability to list, add, and remove channels -------------------------------------------------------------------------------- /messages/v0.2.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.2.1 2 | ============ 3 | 4 | - Add build system instructions in install.txt and README 5 | - Add Github and Package Control links in install.txt -------------------------------------------------------------------------------- /messages/v0.3.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.3.0 2 | ============ 3 | 4 | - Add root conda environment to available conda environments 5 | - Add 'Conda: Search Package' command that searches for packages in the defaults channel -------------------------------------------------------------------------------- /messages/v0.3.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.3.1 2 | ============ 3 | 4 | - Fix issue with command prompt opening on Windows platforms 5 | - Fix issue with Conda Package commands not working on Windows platforms -------------------------------------------------------------------------------- /messages/v0.4.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.0 2 | ============ 3 | 4 | - Change how the build system is executed allowing for Cancel Build to be called 5 | - Fix issue with command palette being empty when channel sources are unavailable 6 | -------------------------------------------------------------------------------- /messages/v0.4.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.1 2 | ============ 3 | 4 | - Fix issue with environments due to Anaconda 5 installer not creating envs directory 5 | -------------------------------------------------------------------------------- /messages/v0.4.2.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.2 2 | ============ 3 | 4 | - Set PYTHONIOENCODING to utf-8 in the Conda build system (thanks @mys721tx) 5 | -------------------------------------------------------------------------------- /messages/v0.4.3.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.3 2 | ============ 3 | 4 | - Fix Conda: List Packages command so that it includes packages installed by pip 5 | -------------------------------------------------------------------------------- /messages/v0.4.4.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.4 2 | ============ 3 | 4 | - Fix plugin settings on Windows being loaded as Unix settings 5 | -------------------------------------------------------------------------------- /messages/v0.4.5.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.5 2 | ============ 3 | 4 | - Add Windows and OSX specific files to Preferences->Packages->Conda menu 5 | -------------------------------------------------------------------------------- /messages/v0.4.6.txt: -------------------------------------------------------------------------------- 1 | Conda v0.4.6 2 | ============ 3 | 4 | - Fix settings file not being loaded 5 | -------------------------------------------------------------------------------- /messages/v0.5.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.5.0 2 | ============ 3 | 4 | - Added the ability to load old settings files on Unix based systems 5 | - Incremented minor version as the new settings file system could cause minor breakage 6 | -------------------------------------------------------------------------------- /messages/v0.5.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.5.1 2 | ============ 3 | 4 | - Fix the 'Cancel Build' menu item in the Tools menu 5 | -------------------------------------------------------------------------------- /messages/v0.5.2.txt: -------------------------------------------------------------------------------- 1 | Conda v0.5.2 2 | ============ 3 | 4 | - Fix Windows issue where GUI figures were not showing on build 5 | -------------------------------------------------------------------------------- /messages/v0.6.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.6.0 2 | ============ 3 | 4 | - Add support for Python version 3.7 5 | -------------------------------------------------------------------------------- /messages/v0.6.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.6.1 2 | ============ 3 | 4 | - Fix windows PATH issue causing import errors with some packages (courtesy of @jim-hart) 5 | -------------------------------------------------------------------------------- /messages/v0.7.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.7.0 2 | ============ 3 | 4 | - Fix stripping all occurrences of 'bin' from conda installation paths 5 | - Change root environment name to base environment to be consistent with conda 6 | -------------------------------------------------------------------------------- /messages/v0.8.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.8.0 2 | ============ 3 | 4 | - Use Anaconda's repo list so that all Python versions are available when creating a new environment 5 | - Add Conda: Open REPL command that opens the current Conda environment in a new REPL tab 6 | -------------------------------------------------------------------------------- /messages/v0.9.0.txt: -------------------------------------------------------------------------------- 1 | Conda v0.9.0 2 | ============ 3 | 4 | - Added setting to save file prior to opening REPL 5 | - Added setting to open REPL in bottom row of layout 6 | - REPL syntax now defaults to Plain text but can be changed to Python 7 | 8 | Thanks to @gseastream for the contributions 9 | -------------------------------------------------------------------------------- /messages/v0.9.1.txt: -------------------------------------------------------------------------------- 1 | Conda v0.9.1 2 | ============ 3 | 4 | - Fix issue when closing the last REPL tab 5 | - Default to Python syntax for REPL 6 | 7 | Thanks to @gseastream for the contributions 8 | --------------------------------------------------------------------------------