diff --git a/HTML/commandview/commandview.js b/HTML/commandview/commandview.js index c05a247..553ea85 100644 --- a/HTML/commandview/commandview.js +++ b/HTML/commandview/commandview.js @@ -1,24 +1,9 @@ (function ($) { -$.fn.termkitCommandView = function (options) { - var $container = this; - - // Parse options. - var defaults = { - }; - options = $.extend({}, defaults, options); - - // Create controller for field. - var input = new termkit.commandView(); - $container.append(input.$element); -} - -/////////////////////////////////////////////////////////////////////////////// - /** * Controller for command view. */ -var cv = termkit.commandView = function (view) { +var cv = termkit.commandView = function (client, session) { var self = this; this.$element = this.$markup(); diff --git a/HTML/index.html b/HTML/index.html index a09953c..6cb8bc4 100644 --- a/HTML/index.html +++ b/HTML/index.html @@ -6,8 +6,11 @@ + + + @@ -30,11 +33,6 @@ } - diff --git a/HTML/termkit.css b/HTML/termkit.css index cbe48f8..c7a7373 100644 --- a/HTML/termkit.css +++ b/HTML/termkit.css @@ -67,14 +67,14 @@ body { .termkitCommandView .command > span.sigil { position: absolute; - left: 10px; + left: 15px; top: 15px; } .termkitCommandView .command .termkitProgressIndicator { position: absolute; - right: 0; - top: 0; + left: -2px; + top: -1px; } /************/ @@ -82,11 +82,15 @@ body { .termkitTokenField { border: 1px dotted #555; line-height: 22px; - padding: 10px 10px 10px 30px; + padding: 11px 10px 9px 35px; cursor: text; } +.termkitTokenField::after { + content: ' '; +} + .termkitTokenField.focused { outline: auto 5px -webkit-focus-ring-color; outline-offset: -2px; diff --git a/HTML/termkit.js b/HTML/termkit.js index 85f7932..853bf04 100644 --- a/HTML/termkit.js +++ b/HTML/termkit.js @@ -20,6 +20,17 @@ $(document).ready(function () { // mark(termkit.tokenField.token, 'tokenField.token'); // mark(termkit.tokenField.token.prototype, 'tokenField.token'); + + var client = new termkit.client(); + client.onConnect = function () { + client.invoke('session.open.shell', {}, function (data) { + var view = new termkit.commandView(client, data); + $('#terminal').append(view.$element); + }); + + }; + + }); })(jQuery); diff --git a/HTML/tokenfield/tokenfield.js b/HTML/tokenfield/tokenfield.js index aa2550f..9360cfe 100644 --- a/HTML/tokenfield/tokenfield.js +++ b/HTML/tokenfield/tokenfield.js @@ -1,20 +1,5 @@ (function ($) { -$.fn.termkitTokenField = function (options) { - var $container = this; - - // Parse options. - var defaults = { - }; - options = $.extend({}, defaults, options); - - // Create controller for field. - var input = new termkit.tokenField($container[0]); - $container.append(input.$element); -} - -/////////////////////////////////////////////////////////////////////////////// - /** * Controller for token-based field. */ @@ -107,6 +92,9 @@ tf.prototype = { this.updateElement(); $element.append(this.$element); }); + if (!this.tokenList.tokens.length) { + $element.append(new tf.tokenEmpty().$element); + } }, // Refresh the given token in response to input. diff --git a/termkit.txt b/termkit.txt index cea8c17..16a4800 100644 --- a/termkit.txt +++ b/termkit.txt @@ -1,27 +1,30 @@ TermKit - ++++ - Goal: next gen terminal / command application Addresses following problems: -1) Monospace character grid with ansi colors is not rich enough to display modern files / media / visualizations / metadata. +1) Monospace character grid with ansi colors is not rich enough to display modern files / media / visualizations / metadata. Cannot effectively handle large output, long/wide tables or direct interaction. 2) Piping binary or text streams between apps is bad for everyone: * Humans have to suffer syntax, cannot reflow/manipulate output in real-time * Computers have to suffer ambiguities -3) Synchronous input/output makes you wait -4) String-based command line requires arcane syntax -5) Commands with more than 1 screenful of output are unwieldy +3) Synchronous input/output makes you wait. SSH keystroke latency is frustrating. +4) String-based command line requires arcane syntax, results in mistakes, repeated attempts at escaping, etc. +5) Unix commands are "useless by default", and when asked, will only tell you raw data, not useful facts. e.g. "rwxr-xr-x" instead of "You can't edit this file." + ++++ - Programs / commands * Output processor for common cli tools * Custom implementation of ls and friends, with support for mimicking classic shell behaviour with a 2.0 twist Cool input scenarios: -* Command input is smart and adapts the semantics based on single character 'commands' which are abstractions of the old bash syntax. E.g. beginning and ending an encapsulated string is done with ". -* Inline consultation of man pages with autocompletion of command line arguments +* As you type, the command is visually tokenized and highlighted. tokens can display autocomplete suggestions, icons and indicators inline. +* Instead of quoting and escaping, keys like " and > just trigger the creation of special tokens which are visually different and represent e.g. a quoted string, an argument, a regular expression. to type the special characters literally, just press them twice. the 'command' is just the concatenation of these tokens, interpreted the same way bash interprets a string. +* Man pages are consulted inline with autocomplete options for arguments and (later) required arguments Cool output scenarios: * Listings of files, anywhere, show an icon with distinguished typography for filename vs meta. Quicklook integration on the icon. -* Output of a command is a series of figures. Figures never go beyond the size of the viewport +* Can complete several tasks at once asynchronously, show real-time progress for all of them together in e.g. a task-list widget. * Command output is interactive: has elements which can be focused, selected/unselected, opened, right clicked, dragged and dropped Good desktop citizen: @@ -29,15 +32,7 @@ Good desktop citizen: * Can drag files, snippets, JSON/CSV off the terminal * Tear-off tabs/windows - -terminal is broken: - -* long command output -> scroll up -* place cursor in middle of line inside quotes, hit enter -> gets executed. - -displays only facts, not things i want to know: -* displays owners, permission flags... doesn't say whether I am allowed to edit or not (use opacity / color) - ++++ - 0.1: UI prototype [X] simulated in safari/webkit.app @@ -49,13 +44,12 @@ displays only facts, not things i want to know: 0.2: App prototype [X] cocoa app [X] webkit in single window view (but built to scale to multiple tabs) - - custom JS termkit object w/ system IO - termkit.* -> JS - system.* -> native - system.files. -> modeled after node.js ? - - - real piped unix commands - - real directory listings + [X] design back-end protocol + [X] node JS back-end, running separately + [X] connect socket + [X] establish session + [ ] passive command implementation + [ ] JS module template, integrated both runtimes. + python bash anonymizer script to collect usage patterns from local geeks turns filenames.foooo.ext into random.random.ext @@ -71,12 +65,155 @@ displays only facts, not things i want to know: - OS X quicklook integration - OS X icon loading -0.4: Modularization / theming +0.4: Modularization - split off command processor rules / autocomplete handlers into separable blocks + - server-side hook system - add plug-in mechanism with drop-in functionality + +0.5: Theming + - polished UI - allow loading of command/theme stylesheets -0.5: + +Node JS daemon / 'NodeKit'. ++ Fast enough for server work, concurrency/scaling included ++ Advanced JavaScript ++ Cross-platform on unix ++ Process / io / everything integration ++ Self-contained binary, can be included in .app +- separate from UI / front-end +- no mac-specific APIs or low-level C access + + => back-end platform, runs locally, can run remotely, or perhaps tunnel its interaction over SSH somehow? + +WebKit/Cocoa front-end ++ Rich, stylable display + jQuery ++ Advanced JavaScript ++ Intimate OS X access, Obj-C, bridgeable with JS + +The split: +Front-end = display, formatting, interaction. Runs in an (enhanced) browser with a websocket to back-end. +Back-end: + +1) Local NodeKit: Start node daemon on startup, connect using direct websocket ws://localhost:2222. +2) Remote NodeKit SSH: Daemon is running, use ssh to set up tunnel between local rand port # and remote 2222. connect local websocket to tunnel. +3) Remote NodeKit WSS: Daemon is running, use WSS to connect directly, must authenticate? don't want to replicate OpenSSH, but rudimentary auth could be useful. + + +DNODE versus custom protocol. + +depends on needs of command-implementers. + + * execute method, preferably by dynamic name lookup (messaging) + * return values asynchronously to affect the UI: + - report progress (download, copy, grep, ...) + - append data to view (listing, query table) + - + * consistent command return status for indicator / logging / processing / triggers + ++++ Command architecture + +The webkit front end is intended to be a view first and foremost. It is an active view that maintains its own contents based on messages to and from the back-end. + +problem: if front-end is agnostic, then how to make commands smarter? + + > shell-OS interface is server-side + > server-side only executes processes/commands, routes streams and provides output. + > separeate data in/out from ui in/out. datastream vs viewstream + + data in/out: + content-type: unix/pipe + application/jsonstream + ... + + serverside has hook system / listener system for manipulating references. this lets e.g. SVN output revision control flags on files transparently. this would apply across the entire shell view automatically. + ++++ UI stream structure + + > shell-specific interaction rules are client-side. + > rich widget lib for display, extensible + > widgets are streamed to client like infograph-ML. objects are smartly typed and have callback commands defined for them. callbacks can be stateful or stateless. though stateful is only intended to be used for interactive commands. + + tableview / listcontainer -> generic, scales form simple list to tabled headers w/ simple syntax + object references for files and other things. are multi-typed and annotated on server-side. + + view out: + + view.task('task') + view.progress('task', 50, 0, 100) + view.table('table') + view.append('table', []) <- generic method, adapts to target type + + View Object Model: + simple reference by named IDs + arrays of objects + objects can have children + + { + id: 'table', + type: 'table', + children: [ + { type: 'row' } + ] + } + ++++ -- + +session.open.shell +session.open.mysql +session.open.git + +command.run + +direct embedding in websocket frame: + +stream := +[type, sequence, data] + -> not just a straight up dict because i don't want to hog the 'type' or 'sequence' keys in {data}. + +> +['session.open.mysql', 1, { + '' +}], + +< +['return', 1, { + sessionId: 1, + status: 'ok', +}], + +> +['session.close', 2, { + id: 1, +}], +< +['return', 2, { + status: 'ok', +}], +> +['command.run', 3, { // shell session + 'session': 1, + 'id': 1, + 'context': '/path', + 'commands': [ + ['svn', 'up'], + ], +}] +< +['return', 3, { + status: 'ok', +}] +< +['task', { + tasks: [] +}] + + +jsonStream.send('session.mysql', { + 'username': 'foobar', +}, function (msg) { + +}); references: @@ -85,3 +222,23 @@ textmate html output features http://blog.macromates.com/2005/html-output-for-commands/ bcat: browser cat tool + +protocol: + + +command output: +* has to be rich +* has to be easy to generate +* has to size to multiple layouts, including on the fly +* has to be interactive + +current widget model: +* base = viewcontroller +* instantiated OO +* $markup / $element pattern for jquery manipulation + +more ideas: +* autocorrection of mistyped commands +* unified progress indicator during command +* history access +* don't execute if invalid command diff --git a/todo.txt b/todo.txt index 86996b3..8b7430b 100644 --- a/todo.txt +++ b/todo.txt @@ -24,45 +24,49 @@ Prototype: . register multiregexp . execute command [?] rewrite $element / $markup pattern to create new $markup on demand when doing insert/remove from DOM + [?] unified viewcontroller class? -[ ] inline autocomplete +[X] inline autocomplete [X] panel overlayed on token [X] alignment [X] keyboard controls up/down - [ ] hit enter after autocomplete in empty token -> undefined + [X] hit enter after autocomplete in empty token -> undefined -[ ] command stream +[ ] command view [X] list of collapsible sections [X] host token field [X] context bar by command [ ] host output [ ] up/down to change focus [ ] anchored scrolling, auto-expand to fill view - [ ] add forking the stream - + [ ] add forking the view with tabs and hosted/nested sessions 2) Command/token autocomplete [X] token multi-regexp patterns + [.] triggers system, unify with token field triggers a bit? [X] autocomplete a string / command - [ ] autocomplete empties + [X] autocomplete empties [ ] autocomplete filesystem [ ] autocomplete dir / file distinction 3) Smart output with selectable things - [ ] Invoke a new process, capture output - [ ] define JSON streaming format - . content type (+ mime) - - streaming format: - * simple object - * stream of objects - * typed multipart - . top level stream of objects - - make test py script that streams in objects - - transform layer, JS template output into stream - - make a script for git (arguments, file/dir, ...) + [X] research FastCGI socket protocol + [X] add socket.io to client + [X] make socket connection to daemon + [X] set up client handling + [X] establish controller for stream + [X] invoke new session +4) NodeKit daemon + [X] socket.io listener + [X] keep state of sessions + [ ] allow path navigation + [ ] define datastream format + [ ] define viewstream format + [ ] make ls / cd commands + [ ] Invoke a new process, capture output + - make a script for git (arguments, file/dir, ...) bugs: [ ] backspacing around token edges -[ ] autocomplete in empty token -> hit enter -> invisible \ No newline at end of file +