• 开发sublime插件


    直接给地址,自己看去,https://code.tutsplus.com/tutorials/how-to-create-a-sublime-text-2-plugin--net-22685

    Sublime Text 2 is a highly customizable text editor that has been increasingly capturing the attention of coders looking for a tool that is powerful, fast and modern. Today, we're going to recreate my popular Sublime plugin that sends CSS through the Nettuts+ Prefixr API for easy cross-browser CSS.

    When finished, you’ll have a solid understanding of how the Sublime Prefixr plugin is written, and be equipped to start writing your own plugins for the editor!

    The extension model for Sublime Text 2 is fairly full-featured.

    The extension model for Sublime Text 2 is fairly full-featured. There are ways to change the syntax highlighting, the actual chrome of the editor and all of the menus. Additionally, it is possible to create new build systems, auto-completions, language definitions, snippets, macros, key bindings, mouse bindings and plugins. All of these different types of modifications are implemented via files which are organized into packages.

    A package is a folder that is stored in your Packages directory. You can access your Packages directory by clicking on the Preferences > Browse Packages… menu entry. It is also possible to bundle a package into a single file by creating a zip file and changing the extension to .sublime-package. We’ll discuss packaging a bit more further on in this tutorial.

    Sublime comes bundled with quite a number of different packages. Most of the bundled packages are language specific. These contain language definitions, auto-completions and build systems. In addition to the language packages, there are two other packages: Default and User. The
    Default package contains all of the standard key bindings, menu definitions, file settings and a whole bunch of plugins written in Python. The User package is special in that it is always loaded last. This allows users to override defaults by customizing files in their User package.

    During the process of writing a plugin, the Sublime Text 2 API referencewill be essential.

    During the process of writing a plugin, the Sublime Text 2 API referencewill be essential. In addition, the Default package acts as a good reference for figuring out how to do things and what is possible. Much of the functionality of the editor is exposed via commands. Any operation other than typing characters is accomplished via commands. By viewing the Preferences > Key Bindings - Defaultmenu entry, it is possible to find a treasure trove of built-in functionality.

    Now that the distinction between a plugin and package is clear, let’s begin writing our plugin.

    Sublime comes with functionality that generates a skeleton of Python code needed to write a simple plugin. Select the Tools > New Plugin…menu entry, and a new buffer will be opened with this boilerplate.

    Here you can see the two Sublime Python modules are imported to allow for use of the API and a new command class is created. Before editing this and starting to create our own plugin, let’s save the file and trigger the built in functionality.

    When we save the file we are going to create a new package to store it in. Press ctrl+s (Windows/Linux) or cmd+s (OS X) to save the file. The save dialog will open to the User package. Don’t save the file there, but instead browse up a folder and create a new folder named Prefixr.

    Now save the file inside of the Prefixr folder as Prefixr.py. It doesn’t actually matter what the filename is, just that it ends in .py. However, by convention we will use the name of the plugin for the filename.

    Now that the plugin is saved, let’s try it out. Open the Sublime console by pressing ctrl+`. This is a Python console that has access to theAPI. Enter the following Python to test out the new plugin:

    You should see Hello World inserted into the beginning of the plugin file. Be sure to undo this change before we continue.

    For plugins, Sublime provides three different types of commands.

    • Text commands provide access to the contents of the selected file/buffer via a View object
    • Window commands provide references to the current window via a Window object
    • Application commands do not have a reference to any specific window or file/buffer and are more rarely used

    Since we will be manipulating the content of a CSS file/buffer with this plugin, we are going to use the sublime_plugin.TextCommand class as the basis of our custom Prefixr command. This brings us to the topic of naming command classes.

    In the plugin skeleton provided by Sublime, you’ll notice the class:

    When we wanted to run the command, we executed the following code in the console:

    Sublime will take any class that extends one of the sublime_plugin classes
    (TextCommandWindowCommand or ApplicationCommand), remove the suffix Command and then convert the CamelCaseinto underscore_notation for the command name.

    Thus, to create a command with the name prefixr, the class needs to be PrefixrCommand.

    One of the most useful features of Sublime is the ability to have multiple selections.

    Now that we have our plugin named properly, we can begin the process of grabbing CSS from the current buffer and sending it to the Prefixr API. One of the most useful features of Sublime is the ability to have multiple selections. As we are grabbing the selected text, we need to write our plug into handle not just the first selection, but all of them.

    Since we are writing a text command, we have access to the current view via self.view. The sel() method of the View object returns an iterable RegionSet of the current selections. We start by scanning through these for curly braces. If curly braces are not present we can expand the selection to the surrounding braces to ensure the whole block is prefixed. Whether or not our selection included curly braces will also be useful later to know if we can tweak the whitespace and formatting on the result we getback from the Prefixr API.

    This code replaces the content of the skeleton run() method.

    If we did not find any curly braces we loop through each selection and adjust the selections to the closest closing curly brace. Next, we use the built-in command expand_selection with the to arg set to brackets to ensure we have the complete contents of each CSS block selected.

    If you would like to double check your work so far, please compare the source to the file Prefixr-1.py in the source code zip file.

    To prevent a poor connection from interrupting other work, we need to make sure that the Prefixr API calls are happening in the background.

    At this point, the selections have been expanded to grab the full contents of each CSS block. Now, we need to send them to the Prefixr API. This is a simple HTTP request, which we are going to use the urllib and urllib2 modules for. However, before we start firing off web requests, we need to think about how a potentially laggy web request could affect the performance of the editor. If, for some reason, the user is on a high-latency, or slow connection, the requests to the Prefixr API could easily take a couple of seconds or more.

    To prevent a poor connection from interrupting other work, we need to make sure that the Prefixr API calls are happening in the background. If you don't know anything about threading, a very basic explanation is that threads are a way for a program to schedule multiple sets of code to run seemingly at the same time. It is essential in our case because it lets the code that is sending data to, and waiting for a response from, the Prefixr API from preventing the rest of the Sublime user interface from freezing.

    We will be using the Python threading module to create threads. To use the threading module, we create a new class that extends threading.Thread called PrefixrApiCall. Classes that extend threading.Thread include a run()method that contains all code to be executed in the thread.

    Here we use the thread __init__() method to set all of the values that will be needed during the web request. The run() method contains the code toset up and execute the HTTP request for the Prefixr API. Since threads operate concurrently with other code, it is not possible to directly return values. Instead we set self.result to the result of the call.

    Since we just started using some more modules in our plugin, we must add them to the import statements at the top of the script.

    Now that we have a threaded class to perform the HTTP calls, we need to create a thread for each selection. To do this we jump back into the run()method of our PrefixrCommand class and use the following loop:

    We keep track of each thread we create and then call the start() method to start each.

    If you would like to double check your work so far, please compare the source to the file Prefixr-2.py in the source code zip file.

    Now that we've begun the actual Prefixr API requests we need toset up a few last details before handling the responses.

    First, we clear all of the selections because we modified them earlier. Later we will set them back to a reasonable state.

    In addition we start a new Edit object. This groups operations for undo and redo. We specify that we are creating a group for the prefixr command.

    As the final step, we call a method we will write next that will handle the result of the API requests.

    At this point our threads are running, or possibly even completed. Next, we need to implement the handle_threads() method we just referenced. This method is going to loop through the list of threads and look for threads that are no longer running.

    If a thread is still alive, we add it to the list of threads to check again later. If the result was a failure, we ignore it, however for good results we call a new replace() method that we'll be writing soon.

    If there are any threads that are still alive, we need to check those again shortly. In addition, it is a nice user interface enhancement to provide an activity indicator to show that our plugin is still running.

    The first section of code uses a simple integer value stored in the variable i to move an = back and forth between two brackets. The last part is the most important though. This tells Sublime to run the handle_threads()method again, with new values, in another 100 milliseconds. This is just like the setTimeout() function in JavaScript.

    The lambda keyword is a feature of Python that allows us to create a new unnamed, or anonymous, function.

    The sublime.set_timeout() method requires a function or method and the number of milliseconds until it should be executed. Without lambda we could tell it we wanted to run handle_threads(), but we would not be able to specify the parameters.

    If all of the threads have completed, we don't need to set another timeout, but instead we finish our undo group and update the user interface to let the user know everything is done.

    If you would like to double check your work so far, please compare the source to the file Prefixr-3.py in the source code zip file.

    With our threads handled, we now just need to write the code that replaces the original CSS with the result from the Prefixr API. As we referenced earlier, we are going to write a method called replace().

    This method accepts a number of parameters, including the Edit object for undo, the thread that grabbed the result from the Prefixr API, if the original selection included braces, and finally the selection offset.

    The offset is necessary when dealing with multiple selections. When we replace a block of CSS with the prefixed CSS, the length of that block will increase. The offset ensures we are replacing the correct content for subsequent selections since the text positions all shift upon each replacement.

    The next step is to prepare the result from the Prefixr API to be dropped in as replacement CSS. This includes converting line endings and indentation to match the current document and original selection.

    As a final step we set the user’s selection to include the end of the last line of the new CSS we inserted, and then return the adjusted offset to use for any further selections.

    If you would like to double check your work so far, please compare the source to the file Prefixr-4.py in the source code zip file.

    We used two custom methods during the replacement process to prepare the new CSS for the document. These methods take the result of Prefixr and modify it to match the current document.

    normalize_line_endings() takes the string and makes sure it matches the line endings of the current file. We use the Settings class from the Sublime API to get the proper line endings.

    The fix_whitespace() method is a little more complicated, but does the same kind of manipulation, just for the indentation and whitespace in the CSS block. This manipulation only really works with a single block of CSS, so we exit if one or more braces was included in the original selection.

    Otherwise, we start by determining the indent level of the original CSS. This is done by searching for whitespace at the beginning of the selection.

    Next we trim the whitespace from the prefixed CSS and use the current view settings to indent the trimmed CSS to the original level using either tabs or spaces depending on the current editor settings.

    We finish the method up by using the original beginning and trailing white space to ensure the new prefixed CSS fits exactly in place of the original.

    With the fix_whitespace() method we used the Python regular expression (re)module, so we need to add it to the list of imports at the top of the script.

    And with this, we've completed the process of writing the prefixrcommand.The next step it to make the command easy to run by providing a keyboard shortcut and a menu entry.

    Most of the settings and modifications that can be made to Sublime are done via JSON files, and this is true for key bindings. Key bindings are usually OS-specific, which means that three key bindings files will need to be created for your plugin. The files should be named Default (Windows).sublime-keymapDefault (Linux).sublime-keymap and Default (OSX).sublime-keymap.

    The .sublime-keymap files contain a JSON array that contains JSON objects to specify the key bindings. The JSON objects must contain a keys and commandkey, and may also contain a args key if the command requires arguments. The hardest part about picking a key binding is to ensure the key binding is not already used. This can be done by going to the Preferences > Key Bindings – Default menu entry and searching for the keybinding you wish to use. Once you’ve found a suitably unused binding, add it to your .sublime-keymap files.

    Normally the Linux and Windows key bindings are the same. The cmd key on OS Xis specified by the string super in the .sublime-keymap files. When porting a key binding across OSes, it is common for the ctrl key onWindows and Linux to be swapped out for super on OS X. This may not, however, always be the most natural hand movement, so if possible try and test your keybindings out on a real keyboard.

    One of the cooler things about extending Sublime is that it is possible to add items to the menu structure by creating .sublime-menu files. Menufiles must be named specific names to indicate what menu they affect:

    • Main.sublime-menu controls the main program menu
    • Side Bar.sublime-menu controls the right-click menu on a file or folder in the sidebar
    • Context.sublime-menu controls the right-click menu on a file being edited

    There are a whole handful of other menu files that affect various other menus throughout the interface. Browsing through the Default package is the easiest way to learn about all of these.

    For Prefixr we want to add a menu item to the Edit menu and some entries to the Preferences menu for settings. The following example is the JSON structure for the Edit menu entry. I’ve omitted the entries for the Preferences menu since they are fairly verbose being nested a few levels deep.

    The one piece to pay attention to is the id keys. By specifying the idof an existing menu entry, it is possible to append an entry without redefining the existing structure. If you open the Main.sublime-menu file from the Defaultpackage and browse around, you can determine what idyou want to add your entry to.

    At this point your Prefixr package should look almost identical to the official version on GitHub.

    钟声敲响了日落
  • 相关阅读:
    Thymeleaf基本知识
    Hibernate学习总结
    oracle学习笔记第三天
    oracle学习笔记第二天
    oracle学习笔记第一天
    Cloudera Hadoop 环境搭建(离线安装)
    SpringBoot搭建基于Apache Shiro+Redis的分布式Session共享功能
    SpringBoot搭建基于Apache Shiro的权限管理功能
    Mybatis基于SqlSession实现CRUD
    Mybatis基于接口注解配置SQL映射器(二)
  • 原文地址:https://www.cnblogs.com/SATinnovation/p/6751705.html
Copyright © 2020-2023  润新知