Skip to content
This repository was archived by the owner on Oct 21, 2022. It is now read-only.

Corrected a couple minute typos #1

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion behaviors-file-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ or multiple \(in order\)

`[:files :lt.objs.files/file-types [{:exts [:elm], :mime "text/x-elm", :tags [:editor.elm], :name "elm"}]]`

Light Table ships with a wide range of mapping to file types to provide syntax highlighting. However you might be developing a plugin for a new language not covered. This config allows you to associate a new file extentions and provide a tag for editors of this file type. In the example above we've added support for files from the Elm programming language. Every Elm file editor object will now get a tag `:editor.elm`.This is obviously useful when you want to configure behaviors that are specific for Elm editors \(say like code eval, docs etc\).
Light Table ships with a wide range of mapping to file types to provide syntax highlighting. However you might be developing a plugin for a new language not covered. This config allows you to associate a new file extensions and provide a tag for editors of this file type. In the example above we've added support for files from the Elm programming language. Every Elm file editor object will now get a tag `:editor.elm`.This is obviously useful when you want to configure behaviors that are specific for Elm editors \(say like code eval, docs etc\).

## Adding tags to objects of a given tag

Expand Down
22 changes: 11 additions & 11 deletions building-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ The right sidebar in Light Table allows for adding items dynamically. By default
```clojure
(ns lt.plugins.myplugin.modules
(:require [lt.object :as object]
[lt.objs.sidebar :as sidebar]
[lt.objs.command :as cmd]
[lt.objs.sidebar :as sidebar]
[lt.objs.command :as cmd]
[lt.util.dom :as dom])
(:require-macros [lt.macros :refer [defui behavior]]))

Expand Down Expand Up @@ -59,17 +59,17 @@ The right sidebar in Light Table allows for adding items dynamically. By default
(object/raise modulebrowser-bar :show-modules))})

```
1. `defui` is a macro which helps produce html dom elements. Here we just create a wrapper div for our sidebar item
2. Much like in [hiccup](https://github.com/weavejester/hiccup) in `defui` we can work with markup as data structures. We can map, filter and the like. Here we map over the modules to produce `li` elements
1. `defui` is a macro which helps produce HTML DOM elements. Here we just create a wrapper div for our sidebar item
2. Much like in [hiccup](https://github.com/weavejester/hiccup) in `defui` we can work with markup as data structures. We can use map, filter and the like. Here we map over the modules to produce `li` elements
3. We've created a function responsible for rendering our modules list
4. `dom/$` is a utility function for selecting the first item satisifying the given query selector. We retrieve the empty ul element
5. Now we replace the empty ul element from above with the ul element created from `render-modules`
6. We've created a behavior to allow the display of the modulebrowser to be configurable
4. `dom/$` is a utility function for selecting the first item satisfying the given query selector. We retrieve the empty `ul` element.
5. Now we replace the empty `ul` element from above with the `ul` element created from `render-modules`
6. We've created a behavior to allow the display of the module browser to be configurable
7. We raise a `:toggle` trigger on the `rightbar` object in the `lt.objs.sidebar` namespace. The responding behavior
will toggle the display of the sidebar and making sure that our modulebrowser is shown as the active/visible item (alternatively hiding the sidebar all together)
8. We render our current list of modules. Currently hardcoded, so imagine the list of modules is created somewhat more dynamically !
9. We've configured our modulebrowser object programtically to be tied to our show behavior. Normally you would do this in a `.behaviors` file for your plugin declaratively
10. The init function is called upon creation of our object. If the init function returns markup, that will be available
will toggle the display of the sidebar and making sure that our module browser is shown as the active/visible item (alternatively hiding the sidebar all together)
8. We render our current list of modules. Currently hard-coded, so imagine the list of modules is created some what more dynamically !
9. We've configured our module browser object programatically to be tied to our show behavior. Normally you would do this in a `.behaviors` file for your plugin declaratively
10. The init function is called upon the creation of our object. If the init function returns markup, that will be available
through the `object/->content` function we saw in our `render-modules` function.
11. We create an instance of our modulebrowser object
12. This is how we add an additional item to the Light Table sidebar. It will be added, but not visible (until we trigger the `:toggle` behavior mentioned previously
Expand Down
39 changes: 20 additions & 19 deletions user-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,26 @@ Commands are the user facing functionality in Light Table. They are typically li

```

1. We give our command an id. That way we can refer to that command from other places. Typically you want to be able to assign keyboard shortcuts to a command. The id is how you can map a keyboard shortcut to your command.
1. We give our command an ID. That way we can refer to that command from other places. Typically you want to be able to assign keyboard shortcuts to a command. The ID is how you can map a keyboard shortcut to your command.
2. Give the command a sound description. Commands are shown in the Command Pane in Light Table, so you want to provide a meaningful description so people know what the command does.
3. This is where we define what's going to happen when the command is to be executed
4. We are using a function `last-active` from the `lt.objs.editor.pool` namespace to get hold of the current Editor. Or currently focused open file if that makes more sense. Actually we are not getting the file, but we are getting an `object` representing that file.
5. The editor object we have access to is a special kind of object. It's basically a wrapped ClojureScript [atom. ](http://clojure.org/reference/atoms). Now that's not to important, the main point is that this object contains meta information that we can access. So in JavaScript terms you could read this as `ed.info.path`
5. The editor object we have access to is a special kind of object. It's basically a wrapped ClojureScript [atom. ](http://clojure.org/reference/atoms). Now that's not too important, the main point is that this object contains meta information that we can access. So in JavaScript terms you could read this as `ed.info.path`

**To make this command available we need to connect to the user plugin project and then evaluate it.**

1. Save the file - When you hit save it will first connect to the project and then compile the ClojureScript code in your user plugin to JavaScript. So first time it take a little time, after that it will be much faster.
2. With the cursor inside the command definition\/\(form in Clojure terms\)
1. Open the command pane \(ctrl-space\)
2. Search for the command `Eval: Eval a form in editor`. Select that
2. Search for the command `Eval: Eval a form in editor`. Select that option.
3. Light Table will tell you to connect to plugin. Click the button `Connect a Client`
4. From the list of available clients select `Light Table UI`
5. You should see `nil` shown after the form. If not try to evaluate one more time.


> When you evaluate code like we just did, LIght Table will during runtime compile the code \(using the ClojureScript compiler\) to JavaScript and add the resulting JavaScript to the running Light Table. You can now make changes to the command as you wish, and re-evaluate it. That will replace the runtime definition of the command with a new definition. This way of developing provides really fast turnaround and promotes a stepwise interactive approach to buidling things.
> When you evaluate code like we just did, Light Table will, during runtime compile the code \(using the ClojureScript compiler\) to JavaScript and add the resulting JavaScript to the running Light Table instance. You can now make changes to the command as you wish, and re-evaluate it. That will replace the runtime definition of the command with a new definition. This way of developing provides really fast turnaround and promotes a stepwise interactive approach to buidling things.

You should now be able to call the command. Just open the command pane and search for the description you gave the command. Select \`View -> Console\` from the menu to open the console if you don't already have it open. Voila you should see the filename of the editor you had focus on when invoking your new command !
You should now be able to call the command. Just open the command pane and search for the description you gave the command. Select \`View -> Console\` from the menu to open the console if you don't already have it open. Voilà you should see the filename of the editor you had focus on when invoking your new command !

## Adding your own behavior

Expand All @@ -69,22 +69,22 @@ You should now be able to call the command. Just open the command pane and searc
(lt.objs.notifos/set-msg! (-> @ed :info :path)))) ;; 5.
```

1. We give our behaviour an id. We are going to need this id to be able to configure when this behavior should be triggered
1. We give our behaviour an ID. We are going to need this ID to be able to configure when this behavior should be triggered
2. This is optional, but it's nice for documentation and you'll see that it's also helpful when we wire it up in the next section
3. Triggers are the definition of event name\(s\) that should trigger this behavior to execute
3. Triggers are the definition of event name\(s\) that should trigger this behavior to be executed.
4. The reaction, defines the function that should be executed when the behavior is triggered. You'll also notice we've
assumed a parameter ed, ie we are expecting this behavior function to be called with an editor object.
assumed a parameter `ed`, i.e. we are expecting this behavior function to be called with an editor object.
5. Finally we use the `set-msg!` function from the `lt.objs.notifos` namespace to set a message with the editors file name in the bottom status bar in Light Table. \(The message will by default be displayed for 10 seconds\)

**Assuming you have already gone through the command example in the previous example you need to:**

1. First scroll to the top of the `User.cljs` file and put the cursor inside the ns form and then evaluate that.
2. Then scroll back to the behaviour and evaluate that
1. First scroll to the top of the `user.cljs` file and put the cursor inside the `ns` form and then evaluate that command.
2. Then scroll back to the behaviour and evaluate that snippet.

**We are not quite done yet, we also need to tell Light Table how and what should make this behavior actually trigger**

1. Open the command pane and search for `Settings: User behaviors` and select that
2. Add the below definition to the file and then save
1. Open the command pane and search for `Settings: User behaviors` and select that option.
2. Add the below definition to the file and then hit save.

```clojure
[:editor :lt.plugins.user/user.display-filename]
Expand All @@ -93,7 +93,7 @@ You should now be able to call the command. Just open the command pane and searc
* If you put your cursor over inside or right next to that line, you will see the description we provided to our behavior is shown highlighted next to the right bracket
* `:editor` is a tag that tells Light Table that this the behavior should be considered for any object in Light Table
that has this tag should be considered a candidate for it to be triggered. All open files are represented as editor objects and they all have by default this tag.
* The final piece of the puzzle is the trigger we defined for our behavior. So whenever someone\/somewhere raises a `:trigger` event on an editor instance Light Table now knows enough to invoke our behavior reaction function. Triggering :focus is something that is done inside another behavior in Light Table, let's not worry to much about that for now.
* The final piece of the puzzle is the trigger we defined for our behavior. So whenever someone\/somewhere raises a `:trigger` event on an editor instance Light Table now knows enough to invoke our behavior reaction function. Triggering :focus is something that is done inside another behavior in Light Table, let's not worry too much about that for now.

![](/assets/lt-user-plugin-beh.png)
### Flexibility through the BOT architecture
Expand All @@ -103,17 +103,18 @@ The combination of **B**ehavior, **O**bject and **T**ags is what is described as
1. **Tags**: You can target behaviors to object with certain tags. So if you change the above behavior wiring to
1. `[:editor.javascript :lt.plugins.user/user.display-filename]`
2. Now the behaviour will only trigger when JavaScript files\(\/editors\) receive the `:focus` trigger. BTW, you can have multiple behavior wirings for the same behavior, so if you would like this behavior to happen for Clojure and Elm files just add a line for each of them.
3. If you'd like to turn off the behavior you can just use the following syntax `[:editor :-lt.plugins.user/user-display-filename]`. Note the minus sigh.
3. If you'd like to turn off the behavior you can just use the following syntax `[:editor :-lt.plugins.user/user-display-filename]`. Note the `
minus sign` on the second part of the expression.
4. When you save the behaviors file, the changes will be applied at once. Runtime.

2. **Triggers**: You can have multiple triggers for your behavior. Say you wanted to also display the filename whenever the editor changes. Just add `:change` to the set of triggers in your behavior and reevaluate it.
2. **Triggers**: You can have multiple triggers for your behaviors. Say, you wanted to also display the filename whenever the editor changes. Just add `:change` to the set of triggers in your behavior and reevaluate it.

3. **Objects**: You can add or remove tags to objects both at declaration time, programatically or in your User.behaviors file. For example if you add the following to your `User.behaviors` file `[:editor :lt.obj/add-tag :mytag]` all editor objects in Light Table will also receive the `:mytag` tag.
3. **Objects**: You can add or remove tags to objects in two distinct ways. At declaration time, programatically or in your `user.behaviors` file. For example, if you add the following to your `user.behaviors` file `[:editor :lt.obj/add-tag :mytag]` all editor objects in Light Table will also receive the `:mytag` tag.

4. **Behaviors**: What's more you can also add or remove behaviors to objects during runtime both in your `User.behaviors`file or programatically.
4. **Behaviors**: What's more, you can also add or remove behaviors to objects _during runtime_ both in your `User.behaviors`file or programatically.


You don't need to understand or use all this from the off, but hopefully you get and idea of the flexibility of the BOT architecture.
You don't need to understand or use all this from the very start, but hopefully you get an idea of the flexibility of the BOT architecture.

> You can get far by just using commands and normal ClojureScript functions, but if you want to create a runtime configurable plugin you'll want to start looking at using behaviors.
> You can get far just by using commands and simple ClojureScript functions, but if you want to create a runtime configurable plugin you'll want to start looking at using behaviors.