Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Sublime Text 2 for Emacsers

Sublime Text 2 for Emacsers

Introduction to Sublime Text 2, especially for Emacs-ers.


Kentaro Kuribayashi

August 24, 2012


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

  2. @kentaro Software Engineer Perl-er / Rubyist Seasoned Emacs-er Kentaro Kuribayashi

    Works for paperboy&co.
  3. 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...
  4. Sublime Text 2

  5. None
  6. • Simple and Fast • Minimap • Quick Navigation •

    Multiple Selections • Highly Customizable • Python Plugin API • Split Editing • Cross Platform and so on...
  7. 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
  8. Quick Panel

  9. Goto Anything

  10. Goto Anything (Methods, etc.)

  11. Goto Anything (Simbols, etc.)

  12. Command Pallet

  13. Quick Panel Goto Anything FuzzyFinder (+α) Like File Navigator Command

    Pallet Command Launcher File Completion Methods Navigation Simbols Navigation
  14. Snippets

  15. In-place Snippets Completion

  16. Snippets Candidates from Command Pallet

  17. 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
  18. Plugins

  19. 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
  20. 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
  21. 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
  22. http://wbond.net/sublime_packages/community There are Much More:

  23. ST2 In Practice

  24. $ 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.
  25. $ 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.
  26. “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.
  27. 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
  28. How to Define Snippets

  29. <snippet> <content><![CDATA[ Hello, ${1:this} is a ${2:snippet}. ]]></content> <!-- Optional:

    Set a tabTrigger to define how to trigger the snippet --> <!-- <tabTrigger>hello</tabTrigger> --> <!-- Optional: Set a scope to limit where the snippet will trigger --> <!-- <scope>source.python</scope> --> </snippet> How to Define Snippets Tools → New Snippet Save file with *.sublime-snippet ext.
  30. 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
  31. 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)

    $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:
  33. Python Plugin API

  34. 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
  35. 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
  36. 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
  37. API Details

  38. 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”)
  39. Plugin Name Convention Plugin Class Name: FooBarCommand Command Name: foo_bar

    class FooBarCommand(sublime_plugin.TextCommand): # ... view.run_command(“foo_bar”)
  40. 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.
  41. 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
  42. Available UI Components Status Message Error Message Message Dialog OK/Cancle

    Dialog Quick Panel Input Panel Output Panel
  43. import sublime, sublime_plugin class ExampleStatusMessageCommand(sublime_plugin.ApplicationCommand): def run(self): sublime.status_message("Hello, World!") Status

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

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

    Message Dialog
  46. 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
  47. 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.
  48. 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
  49. Output Panel popwin.el -like interface It’s a bit complecated to

    use Output Panel.
  50. 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"})
  51. 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)
  52. 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`
  53. Practical Plugin Development

  54. 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
  55. 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.
  56. 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.
  57. 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.
  58. 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.
  59. 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
  60. [ { "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:
  61. https://github.com/kentaro/SublimeEijiro Whole the Code is Available at

  62. Recap

  63. • 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
  64. • 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
  65. Try it Now! http://sublimetext.com