Sublime Text for Data Science

Introduction

Data Scientists have to deal with multiple languages and tools in their every day life. We code in languages like Python, R, Julia, Matlab or Octave, among others; we also query databases with languages like SQL, and generate reports with tools like \(\LaTeX\) or RMarkdown.

Most of these languages come with an integrated development environment (IDE). For example, Matlab and Octave come with an editor, RStudio is the standard IDE for R and RMarkdown; Python has multiple IDEs such as PyCharm, IDLE and Spyder; Julia has Juno; TexStudio and TexShop are excellent \(\LaTeX\) editors; and Workbench is a visual development tool available for MySQL.

These applications are great to work with; however when you have to work with several of them it becomes a hassle to deal with multiple configurations, workflows and keyboard shortcuts. Because of that reason I have switched to working with one tool for all of them: Sublime Text.

The purpose of this post is to show you how Sublime Text can be used as a one-stop shop tool for the coding needs of a Data Scientist.

Sublime Text

Sublime Text (ST) is a multi-purpose text editor with functionality that can be extended through packages. This feature is not unique to ST, there are editors such as Vim, Emacs, Notepad++, VSCode, Atom, etc, that are also highly configurable; however I stuck to ST due to how fast and easy to use it is. Furthermore, the other editors I mentioned are free, as opposed to ST; however, ST can still be used without paying for a license. In my case I bought the license due to how useful ST was for my projects.

Out of the box ST does not do much, but with the proper configuration we can turn it into an excellent interactive development environment. As an example, below is a screen recording of simple "Hello world" snippets in Python, R and Julia executed side by side in ST.

In the following sections I will show you how to set ST up for interactive execution of Python, R, Julia, Octave and MySQL. I will not discuss how to install ST nor any of the aforementioned languages; I assume they are already in your system. Furthermore, the tutorial is focused on a Mac operating system, but the same concepts apply to Windows; the only difference would be the use of Ctrl and Alt instead of Cmd and Option in keyboard shortcuts, and backslash instead of slash in file path names.

Installation of SendCode and Terminus

The packages that allow the opening of different terminals and sending code to them are Terminus and SendCode, both by randy3k, and can be installed with Package Control.

If you do not have Package Control installed yet, you can do so by clicking on Tools > Install Package Control.... Once installed, click on Preferences > Package Control or press Cmd+Shift+P, and you will see a dropdown menu. Start writing Install and the dropdown menu will narrow down the options that contain that word; click on the option Package Control: Install Package and type the name of the package you want to install; in this case it is SendCode. Repeat the process to install Terminus.

After their installation, we have to configure Terminus to open the terminals we want, and SendCode to send and execute code in the terminals.

SendCode

We specify we want SendCode to send lines of code to Terminus by opening the SendCode settings file at Preferences > Package Settings > SendCode > Settings and writing

{
    "prog": "terminus"
}

Terminus

The default Terminus settings are good enough to get us going, and I will not go over them. They can later be configured to change the color of the terminals, cursor type, font type and size, etc. However, we do need to configure the shortcuts to open the different terminals in Terminus, and that is what we will do in the following sections.

Shortcuts and SendCode Configurations

Python

When I code in Python I work with an IPython terminal instead of the regular console. I open IPython with the shortcut Cmd + Option + I on the right column of my working window. We will use the same configuration in this tutorial.

In order to open IPython with Cmd + Option + I we have to configure the shortcut in the ST key bindings file located at Preferences > Key Bindings. We need to know the location of our IPython executable to configure the shortcut; if you do not know it you can find it in Mac’s Terminal with the command which ipython. Let us assume we found the IPython executable at /path/to/ipythonfolder/ipython; the configuration of our shortcut is then

// Open IPython at current file directory
{
    "keys": ["super+alt+i"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/ipythonfolder/ipython",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "iPython",
    "tag": "python"
    }
},

Now when we press Cmd + Option + I ST will open IPython in a tab in the second column. We now have to modify the SendCode settings to send Python code to the tab we opened. The modified SendCode settings now look like

{
    "prog": "terminus",
    "python":
    {
        "bracketed_paste_mode": true,
        "tag": "python"
    },
}

Furthermore, if we want to send code to IPython with Shift + Enter we need to add the following lines in the Key Bindings file:

// Send code to Terminus
{
    "keys": ["shift+enter"], "command": "send_code",
    "context": [
        { "key": "selector",
            "operator": "equal",
            "operand": "source.python" }
    ]
},

The "context" option "source.python" limits our ability to send code with the assigned shortcut only to Python code. We will expand that ability to our other languages by appending more options to this parameter.

We can further expand the configuration to be able to build and run a file in the IPython terminal, not specific lines of code only. SendCode already comes with preconfigured build systems for IPython, Julia, R and Rcpp files. The build system for IPython is located at Tools > Build System > IPython - Source File. After choosing this build system, the Python file can be executed with the default shorcut Cmd + B.

That is it. We should now be able to run an IPython terminal and execute code in it.

Below is a screen recording of a linear regression example in Python. First the IPython terminal is opened with Cmd + Option + B, then some code selections are sent to the terminal with Shift + Enter, and finally the whole the file is executed in the terminal with Cmd + B.

R

The setup of an R terminal in ST is very similar to that of IPython. Like we did with Python, we will not use the standard R terminal; instead we will use radian. Radian is an interface to the standard R terminal, like what IPython is for Python; therefore, we have to have a proper R installation before we can continue.

Assuming we have R already installed, we install radian from IPython with the command pip install -U radian. Once installed, we locate the executable for radian and copy its path. In this case we assume we found radian at /path/to/radianfolder/radian. We can configure the shortcut Cmd + Option + R to open a tab for radian in the second column with the following lines

// Open R at current file directory
{
    "keys": ["super+alt+r"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/radianfolder/radian",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Rterm",
    "tag": "r"
    }
},

We then add the following lines to the SendCode settings

 "r":
    {
        "bracketed_paste_mode": true,
        "tag": "r"
    },

and add R to the context selector of the SendCode shortcut for Terminus; the resulting shorcut settings are

// Send code to Terminus
{
    "keys": ["shift+enter"], "command": "send_code",
    "context": [
        { "key": "selector",
            "operator": "equal",
            "operand": "source.python,source.r" }
    ]
},

These settings should allow us to send code to open IPython and radian terminals.

We can also build R files within the radian terminal. The preconfigured build system that comes with SendCode can be found at Tools > Build System > R - Source File. Once selected, we can execute the whole file in the radian terminal with Cmd + B. Below is a screen recording of a linear regression example in R. Similar to what we did for IPython, we open the radian terminal with Cmd + Option + R, send some lines of code to the terminal with Shift + Enter, and execute the whole file with Cmd + B.

For the rest of the languages I will only post the code for the shortcuts and SendCode settings. I will also assume their executables are installed in the path /path/to/executablefolder/executable, and will use the same Shift+Enter shortcut to send code to their terminals. I will not post this shortcut configuration for each language, though; instead, I will show what the final Shift+Enter shortcut looks like at the end of the post.

Julia

Shortcut: Cmd + Option + J
Configuration in Key Bindings file:

// Open Julia at current file directory
 {
    "keys": ["super+alt+j"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/juliafolder/julia",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Julia",
    "tag": "julia"
    }
},

SendCode Settings:

"julia":
    {
        "tag": "julia"
    },

A build system can be used to execute whole files in the Julia terminal; the one that ships with SendCode is located at Tools > Build System > Julia - Source File. Below is a Julia version of the linear regression example shown in the Python and R cases.

Octave

Shortcut: Cmd + Option + O
Configuration in Key Bindings file:

// Open Octave at current file directory
{
    "keys": ["super+alt+o"],
    "command": "terminus_open",
    "args": {
        "cmd": "/usr/local/bin/octave",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Octave",
    "tag": "octave"
    }
},

SendCode Settings:

"matlab":
{
    "bracketed_paste_mode": false,
    "tag": "octave"
},

Here is an example of a sine plot in Octave

MySQL

Shortcut: Cmd + Option + Y
Configuration in Key Bindings file:

// Open MySQL at current file directory
{
    "keys": ["super+alt+y"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/mysqlfolder/mysql",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "MySQL",
    "tag": "sql"
    }
},

SendCode Settings:

"sql":
    {
    "tag": "sql"
},

Below is MySQL in action; I used this example from the documentation.

Final Configuration

Here is how the final files for the SendCode settings and Key Bindings look like.

SendCode Settings:

{
    "prog": "terminus",
    "python":
    {
        "bracketed_paste_mode": true,
        "tag": "python"
    },
    "r":
    {
        "bracketed_paste_mode": true,
        "tag": "r"
    },
    "julia":
    {
        "tag": "julia"
    },
    "matlab":
    {
        "bracketed_paste_mode": true,
        "tag": "octave"
    },
    "sql":
        {
        "tag": "sql"
    }
}

Key Bindings file:

// Send code to Terminus
{
    "keys": ["shift+enter"], "command": "send_code",
    "context": [
        { "key": "selector",
            "operator": "equal",
            "operand": "source.python,source.r,source.julia,source.matlab,source.sql" }
    ]
},
// Open IPython at current file directory
{
    "keys": ["super+alt+i"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/ipythonfolder/ipython",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "iPython",
    "tag": "python"
    }
},
// Open R at current file directory
{
    "keys": ["super+alt+r"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/radianfolder/radian",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Rterm",
    "tag": "r"
    }
},
// Open Julia at current file directory
 {
    "keys": ["super+alt+j"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/juliafolder/julia",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Julia",
    "tag": "julia"
    }
},
// Open Octave at current file directory
{
    "keys": ["super+alt+o"],
    "command": "terminus_open",
    "args": {
        "cmd": "/usr/local/bin/octave",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "Octave",
    "tag": "octave"
    }
},
// Open MySQL at current file directory
{
    "keys": ["super+alt+y"],
    "command": "terminus_open",
    "args": {
        "cmd": "/path/to/mysqlfolder/mysql",
        "cwd": "${file_path:${folder}}",
        "pre_window_hooks": [
         ["set_layout", {
            "cols": [0.0, 0.5, 1.0],
            "rows": [0.0, 1.0],
            "cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
        }],
        ["focus_group", {"group": 1}]
      ] ,
    "title": "MySQL",
    "tag": "sql"
    }
}

Conclusion

Sublime Text is a fast and highly configurable text editor that can be used as an interactive developement tool for multiple programming and markup languages used in Data Science. In this post I showed how ST can be configured to run Python, R, Julia, Octave and SQL interactively.

I did not cover the configuration of ST for \(\LaTeX\) or RMarkdown because there are already really good tutorials out there like this one for LaTeX and this one for RMarkdown.

Furthermore, I need to provide the disclaimer that ST is not a perfect replacement of specialized IDEs like RStudio or PyCharm; these applications provide features that ST does not, e.g., visual debugging. However, for fast and interactive development of small projects ST does a wonderful job.

I hope this post showed you something cool about Sublime Text, but more important, I hope you learned something new about the development tools available for your career in Data Science.

See also