├── .gitignore ├── LICENSE ├── README.md └── images ├── .DS_Store ├── Extension@2x.png ├── Screen Shot 2015-07-22 at 1.30.25 PM.png ├── Screen Shot 2015-07-22 at 1.34.33 PM.png ├── SearchSentence@2x.png ├── SpanishSentence@2x.png ├── TweetCommand 1@2x.png ├── TweetCommand@2x.png ├── TweetSentence 1@2x.png ├── TweetSentence 2@2x.png ├── TweetSentence@2x.png ├── TwitterShot 1@2x.png └── TwitterShot@2x.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 27 | node_modules 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 lacona 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lacona Kickstarter Nerd Details 2 | 3 | Technical information about developing custom Lacona Commands. For the [Kickstarter Campaign](https://www.kickstarter.com/projects/2102999333/lacona-natural-language-commands-for-your-mac). Read at your own risk. 4 | 5 | Lacona extentions are written in Javascript, which run in a Node.js process alongside the app. They have the full power of Node.js along with their disposal, along with an additional custom Lacona library for interfacing with some Mac-specific features like Spotlight. Commands can also make use of AppleScript to interact with other apps. 6 | 7 | Lacona supports two different kinds of addons - **commands**, which give Lacona new functionality, and **extensions**, which build upon existing functionality. Both commands and extensions are defined using Javascript code. At launch, you won't be able to extend Lacona without touching some code. At some point, I would love to develop a GUI command and extension development, but that would be a stretch goal. 8 | 9 | ## Commands 10 | 11 | I'll explain by way of example. You could make a new command that allows users to tweet. You define two things: the **grammar** (sentence structure) and the **logic** (the code that physically sends the tweet to Twitter). The image below shows the grammar in a pseudocode format. To see what the code will really look like, check out the [show me the code](#show-me-the-code) section. 12 | 13 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetCommand@2x.png) 14 | 15 | That's it - you just specify the sentence structure, and assign an `id` to the relevant pieces. You don't need to think about the parsing logic at all. 16 | 17 | Lacona users who install your command can now make some insightful tweets. 18 | 19 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetSentence@2x.png) 20 | 21 | A few things you should notice: 22 | 23 | - You do not need to do anything fancy to allow the user to input a string that is less than 140 characters - that is all built into Lacona with the `` component. 24 | - You are providing many different ways for the user to input the same thing. This flexibility allows anyone to use Lacona in the way that is most natural for them. 25 | - Someone can translate your command, and as long as you they put in a `` with `id = message`, it will work with the same code. Here is an example with Spanish. 26 | 27 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetCommand 1@2x.png) 28 | 29 | Notice that we have added a new language, with a new grammar, but the code hasn't changed at all. You can do this for every language under the sun. 30 | 31 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/SpanishSentence@2x.png) 32 | 33 | You can think of commands as a list of additional sentences that Lacona will be able to understand. They each have a single verb, and they do a single thing. 34 | 35 | ## Extensions 36 | 37 | Extensions build on top of commands. If commands define new sentences, then Extensions provide new phrases with which you can compose those sentences. 38 | 39 | Let's have another example. It may be useful to post the same thing to different social networks. Let's say we want the user to be able enter `tweet my last Facebook status` - a useful thing for those who use multiple social networks. 40 | 41 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetSentence 1@2x.png) 42 | 43 | We already have a Tweet command, but right now, entering `tweet my last Facebook status` would not have the desired results. It would interpret `my last Facebook status` as a string, and post it literally. 44 | 45 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetSentence@2x.png) 46 | 47 | We don't want to rewrite our Tweet Command - we should keep it as general as possible. After all, we wouldn't want to modify the command to fit into every other social network. Instead, we can just extend the `` component. 48 | 49 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/Extension@2x.png) 50 | 51 | Now, any time a `` is used in any Lacona command, `my last Facebook status` will also be an option. Of course, it is possible that the user may want to tweet that exact message, so both options will be presented side-by-side. 52 | 53 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TweetSentence 2@2x.png) 54 | 55 | If the user selects the italicized, purple option, it will have the desired effect. 56 | 57 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/TwitterShot 1@2x.png) 58 | 59 | Many of the built-in commands use the `` component, so the user will now be able to use their last Facebook status in other contexts as well. This may or may not be useful, but the option is always available. 60 | 61 | ![Command Structure](https://raw.github.com/lacona/kickstarter-nerd-details/master/images/SearchSentence@2x.png) 62 | 63 | # Show me the Code 64 | 65 | All Lacona commands run on Node.js. While they can be written in plain JS, the preferred way to write them is actually to use [JSX](https://facebook.github.io/react/docs/jsx-in-depth.html) - a superset of Javascript developed by Facebook for use with the React user interface library. Grammars are defined declaratively using an XML-like syntax, which allows for greater clarity for deeply-nested structures. The code is then transpiled into pure JS using [Babel](https://babeljs.io/) This all may change a bit before the final API release, but it will give you a general idea. Of course, the final API release will include lots of pretty documentation. 66 | 67 | Here is an example of the Tweet command that we created above, in code. 68 | 69 | ```js 70 | /** @jsx createElement */ 71 | import {createElement, Phrase} from 'lacona-phrase' 72 | 73 | class TweetContent extends Phrase { 74 | describe () { 75 | return ( 76 | 77 | 78 | 79 | ) 80 | } 81 | } 82 | 83 | class TweetCommand extends Phrase { 84 | describe () { 85 | return ( 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | ) 102 | } 103 | 104 | execute (result) { 105 | send_to_twitter(result.message) 106 | } 107 | } 108 | ``` 109 | 110 | And here is an example of the `my last Facebook status` extension. 111 | 112 | ```js 113 | /** @jsx createElement */ 114 | import {createElement, Phrase} from 'lacona-phrase' 115 | import String from 'LaconaCommand-String' 116 | 117 | class FacebookExtension extends Phrase { 118 | getValue () { 119 | return get_last_facebook_status() 120 | } 121 | 122 | describe () { 123 | return 124 | } 125 | } 126 | 127 | FacebookExtension.extends = [String] 128 | ``` 129 | 130 | ## Internationalization 131 | 132 | Of course, the problem with Natural Language interfaces is that they're fairly difficult to translate. It's not enough to simply translate the labels in a form and call it a day. Here are just a few common design issues. 133 | 134 | - Languages have different word order, including the position of verbs 135 | - Some languages have accented/modified characters, which can be essential but are a pain to type 136 | - Some languages have dramatic differences between dialects 137 | - Some languages have multiple sets of characters with the same meaning 138 | - Some languages separate words with spaces, others do not 139 | - Some languages are written left-to-right, some right-to-left 140 | - In some languages, it is common to use foreign words or characters to express certain concepts even if words to represent them do exist in the language 141 | - In some languages, the user enters text in one character set, and replaced with different characters over time 142 | - Some languages have words that simply do not have an equivalent in other languages 143 | - Some languages use distinguish between different verbs depending upon the verb's object, while other languages do not 144 | - Clearly, there are a lot of issues. Because of this, Lacona's language processing is as general as possible. It does not rely on the verb coming at the beginning of a sentence, it does not rely on words being separated by spaces, and it does not rely on any particular character set. It takes any input, interprets it according to its Commands, forms an data structure based upon the input, and sends the data to the command to execute. 145 | 146 | This means that the *language* of Commands can be translated, while keeping the *code* the same. Developers do not need to know any other languages, or anything about language processing at all. And translators don't need to know anything about code. Lacona handles all of that. 147 | 148 | ## Under the Hood 149 | 150 | Lacona does not know English. That is to say, it cannot break a sentence into grammatical components, and it cannot infer any meaning from an arbitrary sentence. It understands only the sentences that have been described for it in Commands, and nothing more. 151 | 152 | This means that everything that Lacona can do must be translated manually into every new language that it is to support. Lacona will only launch with support for US and UK English. However, all of the Lacona commands will be open-source, so that multilingual users from around the world can add new translations. 153 | 154 | To get a bit more technical, you can think of Lacona Commands as closer Formal Grammars, or very glorified Regular Expressions. It takes arbitrary strings as input, and interprets them according to its rules. I am not an expert in computational linguistics, but I can provide a bit more information. the biggest differences are: 155 | 156 | - Lacona Commands are not necessarily Regular or Context-Free. Commands are composed of components, which can be thought of as similar to rules in a formal grammar. However complex components can be much more complex - they can even make use of arbitrary code to handle possible inputs. 157 | - Lacona Commands are designed to not only interpret an string after it has been input, but also while it is being input. For example, the string "617-" is very clearly not a valid Phone Number, but it is possible that it is the beginning of a Phone Number. Lacona needs to identify that. 158 | - Lacona command components can be evaluated dynamically, so grammars can change state based on external factors, such as the contents of the clipboard, results of scripts or network requests, or the current date. 159 | - Altogether, this means that Lacona has a language processing system that is general enough to support all of the quirks of language, but simple enough be accessible. Simple commands are easy, and very complex commands are possible. 160 | 161 | ## Further information 162 | 163 | Of course, this is just an introduction. Much more information will be available with the release of the API. If you have further questions, please ask on [Kickstarter](https://www.kickstarter.com/projects/2102999333/lacona-natural-language-commands-for-your-mac) or [Twitter](https://twitter.com/lacona). 164 | -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/.DS_Store -------------------------------------------------------------------------------- /images/Extension@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/Extension@2x.png -------------------------------------------------------------------------------- /images/Screen Shot 2015-07-22 at 1.30.25 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/Screen Shot 2015-07-22 at 1.30.25 PM.png -------------------------------------------------------------------------------- /images/Screen Shot 2015-07-22 at 1.34.33 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/Screen Shot 2015-07-22 at 1.34.33 PM.png -------------------------------------------------------------------------------- /images/SearchSentence@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/SearchSentence@2x.png -------------------------------------------------------------------------------- /images/SpanishSentence@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/SpanishSentence@2x.png -------------------------------------------------------------------------------- /images/TweetCommand 1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TweetCommand 1@2x.png -------------------------------------------------------------------------------- /images/TweetCommand@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TweetCommand@2x.png -------------------------------------------------------------------------------- /images/TweetSentence 1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TweetSentence 1@2x.png -------------------------------------------------------------------------------- /images/TweetSentence 2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TweetSentence 2@2x.png -------------------------------------------------------------------------------- /images/TweetSentence@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TweetSentence@2x.png -------------------------------------------------------------------------------- /images/TwitterShot 1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TwitterShot 1@2x.png -------------------------------------------------------------------------------- /images/TwitterShot@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandonhorst/kickstarter-nerd-details/a34ce7a255f8a547c3a85276f8b8d228a7b7f57b/images/TwitterShot@2x.png --------------------------------------------------------------------------------