• Stars
    star
    1,355
  • Rank 34,674 (Top 0.7 %)
  • Language
    CoffeeScript
  • License
    MIT License
  • Created over 11 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Omelette is a simple, template based autocompletion tool for Node and Deno projects with super easy API. (For Bash, Zsh and Fish)

Omelette is a simple template based autocompletion tool for Node and Deno projects with super easy API.

npm version Build Status

yarn add omelette
# or
npm install omelette

You also can use Omelette with Deno:

import omelette from "https://deno.land/x/omelette/omelette.ts";

You just have to decide your program name and CLI fragments.

omelette`github ${['pull', 'push']} ${['origin', 'upstream']} ${['master', 'develop']}`.init()

...and you are almost done! The output will look like this:

Quick Start

For a step by step guide please follow this link

Implementing omelette is very easy:

import * as omelette from 'omelette';

const firstArgument = ({ reply }) => {
  reply([ 'beautiful', 'cruel', 'far' ])
}

const planet = ({ reply }) => {
  reply([ 'world', 'mars', 'pluto' ])
}

omelette`hello|hi ${firstArgument} ${planet}`.init()

Simple Event Based API ☕️

It's based on a simple CLI template.

Let's think we have a executable file with the name githubber, in a global path.

In our program, the code will be:

import * as omelette from 'omelette';

// Write your CLI template.
const completion = omelette(`githubber|gh <action> <user> <repo>`);

// Bind events for every template part.
completion.on('action', ({ reply }) => {
  reply([ 'clone', 'update', 'push' ])
})

completion.on('user', ({ reply }) => {
  reply(fs.readdirSync('/Users/'))
})

completion.on('repo', ({ before, reply }) => {
  reply([
    `http://github.com/${before}/helloworld`,
    `http://github.com/${before}/blabla`
  ])
})

// Initialize the omelette.
completion.init()

// If you want to have a setup feature, you can use `omeletteInstance.setupShellInitFile()` function.
if (~process.argv.indexOf('--setup')) {
  completion.setupShellInitFile()
}

// Similarly, if you want to tear down autocompletion, use `omeletteInstance.cleanupShellInitFile()`
if (~process.argv.indexOf('--cleanup')) {
  completion.cleanupShellInitFile()
}

// Rest is yours
console.log("Your program's default workflow.")
console.log(process.argv)

complete.reply is the completion replier. You must pass the options into that method.

ES6 Template Literal API 🚀

You can use Template Literals to define your completion with a simpler (super easy) API.

import * as omelette from 'omelette';

// Just pass a template literal to use super easy API.
omelette`hello ${[ 'cruel', 'nice' ]} ${[ 'world', 'mars' ]}`.init()

Let's make the example above with ES6 TL:

import * as omelette from 'omelette'

// Write your CLI template.
omelette`
  githubber|gh

  ${[ 'clone', 'update', 'push' ]}
  ${() => fs.readdirSync('/Users/')}
  ${({ before }) => [
    `http://github.com/${before}/helloworld`,
    `http://github.com/${before}/blabla`,
  ]}
`.init()

Also you can still use lambda functions to make more complex template literals:

Advanced Template Literals

import * as omelette from 'omelette';

omelette`
  githubber|gh
      ${['pull', 'push', 'star'] /* Direct command list */}
      ${require('some/other/commands') /* Import from another file */}
      ${getFromRemote('http://api.example.com/commands') /* Remote call at the beginning */}
      ${({ reply }) => fetch('http://api.example.com/lazy-commands').then(reply) /* Fetch when argument <tab>bed */}
      ${() => fs.readdirSync("/Users/") /* Access filesystem via Node */}
      ${({ before }) => [ /* Use parameters like `before`, `line`, `fragment` or `reply` */
        `${before}/helloworld`,
        `${before}/blabla`
      ]}
  `.init()

// No extra configuration required.

console.log("Your program's default workflow.")
console.log(process.argv)

Async API

Omelette allows you to use async functions. You have to use onAsync and to pass Promise object to the reply function.

complete.onAsync('user', async ({ reply }) => {
  reply(new Promise((resolve) => {
    fs.readdir('/Users/', (err, users) => {
      resolve(users)
    })
  }))
})

⚠️ A note about async handlers

If you are using async handlers, you have to use complete.next method to continue running your main workflow.

// ...

complete.onAsync('user', async ({ reply }) => {
  reply(new Promise((resolve) => {
    fs.readdir('/Users/', (err, users) => {
      resolve(users)
    })
  }))
})

// Instead of running directly, you need to set an handler to run your main workflow.
complete.next(()=> {
  console.log("Your program's default workflow.")
  console.log(process.argv)
})

// .init must be called after defining .next
complete.init()
// ...

Using util.promisify will make your async handlers easier.

import promisify from 'util';

complete.onAsync('user', async ({ reply }) => {
  reply(await promisify(fs.readdir)('/Users'))
})

Tree API 🌲

You can use simple objects as autocompletion definitions:

omelette('hello').tree({
  cruel: ['world', 'moon'],
  beautiful: ['mars', 'pluto']
}).init();

Install

Automated Install

⚠️ Not available for Deno runtime. You can make your users to put yourprogram --completion | source or yourprogram --completion-fish | source args explicitly to their shell config file.

Installing and making your users install the autocompletion feature is very simple.

You can use simply use setupShellInitFile function.

try {
  // Pick shell init file automatically
  complete.setupShellInitFile()

  // Or use a manually defined init file
  complete.setupShellInitFile('~/.my_bash_profile')

} catch (err) {
  // setupShellInitFile() throws if the used shell is not supported
}

If you use Bash, it will create a file at ~/.<program-name>/completion.sh and append a loader code to ~/.bash_profile file.

If you use Zsh, it appends a loader code to ~/.zshrc file.

If you use Fish, it appends a loader code to ~/.config/fish/config.fish file.

TL;DR: It does the Manual Install part, basically.

Automated Uninstallation

⚠️ Not available for Deno runtime. Your users need to remove the autocompletion setup script from their shell config files.

Similarly to installation, you can use cleanupShellInitFile to undo changes done by setupShellInitFile.

complete.cleanupShellInitFile()

As with setupShellInitFile(), wrap this in a try/catch block to handle unsupported shells.

Manual Installation

Instructions for your README files:

(You should add these instructions to your project's README, don't forget to replace myprogram string with your own executable name)

In zsh, you should write these:

echo '. <(myprogram --completion)' >> ~/.zshrc

In bash:

On macOS, you may need to install bash-completion using brew install bash-completion.

myprogram --completion >> ~/.config/hello.completion.sh
echo 'source ~/.config/hello.completion.sh' >> ~/.bash_profile

In fish:

echo 'myprogram --completion-fish | source' >> ~/.config/fish/config.fish

That's all!

Now you have an autocompletion system for your CLI tool.

Additions

There are some useful additions to omelette.

Parameters

Callbacks have two parameters:

  • The fragment name (e.g.command of <command> template) (only in global event)
  • The meta data
    • fragment: The number of fragment.
    • before: The previous word.
    • line: The whole command line buffer allow you to parse and reply as you wish.
    • reply: This is the reply function to use this-less API.

Global Event

You can also listen to all fragments by "complete" event.

complete.on('complete', (fragment, { reply }) => reply(["hello", "world"]));

Numbered Arguments

You can also listen to events in order.

complete.on('$1', ({ reply }) => reply(["hello", "world"]))

Autocompletion Tree

You can create a completion tree to more complex autocompletions.

omelette('hello').tree({
  how: {
    much: {
      is: {
        this: ['car'],
        that: ['house'],
      }
    },
    are: ['you'],
    many: ['cars', 'houses'],
  },
  where: {
    are: {
      you: ['from'],
      the: ['houses', 'cars'],
    },
    is: {
      // You can also add some logic with defining functions:
      your() {
        return ['house', 'car'];
      },
    }
  },
}).init()

Now, you will be able to use your completion as tree.

Thanks @jblandry for the idea.

Advanced Tree Implementations

You can seperate your autocompletion by importing objects from another file:

omelette('hello').tree(require('./autocompletion-tree.js')).init();

Short Names

You can set a short name for an executable:

In this example, githubber is long and gh is short.

omelette('githubber|gh <module> <command> <suboption>');

Test

Now you can try it in your shell.

git clone https://github.com/f/omelette
cd omelette/example
alias githubber="./githubber" # The app should be global, completion will search it on global level.
./githubber --setup --debug # --setup is not provided by omelette, you should proxy it.
# (reload bash, or source ~/.bash_profile or ~/.config/fish/config.fish)
omelette-debug-githubber # See Debugging section
githubber<tab>
ghb<tab> # short alias
gh<tab> # short alias

Debugging

--debug option generates a function called omelette-debug-<programname>. (omelette-debug-githubber in this example).

When you run omelette-debug-<programname>, it will create aliases for your application. (githubber and gh in this example).

A long name:

$ githubber<tab>
clone update push

Or short name:

$ gh<tab>
clone update push

Then you can start easily.

$ ./githubber<tab>
clone update push
$ ./githubber cl<tab>
$ ./githubber clone<tab>
Guest fka
$ ./githubber clone fka<tab>
$ ./githubber clone fka http://github.com/fka/<tab>
http://github.com/fka/helloworld
http://github.com/fka/blabla

Using with Deno

Omelette now supports and is useful with Deno. You can make your Deno based CLI tools autocomplete powered using Omelette. It's fully featured but setupShellInitFile and cleanupShellInitFile methods does not exist for now (to prevent requirement of allow-env, allow-read and allow-write permissions).

Instructions to use Omelette in your Deno projects:

Assume we have a hello.js:

import omelette from "https://raw.githubusercontent.com/f/omelette/master/deno/omelette.ts";

const complete = omelette("hello <action>");

complete.on("action", function ({ reply }) {
  reply(["world", "mars", "jupiter"]);
});

complete.init();

// your CLI program

Install your program using deno install:

deno install hello.js
hello --completion | source # bash and zsh installation
hello --completion-fish | source # fish shell installation

That's all! Now you have autocompletion feature!

hello <tab><tab>

Users?

  • Office 365 CLI uses Omelette to support autocompletion in office365-cli.
  • Visual Studio App Center CLI uses Omelette to support autocompletion in appcenter-cli.

Contribute

I need your contributions to make that work better!

License

This project licensed under MIT.

More Repositories

1

awesome-chatgpt-prompts

This repo includes ChatGPT prompt curation to use ChatGPT better.
HTML
95,527
star
2

graphql.js

A Simple and Isomorphic GraphQL Client for JavaScript
JavaScript
2,256
star
3

vue-wait

Complex Loader and Progress Management for Vue/Vuex and Nuxt Applications
JavaScript
2,004
star
4

delorean

An Agnostic, Complete Flux Architecture Framework
JavaScript
749
star
5

fatura

eArşiv / eFatura Fatura Oluşturucu
JavaScript
548
star
6

vue-smart-route

Smart route search to make intelligent looking apps with Vue.js.
JavaScript
319
star
7

react-wait

Complex Loader Management Hook for React Applications
JavaScript
305
star
8

atom-term2

THIS PROJECT IS NO LONGER MAINTAINED. PLEASE USE ATOM TERM3 PACKAGE
CoffeeScript
294
star
9

guardian

Guardian watches over your files and run assigned tasks.
Crystal
276
star
10

loremjs

Lorem.js Dummy Text/Image Generator for jQuery and Native JS
HTML
189
star
11

react-hooks-todo-app

A highly testable TodoList app that uses React hooks and Context.
JavaScript
187
star
12

kamber

Static site server (basically blogs) with Crystal Language
Crystal
173
star
13

dom-wait

Complex Loader and Progress Management for Vanilla JS
HTML
143
star
14

pq

Human Readable Promise Chains
JavaScript
143
star
15

vue-plugin-boilerplate

Vue Plugin Boilerplate
JavaScript
122
star
16

confirmation

A simple Node tool to replicate Browser's confirm popup on your CLI.
JavaScript
115
star
17

netflix-data

All Netflix Genres
111
star
18

dahi

Türkçe NLP'de bir marka (Parody)
JavaScript
97
star
19

atom-bootstrap3

Twitter Bootstrap 3 Snippets for Atom
CoffeeScript
81
star
20

completion

Easy Command Line Completion for Crystal
Crystal
70
star
21

honst

Fixes your dataset according to your rules.
JavaScript
69
star
22

do-sshuttle

Use DigitalOcean Droplet to Transparent Proxying via sshuttle
Shell
66
star
23

baristai

TypeScript
66
star
24

equiv

It finds equivalents of the things.
Crystal
61
star
25

kemal-react-chat

This demonstrates how easy it is to build Realtime Web applications with Kemal.
JavaScript
60
star
26

temel

Extensible Markup DSL for Crystal
Crystal
59
star
27

omi-devtools

DevTools for Omi.js
JavaScript
54
star
28

vue-analog-clock-range

Vue Analog Clock Range Component
Vue
52
star
29

kreal

Kreal is a model sharing & RPC library built on and works with Kemal seamlessly.
HTML
44
star
30

ufcs

DLang's Universal Function Call Syntax port to JavaScript
JavaScript
42
star
31

xtract

Extract data from DOM, easily.
JavaScript
40
star
32

lambda.cr

Uniformed function call syntax for Crystal Language.
Crystal
36
star
33

qvimrc

Quick Vimrc
Vim Script
33
star
34

deasciifier

Deasciifier yabancı metinleri Türkçeye çevirmenize yarayan bir uygulamadır.
JavaScript
29
star
35

emoji-downloader

A simple Emoji downloader for CLI
Shell
29
star
36

phaser-coffee-boilerplate

Phaser CoffeeScript + Browserify + LiveReload Boilerplate
CoffeeScript
27
star
37

hexwords-tr

Turkish Hex Words
JavaScript
27
star
38

graphql.js-demo

GraphQL.js Sinatra Example
Ruby
24
star
39

macaron

Macros for CoffeeScript
CoffeeScript
24
star
40

postcss-inline-image

PostCSS plugin that puts images as data URIs into your CSS
JavaScript
21
star
41

sofle-mario

C
21
star
42

dont-fail-me-again

Node.js Error Handler by The Dark Side
JavaScript
21
star
43

fka

JavaScript
20
star
44

idiot

Easier NodeMCU Environment - IoT Made Simple
MoonScript
19
star
45

storm-bitbar

BitBar plugin for Storm-SSH
Shell
16
star
46

veznedar

Arapça Kök Üreteci
JavaScript
16
star
47

graphqljs-rails

GraphQL.js Rails for Rails 5
JavaScript
15
star
48

f

14
star
49

view.coffee

Dead Simple, Vanilla-ish Client-Side Framework based on jQuery, inspired by GitHub's Space-Pen Library
CoffeeScript
13
star
50

jquery.resizestop

Special Event for Resize Controls
12
star
51

awesome-safran

Safran CLI Okuyucuları
12
star
52

safran-cli

Safran.io için command line okuyucu.
JavaScript
11
star
53

GitHubDashboard.kdapp

GitHubDashboard
CoffeeScript
11
star
54

twhosts

Twitter Unblock
10
star
55

jackpack

JackPack
JavaScript
9
star
56

backbone-presentation

Backbone.js Presentation (Turkish)
JavaScript
9
star
57

mood-convert-ampt

JavaScript
9
star
58

popthelock

Pop The Lock JS Clone
8
star
59

mertlang

8
star
60

puremise.js

Yet another purely functional Promise Monad implementation
JavaScript
8
star
61

boehm

7
star
62

wolves

JavaScript port of lykoss/lykos, a Werewolf party game IRC bot
CoffeeScript
7
star
63

knockbone

Knockout.js and Backbone.js Entegration
JavaScript
7
star
64

llm-viz-tr

TypeScript
6
star
65

dyncall

Dynamic method calling support for Crystal Language.
Crystal
6
star
66

lama.app

OS X Application Helper for emre/lama
Objective-C
6
star
67

ircbot

IRC Bot Framework
PHP
6
star
68

kurye

GitHub Project Cloner for Boilerplate Projects
Python
6
star
69

r3

Ruby
5
star
70

html5init

HTML5 Project Startup
CSS
5
star
71

ronin

Very simple Jinja2 based Static Site Boilerplate
Python
5
star
72

plug

jquery plugin generator.
JavaScript
5
star
73

vimme

my newest simple vim environment
Vim Script
5
star
74

shelljs

Javascript + PHP ShellLike Application
5
star
75

pinata

Sinatra-like PHP Framework
PHP
5
star
76

twittersearch

Workshop Project for Ozgur Web Gunleri 2012
JavaScript
4
star
77

restafarian

Node.js Restful Client
3
star
78

mvc

PHP
3
star
79

kamber-theme-default

Kamber Default Template
CSS
3
star
80

cssmodules-demo

Ruby
2
star
81

notes

HTML
2
star
82

win-turkish-us-layout

Windows sistemlere OS X'teki `ALT + harf` desteği sağlar.
2
star
83

kamber-theme-dark

Dark theme for Kamber
CSS
2
star
84

dotvim

Vim Script
1
star
85

lolero

Lölero Language
1
star
86

knapsack-problem

Solving Knapsack Problem with dynamic programming in Ruby
Ruby
1
star
87

umut

1
star
88

turkiye-brand-db

The Brands Database for Turkey
1
star
89

keybase-messenger

keybase based crypted local messenger interface running on firebase
1
star
90

jspy

jspy conference 2012 website
1
star
91

md5solve

MD5 decrypter. Generates content from it's MD5 sum. Work in progress.
1
star
92

react-rails-server-side-example

React Rails with Server Side Rendering Example
JavaScript
1
star
93

crystal-kemal-todo-list

TodoList based on Crystal and Kemal
HTML
1
star
94

react-playground

JavaScript
1
star
95

popeye

Popeye.js ~ Backbone.js PowerUp Wrapper
JavaScript
1
star
96

respublica

Complete Vieux Framework - "Res publica non dominetur"
1
star
97

perr

Perr UI Library using CoffeeScript
JavaScript
1
star
98

vim-script-template

Vim Script
1
star
99

dotfiles

Dotfiles for myself
Vim Script
1
star
100

eventstream.js

Pure functional EventStream monad implementation
JavaScript
1
star