dkandalov/live-plugin


IntelliJ plugin for writing plugins at runtime

https://plugins.jetbrains.com/plugin/7282

License: Other

Language: Groovy

Keywords: groovy, groovy-language, groovy-script, ide, intellij-api, intellij-plugin, kotlin, kotlin-script, micro-plugin


LivePlugin

This is a plugin for IntelliJ IDEs to write plugins at runtime. It uses Groovy as main language and has experimental support for Scala and Clojure.

To install search for "liveplugin" in IDE Preferences -> Plugins -> Browse Repositories. Alternatively, download LivePlugin.zip from GitHub and use IDE Preferences -> Plugins -> Install plugin from disk. See also plugin repository page.

demo

Why?

There is great Internal Reprogrammability blog post on this topic by Martin Fowler.

Motivations for LivePlugin are along the same lines:

  • minimal setup to start writing plugin. Creating new project configured for plugin development feels like too much effort if all I want is to write 20 lines of code. LivePlugins exist outside of normal IDE projects and, therefore, can be modified and run from any project.
  • fast feedback loop. Typical plugin development involves starting new instance of IDE and restarting it on every code change which cannot be hot swapped. LivePlugins are run in the same JVM instance, so there is no need to restart IDE.
  • customizable IDE. It is disappointing that most development tools are difficult to customize. After all, developers is the best possible group of people to do it. This plugin is an attempt to improve the situation.

Practical use cases:

  • project-specific workflow automation
  • running existing shell scripts from IDE
  • quick prototyping of IntelliJ plugins
  • experimenting with IntelliJ API

Plugin Examples

Hello world
import static liveplugin.PluginUtil.show
show("Hello world") // shows balloon message with "Hello world" text
Insert New Line Above Action
import com.intellij.openapi.actionSystem.AnActionEvent
import static liveplugin.PluginUtil.*

// This action inserts new line above current line.
// It's a follow-up for these posts:
//   http://martinfowler.com/bliki/InternalReprogrammability.html
//   http://nealford.com/memeagora/2013/01/22/why_everyone_eventually_hates_maven.html
// Note that there is "Start New Line Before Current" action (ctrl + alt + enter) which does almost the same thing.

registerAction("InsertNewLineAbove", "alt shift ENTER") { AnActionEvent event ->
    runDocumentWriteAction(event.project) {
        currentEditorIn(event.project).with {
            def offset = caretModel.offset
            def currentLine = caretModel.logicalPosition.line
            def lineStartOffset = document.getLineStartOffset(currentLine)

            document.insertString(lineStartOffset, "\n")
            caretModel.moveToOffset(offset + 1)
        }
    }
}
show("Loaded 'InsertNewLineAbove' action<br/>Use 'Alt+Shift+Enter' to run it")

See also Scala plugin example, Clojure plugin example and more examples listed below.

How to start writing plugins

  • open Plugins tool window
  • select one of the plugin entries in the panel
    (entries are folders, and plugin.groovy are startup scripts for plugins)
  • click Run icon to execute plugin (or use keyboard shortcuts alt+C, alt+E or ctrl+shift+L)

If the above worked fine:

  • modify plugin.groovy and rerun plugin to see results
  • add built-in plugin examples and experiment with them (in Plugins toolwindow header + button -> Examples)

If something doesn't work, report an issue.

(To use alt+... shortcuts on OSX you might need a workaround, please see this wiki page .)

The main idea

LivePlugin basically runs Groovy code in JVM. Conceptually it's quite simple:

ClassLoader classLoader = createClassLoader(ideClassloader, ...);
GroovyScriptEngine scriptEngine = new GroovyScriptEngine(pluginFolderUrl, classLoader);
scriptEngine.run(mainScriptUrl, createGroovyBinding(binding));

This means that your code is executed in the same environment as IDE internal code. You can use any internal API and observe/change state of any object inside IDE. There are some limitations of course, like final fields and complex APIs not designed to be re-initialized.

To simplify usage of IntelliJ API for practical purposes some parts of IntelliJ API are wrapped in PluginUtil class. This is essentially a layer on top standard IntelliJ API. If you find yourself writing interesting IDE scripts, feel free to create pull request or send a gist to include your code into PluginUtil. This is experimental API and there is no intention to keep it minimal. PluginUtil is not required though and you can always use IntelliJ classes directly.

Also note that:

  • plugins are evaluated with new classloader on each run
  • plugins are stored in $HOME/.$INTELLIJ_VERSION/config/live-plugins (on Mac $HOME/Library/Application Support/IntelliJIdea15/live-plugins) Note that you can use ctrl+shift+C shortcut to copy file/folder path.
  • if available, Groovy library bundled with IDE is used

Misc tips

  • if your plugins are stable enough, you can enable Settings -> Run All Live Plugins on IDE Startup option. If some of the plugins are not meant to be executed at startup, add if (isIdeStartup) return statement at the top.
  • it helps to have JetGroovy plugin installed (only available in IDEs with Java support)
  • you can get auto-completion and code navigation in plugins code
    • install/enable Groovy plugin
    • Plugin toolwindow -> Settings -> Add LivePlugin Jar to Project
      (the jar also includes source code for PluginUtil)
    • Plugin toolwindow -> Settings -> Add IDEA Jars to Project
      (adding jars unrelated to your actual project is a hack but there seems to be no major problems with it)
  • it helps to be familiar with IntelliJ API
  • when plugin seems to be big enough, you can move it to proper plugin project and still use live plugin See liveplugin as an entry point for standard plugins.

More examples

Similar plugins

The idea of running code inside IntelliJ is not original. There are similar plugins (some of them might be out-of-date though):

Wish list

  • try writing plugin for custom language support
  • create AST pattern-matching API (this can be useful for writing inspections/intentions to match/replace parts of syntax tree)
  • try more languages, e.g. Kotlin, Ruby or Java

Contributing

Please see CONTRIBUTING.md.

Project Statistics

Sourcerank 8
Repository Size 57.4 MB
Stars 408
Forks 42
Watchers 23
Open issues 22
Dependencies 0
Contributors 4
Tags 20
Created
Last updated
Last pushed

Top Contributors See all

Dmitry Kandalov Vojtěch Krása Lukas Waslowski jasonnn

Recent Tags See all

v0.6.1beta December 12, 2017
v0.6.0beta December 01, 2017
v0.5.13beta June 01, 2017
v0.5.12beta March 22, 2017
v0.5.11beta December 17, 2016
v0.5.10beta August 15, 2016
v0.5.9beta August 14, 2016
v0.5.8beta May 08, 2016
v0.5.7beta March 16, 2016
v0.5.6beta December 24, 2015
v0.5.5beta December 08, 2015
v0.5.4beta July 27, 2015
v0.5.3beta February 23, 2015
v0.5.2beta January 22, 2015
v0.5.0beta November 25, 2014

Interesting Forks See all

137583937/live-plugin
IntelliJ plugin for writing plugins at runtime
Groovy - Updated - 1 stars

Something wrong with this page? Make a suggestion

Last synced: 2017-11-24 18:50:28 UTC

Login to resync this repository