Slide 1

Slide 1 text

Sublime Text 2 (especially for Emacs-ers) 2012-08-24

Slide 2

Slide 2 text

@kentaro Software Engineer Perl-er / Rubyist Seasoned Emacs-er Kentaro Kuribayashi Works for paperboy&co.

Slide 3

Slide 3 text

My Works on Emacs Simple Hatena Mode Emacs Interface to Hatena::Diary Writer auto-save-buffers-enhanced.el Better auto-save feature for Emacs ditz.el Emacs Interface to ditz.rb cppref.el Emacs Interface to cppref Command Taskpaper Super Simple Task Management Tool and so on...

Slide 4

Slide 4 text

Sublime Text 2

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

• Simple and Fast • Minimap • Quick Navigation • Multiple Selections • Highly Customizable • Python Plugin API • Split Editing • Cross Platform and so on...

Slide 7

Slide 7 text

This information is hardly useful for anyone. Emacs is... Well, nobody really knows what emacs is, although some people edit text with it. If you are an emacs user, you’re probably not reading this. http://docs.sublimetext.info/en/latest/basic_concepts.html#emacs Sublime Text Unofficial Documentation

Slide 8

Slide 8 text

Quick Panel

Slide 9

Slide 9 text

Goto Anything

Slide 10

Slide 10 text

Goto Anything (Methods, etc.)

Slide 11

Slide 11 text

Goto Anything (Simbols, etc.)

Slide 12

Slide 12 text

Command Pallet

Slide 13

Slide 13 text

Quick Panel Goto Anything FuzzyFinder (+α) Like File Navigator Command Pallet Command Launcher File Completion Methods Navigation Simbols Navigation

Slide 14

Slide 14 text

Snippets

Slide 15

Slide 15 text

In-place Snippets Completion

Slide 16

Slide 16 text

Snippets Candidates from Command Pallet

Slide 17

Slide 17 text

Snippets Easy to Define How to Do it will be described later Very Expressive TextMate2 / yasnippet -like or ++ Easy to Memorize Trigger Strings appear when completing

Slide 18

Slide 18 text

Plugins

Slide 19

Slide 19 text

Package Control Package Management Tool Install Packages from Command Pallet Maintained by Will Bond Various Repositories Support GitHub BitBucket Custom Repository Defined by JSON http://wbond.net/sublime_packages/community

Slide 20

Slide 20 text

Git / SideBarGit Execute Git Commands from ST2 Side Bar Enhancements for Git Sublime Tweet Make Tweets from ST2 Retrieve Timeline into and Manipulate against Tweets Many Plugins for Development Ruby / Python / JavaScript / HTML / etc. flymake-like Lint Plugin Many Snippets for Languages LiveReload LiveReload Server Implementation for ST2 Usable for Realtime Preview Markdown Viewer

Slide 21

Slide 21 text

config.middleware.insert_before( Rack::Lock, Rack::LiveReload, min_delay: 500, max_delay: 10000, port: 35729, host: 'localhost', ignore: [] ) config/environments/development.rb: Rails with LiveReload guard-livereload not Required

Slide 22

Slide 22 text

http://wbond.net/sublime_packages/community There are Much More:

Slide 23

Slide 23 text

ST2 In Practice

Slide 24

Slide 24 text

$ ln -s "/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl" $HOME/bin/subl $ subl -h Mac OSX / Linux: Launch from Terminal Run ST2 with your environment variables to avoid troubles.

Slide 25

Slide 25 text

$ cd $HOME/Library/Application\ Support/ $ mv Sublime\ Text\ 2/ $HOME/Dropbox/ Apps/ $ ln -s $HOME/Dropbox/Apps/Sublime\ Text \ 2/ Sublime\ Text\ 2 Mac OSX: Sync Settings by DropBox All Settings / Plugins are located in the place, so you just need to make a symlink to there.

Slide 26

Slide 26 text

“save_on_focus_lost”: true for auto-save-buffers Preferences.sublime-settings: auto-save-bufffers-enhanced.el can’t be ported directly to ST2 because ST2 doesn’t have `run-with-idle-timer`-like API... "save_on_focus_lost": true Buffers will automatically saved when focus out.

Slide 27

Slide 27 text

Sublime Linter CoffeeScript lint via coffee -s -l CSS lint via built-in csslint Git Commit Messages lint via built-in module Haml lint via haml -c Java lint via javac -Xlint Javascript lint via built in jshint, jslint, or the closure linter Objective-J lint via built-in capp_lint Perl lint via Perl:Critic or syntax+deprecation checking via perl -c PHP syntax checking via php -l Puppet syntax checking via puppet parser validate Python native, moderately-complete lint Ruby syntax checking via ruby -wc https://github.com/SublimeLinter/SublimeLinter for flymake.el

Slide 28

Slide 28 text

How to Define Snippets

Slide 29

Slide 29 text

How to Define Snippets Tools → New Snippet Save file with *.sublime-snippet ext.

Slide 30

Slide 30 text

How to Define Snippets (2) content Content of Snippets tabTrigger Trigger String to Start Completing scope Mode Where Snippets are Available description Name Desplayed When Completing

Slide 31

Slide 31 text

Hello, ${1:this} is a ${2:snippet}. ${0} Push TAB to move from ${1:this} to ${2:snippet} Same number will be edited simultaneously. Completion ends at ${0} ${num:placehodler} How to Define Snippets (3)

Slide 32

Slide 32 text

How to Define Snippets (4) $PARAM1 $SELECTION $TM_CURRENT_LINE $TM_CURRENT_WORD $TM_FILENAME $TM_FILEPATH $TM_FULLNAME $TM_LINE_INDEX $TM_LINE_NUMBER $TM_SELECTED_TEXT $TM_SOFT_TABS $TM_TAB_SIZE Special Variables Regular Expressions http://docs.sublimetext.info/en/latest/reference/snippets.html for Details:

Slide 33

Slide 33 text

Python Plugin API

Slide 34

Slide 34 text

On Windows and Linux, Sublime Text 2 comes with its own Python interpreter and it’s separate from your system’s Python installation. On OS X, the system Python is used instead. Modifying your system version of Python, such as replacing it with the MacPorts version, can cause problems for Sublime Text. What Python is Used? http://docs.sublimetext.info/en/latest/basic_concepts.html#your-system-s-python-vs-the-sublime-text-2-embedded-python

Slide 35

Slide 35 text

Python on OSX print sys.version 2.6.7 (r267:88850, Jun 20 2012, 16:23:38) [GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/ clang-418.0.60)] • Sublime Text2 for Mac (Build 2216) • Mac OSX 10.8 • It seems to be same as /usr/bin/python2.6

Slide 36

Slide 36 text

Install External Libraries $ sudo /usr/bin/easy_install-2.6 pip $ sudo /usr/local/bin/pip-2.6 install [module_name] Now you can use external libraries in your plugin. But then, your plugin won’t work in Windows / Linux. OSX Only

Slide 37

Slide 37 text

API Details

Slide 38

Slide 38 text

Hello, World! import sublime, sublime_plugin class ExampleCommand(sublime_plugin.TextCommand): def run(self, edit): self.view.insert(edit, 0, "Hello, World!") Tools → New Plugin Save file as *.py Run command in Python console (C-`): view.run_command(“example”)

Slide 39

Slide 39 text

Plugin Name Convention Plugin Class Name: FooBarCommand Command Name: foo_bar class FooBarCommand(sublime_plugin.TextCommand): # ... view.run_command(“foo_bar”)

Slide 40

Slide 40 text

Plugin Types Application Commands It doesn’t have any specific reference to window/view. Window Commands Provides a reference to the current window. Text Commands Provides a reference to the current view. Event Listner Will be invoked when some event occurs.

Slide 41

Slide 41 text

API Reference / Documents Unofficial Document http://net.tutsplus.com/tutorials/python-tutorials/how-to-create-a-sublime-text-2-plugin/ How to Create a Sbulime Text 2 Plguin http://net.tutsplus.com/tutorials/python-tutorials/how-to-create-a-sublime-text-2-plugin/ Official API Reference http://www.sublimetext.com/docs/2/api_reference.html Cookbook by @jugyo https://gist.github.com/3338888

Slide 42

Slide 42 text

Available UI Components Status Message Error Message Message Dialog OK/Cancle Dialog Quick Panel Input Panel Output Panel

Slide 43

Slide 43 text

import sublime, sublime_plugin class ExampleStatusMessageCommand(sublime_plugin.ApplicationCommand): def run(self): sublime.status_message("Hello, World!") Status Message

Slide 44

Slide 44 text

import sublime, sublime_plugin class ExampleErrorMessageCommand(sublime_plugin.ApplicationCommand): def run(self): sublime.error_message("Error!") Error Message

Slide 45

Slide 45 text

import sublime, sublime_plugin class ExampleMessageDialogCommand(sublime_plugin.ApplicationCommand): def run(self): sublime.message_dialog("How are you?") Message Dialog

Slide 46

Slide 46 text

import sublime, sublime_plugin class ExampleOkCancelDialogCommand(sublime_plugin.ApplicationCommand): def run(self): if sublime.ok_cancel_dialog("OK?", "Sure!"): print "OK pushed!" else: print "Canceled!" OK/Cancel Dialog

Slide 47

Slide 47 text

import sublime, sublime_plugin class ExampleQuickPanelCommand(sublime_plugin.WindowCommand): def run(self): self.items = [ "item " + str(i) for i in range(1, 6) ] self.window.show_quick_panel(self.items, self.on_done) def on_done(self, index): if index > 0: print "Selected: {0}".format(self.items[index]) else: print "Canceled!" Quick Panel • `index` will be one of `items` selected. • `-1` returned if canceled.

Slide 48

Slide 48 text

import sublime, sublime_plugin class ExampleInputPanelCommand(sublime_plugin.WindowCommand): def run(self): self.window.show_input_panel("Input: ", "default text", self.on_done, self.on_changed, self.on_canceled) def on_done(self, str): print str def on_changed(self, str): print str def on_canceled(self): print "Canceled!" Input Panel

Slide 49

Slide 49 text

Output Panel popwin.el -like interface It’s a bit complecated to use Output Panel.

Slide 50

Slide 50 text

class ExampleOutputPanelCommand(sublime_plugin.WindowCommand): def run(self): output_view = self.window.get_output_panel("foo") # Set some view settings output_view.set_scratch(True) output_view.set_name("Foo Results") output_view.settings().set("key", "value") # Begin edit session edit = output_view.begin_edit() # Insert content output_view.replace(edit, sublime.Region(0, output_view.size()), "foo foo foo") # End edit session output_view.end_edit(edit) # Finally, show panel output_view.set_read_only(True) self.window.run_command("show_panel", {"panel": "output.foo"})

Slide 51

Slide 51 text

class ExampleThreadCommand(sublime_plugin.WindowCommand): def run(self): thread.start_new_thread(self.in_new_thread, ()) def in_new_thread(self): self.window.show_input_panel("Hello from a new thread!", "", None, None, None) Calling UI Components on other Threads ...Will get an Error: RuntimeError: Must call on main thread, consider using sublime.set_timeout(function, timeout)

Slide 52

Slide 52 text

class ExampleThreadCommand(sublime_plugin.WindowCommand): def run(self): thread.start_new_thread(self.in_new_thread, ()) def in_new_thread(self): sublime.set_timeout(self.in_main_thread, 0) def in_main_thread(self): self.window.show_input_panel("Hello from the main thread!", "", None, None, None) Calling UI Components on other Thread (2) • UI components must be called in `main thread`. • Use 'sublime.set_timeout(callback, delay)' for it. • When it's some dialog component, to make matters worse, the whole editor can block and won't return to the `main thread`

Slide 53

Slide 53 text

Practical Plugin Development

Slide 54

Slide 54 text

Sublime Eijiro Plugin • Consult a word at cursor to Eijiro (Online Japanese-English/English-Japanese Dictionary) • Display meanings of the word returned by the dictionary in Output Panel • Enable to launch the command from Command Pallet

Slide 55

Slide 55 text

class EijiroCommand(sublime_plugin.TextCommand): def run(self, edit): point = self.view.sel()[0].begin() self.word = self.view.substr(self.view.word(point)) if not self.word: sublime.status_message("No word found.") return else: self.consult_dictionary(self.word) Get a Word at Cursor • We support only one selection this time. • view.substr() takes sublime.Region returned from view.word() / view.line() etc. to retrieve a word in the range.

Slide 56

Slide 56 text

def consult_dictionary(self, word): encoded_word = urllib.quote(word) self.url = "http://eow.alc.co.jp/{0}/ UTF-8/".format(encoded_word) thread.start_new_thread(self.fetch_remote_dictionary, ()) Back off Heavy IO • Don’t block the main thread with heavy IO. • Use thread to back off.

Slide 57

Slide 57 text

def fetch_remote_dictionary(self): try: request = urllib2.Request(self.url) return self.handle_response(urllib2.urlopen(request, timeout=10)) except urllib2.HTTPError as e: self.handle_error("HTTP", e) except urllib2.URLError as e: self.handle_error("URL", e) HTTP Request with urllib2 • We can freely use Python’s rich libraries. • Even external libraries can be used in Mac OSX ad described before.

Slide 58

Slide 58 text

def handle_response(self, response): self.content = response.read() sublime.set_timeout(self.show_output_view, 0) Return to the Main Thread • When we use some UI component, we must call it in the main thread as described before.

Slide 59

Slide 59 text

def show_output_view(self): output_view = self.view.window().get_output_panel("eijiro." + self.word) output_view.set_scratch(True) output_view.set_name("Eijiro Result") edit = output_view.begin_edit() raw_content = self.extract_content(self.content) output_view.replace(edit, sublime.Region(0, output_view.size()), raw_content.decode("utf-8")[:]) output_view.end_edit(edit) output_view.set_read_only(True) self.view.window().run_command("show_panel", {"panel": "output.eijiro." + self.word}) Show the Meanings

Slide 60

Slide 60 text

[ { "caption": "Eijiro: Search", "command": "eijiro" } ] Register the Command • To register your command to Command Pallet, Default.sublime-commands file need to be prepared like above. Default.sublime-commands:

Slide 61

Slide 61 text

https://github.com/kentaro/SublimeEijiro Whole the Code is Available at

Slide 62

Slide 62 text

Recap

Slide 63

Slide 63 text

• Sublime Text 2 is actually a highly customizable editor • Python API is easier to do with than elisp / vimscript • Rich UI components are very useful and easy to use from plugins • There already have been many plugins by community Pros

Slide 64

Slide 64 text

• Sublime Text 2 is a proprietary software • There’s no dired (wdired) -like things (it’s very critical personally...) • Not stable enough. It often crash, especially with LiveReload plugin. Cons

Slide 65

Slide 65 text

Try it Now! http://sublimetext.com