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
Tweet

More Decks by Kentaro Kuribayashi

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

  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...

    View Slide

  4. Sublime Text 2

    View Slide

  5. View Slide

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

    View Slide

  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

    View Slide

  8. Quick Panel

    View Slide

  9. Goto Anything

    View Slide

  10. Goto Anything
    (Methods, etc.)

    View Slide

  11. Goto Anything
    (Simbols, etc.)

    View Slide

  12. Command Pallet

    View Slide

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

    View Slide

  14. Snippets

    View Slide

  15. In-place
    Snippets Completion

    View Slide

  16. Snippets Candidates
    from Command Pallet

    View Slide

  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

    View Slide

  18. Plugins

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  23. ST2 In Practice

    View Slide

  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.

    View Slide

  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.

    View Slide

  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.

    View Slide

  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

    View Slide

  28. How to Define
    Snippets

    View Slide


  29. Hello, ${1:this} is a ${2:snippet}.
    ]]>





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

    View Slide

  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

    View Slide

  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)

    View Slide

  32. 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:

    View Slide

  33. Python
    Plugin API

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  37. API Details

    View Slide

  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”)

    View Slide

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

    View Slide

  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.

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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.

    View Slide

  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

    View Slide

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

    View Slide

  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"})

    View Slide

  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)

    View Slide

  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`

    View Slide

  53. Practical Plugin
    Development

    View Slide

  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

    View Slide

  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.

    View Slide

  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.

    View Slide

  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.

    View Slide

  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.

    View Slide

  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

    View Slide

  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:

    View Slide

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

    View Slide

  62. Recap

    View Slide

  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

    View Slide

  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

    View Slide

  65. Try it Now!
    http://sublimetext.com

    View Slide