2
0
Bläddra i källkod

Command and key binding refactoring

Nicolas Petton 12 år sedan
förälder
incheckning
e8d2d5ef7e

+ 32 - 41
js/Helios-Commands-Browser.deploy.js

@@ -289,56 +289,47 @@ smalltalk.HLMoveMethodToCommand.klass);
 
 
 smalltalk.addClass('HLMoveMethodToClassCommand', smalltalk.HLMoveMethodToCommand, [], 'Helios-Commands-Browser');
-
 smalltalk.addMethod(
-"_key",
+"_execute",
 smalltalk.method({
-selector: "key",
+selector: "execute",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return (67);
-}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
-messageSends: []}),
-smalltalk.HLMoveMethodToClassCommand.klass);
+var class_;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+class_=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(self)._input());
+$1=class_;
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._commandError_(_st("No class named: ").__comma(_st(self)._input()));
+} else {
+$1;
+};
+_st(_st(self)._model())._moveMethodToClass_(class_);
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{class_:class_},smalltalk.HLMoveMethodToClassCommand)})},
+messageSends: ["at:", "input", "current", "ifNil:", "commandError:", ",", "moveMethodToClass:", "model"]}),
+smalltalk.HLMoveMethodToClassCommand);
 
 smalltalk.addMethod(
-"_label",
+"_inputLabel",
 smalltalk.method({
-selector: "label",
+selector: "inputLabel",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return "to class";
-}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return "Move method to class:";
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLMoveMethodToClassCommand)})},
 messageSends: []}),
-smalltalk.HLMoveMethodToClassCommand.klass);
+smalltalk.HLMoveMethodToClassCommand);
 
-
-smalltalk.addClass('HLMethodMoveToClassSelectionCommand', smalltalk.HLMoveMethodToClassCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
-"_asBinding",
+"_isInputRequired",
 smalltalk.method({
-selector: "asBinding",
+selector: "isInputRequired",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st((smalltalk.HLBindingInput || HLBindingInput))._on_labelled_activeBlock_(_st(self)._key(),_st(self)._label(),_st(self)._activeBlock()))._callback_((function(ex){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._execute_(ex);
-}, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asBinding",{},smalltalk.HLMethodMoveToClassSelectionCommand)})},
-messageSends: ["callback:", "execute:", "on:labelled:activeBlock:", "key", "label", "activeBlock"]}),
-smalltalk.HLMethodMoveToClassSelectionCommand);
-
-smalltalk.addMethod(
-"_execute_",
-smalltalk.method({
-selector: "execute:",
-fn: function (aClass){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._model())._moveMethodToClass_(aClass);
-return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aClass:aClass},smalltalk.HLMethodMoveToClassSelectionCommand)})},
-messageSends: ["moveMethodToClass:", "model"]}),
-smalltalk.HLMethodMoveToClassSelectionCommand);
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLMoveMethodToClassCommand)})},
+messageSends: []}),
+smalltalk.HLMoveMethodToClassCommand);
 
 
 smalltalk.addMethod(
@@ -347,10 +338,10 @@ smalltalk.method({
 selector: "key",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return (13);
-}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMethodMoveToClassSelectionCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return (67);
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
 messageSends: []}),
-smalltalk.HLMethodMoveToClassSelectionCommand.klass);
+smalltalk.HLMoveMethodToClassCommand.klass);
 
 smalltalk.addMethod(
 "_label",
@@ -358,10 +349,10 @@ smalltalk.method({
 selector: "label",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return "select a class";
-}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMethodMoveToClassSelectionCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return "to class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
 messageSends: []}),
-smalltalk.HLMethodMoveToClassSelectionCommand.klass);
+smalltalk.HLMoveMethodToClassCommand.klass);
 
 
 smalltalk.addClass('HLMoveMethodToProtocolCommand', smalltalk.HLMoveMethodToCommand, [], 'Helios-Commands-Browser');

+ 40 - 54
js/Helios-Commands-Browser.js

@@ -404,76 +404,62 @@ smalltalk.HLMoveMethodToCommand.klass);
 
 
 smalltalk.addClass('HLMoveMethodToClassCommand', smalltalk.HLMoveMethodToCommand, [], 'Helios-Commands-Browser');
-
 smalltalk.addMethod(
-"_key",
+"_execute",
 smalltalk.method({
-selector: "key",
-category: 'accessing',
+selector: "execute",
+category: 'executing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return (67);
-}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
+var class_;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+class_=_st(_st((smalltalk.Smalltalk || Smalltalk))._current())._at_(_st(self)._input());
+$1=class_;
+if(($receiver = $1) == nil || $receiver == undefined){
+_st(self)._commandError_(_st("No class named: ").__comma(_st(self)._input()));
+} else {
+$1;
+};
+_st(_st(self)._model())._moveMethodToClass_(class_);
+return self}, function($ctx1) {$ctx1.fill(self,"execute",{class_:class_},smalltalk.HLMoveMethodToClassCommand)})},
 args: [],
-source: "key\x0a\x09^ 67",
-messageSends: [],
-referencedClasses: []
+source: "execute\x0a\x09| class |\x0a\x09class := Smalltalk current at: self input.\x0a\x09class ifNil: [ self commandError: 'No class named: ', self input ].\x0a\x09\x0a\x09self model moveMethodToClass: class",
+messageSends: ["at:", "input", "current", "ifNil:", "commandError:", ",", "moveMethodToClass:", "model"],
+referencedClasses: ["Smalltalk"]
 }),
-smalltalk.HLMoveMethodToClassCommand.klass);
+smalltalk.HLMoveMethodToClassCommand);
 
 smalltalk.addMethod(
-"_label",
+"_inputLabel",
 smalltalk.method({
-selector: "label",
+selector: "inputLabel",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return "to class";
-}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return "Move method to class:";
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLMoveMethodToClassCommand)})},
 args: [],
-source: "label\x09\x0a\x09^ 'to class'",
+source: "inputLabel\x0a\x09^ 'Move method to class:'",
 messageSends: [],
 referencedClasses: []
 }),
-smalltalk.HLMoveMethodToClassCommand.klass);
-
+smalltalk.HLMoveMethodToClassCommand);
 
-smalltalk.addClass('HLMethodMoveToClassSelectionCommand', smalltalk.HLMoveMethodToClassCommand, [], 'Helios-Commands-Browser');
 smalltalk.addMethod(
-"_asBinding",
+"_isInputRequired",
 smalltalk.method({
-selector: "asBinding",
-category: 'converting',
+selector: "isInputRequired",
+category: 'testing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st((smalltalk.HLBindingInput || HLBindingInput))._on_labelled_activeBlock_(_st(self)._key(),_st(self)._label(),_st(self)._activeBlock()))._callback_((function(ex){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._execute_(ex);
-}, function($ctx2) {$ctx2.fillBlock({ex:ex},$ctx1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asBinding",{},smalltalk.HLMethodMoveToClassSelectionCommand)})},
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLMoveMethodToClassCommand)})},
 args: [],
-source: "asBinding\x0a\x09^ (HLBindingInput on: self key labelled: self label activeBlock: self activeBlock)\x0a    \x09callback: [:ex | self execute: ex ]",
-messageSends: ["callback:", "execute:", "on:labelled:activeBlock:", "key", "label", "activeBlock"],
-referencedClasses: ["HLBindingInput"]
-}),
-smalltalk.HLMethodMoveToClassSelectionCommand);
-
-smalltalk.addMethod(
-"_execute_",
-smalltalk.method({
-selector: "execute:",
-category: 'actions',
-fn: function (aClass){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._model())._moveMethodToClass_(aClass);
-return self}, function($ctx1) {$ctx1.fill(self,"execute:",{aClass:aClass},smalltalk.HLMethodMoveToClassSelectionCommand)})},
-args: ["aClass"],
-source: "execute: aClass\x0a\x09self model moveMethodToClass: aClass",
-messageSends: ["moveMethodToClass:", "model"],
+source: "isInputRequired\x0a\x09^ true",
+messageSends: [],
 referencedClasses: []
 }),
-smalltalk.HLMethodMoveToClassSelectionCommand);
+smalltalk.HLMoveMethodToClassCommand);
 
 
 smalltalk.addMethod(
@@ -483,14 +469,14 @@ selector: "key",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return (13);
-}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMethodMoveToClassSelectionCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return (67);
+}, function($ctx1) {$ctx1.fill(self,"key",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
 args: [],
-source: "key\x0a\x09^ 13 \x22enter\x22",
+source: "key\x0a\x09^ 67",
 messageSends: [],
 referencedClasses: []
 }),
-smalltalk.HLMethodMoveToClassSelectionCommand.klass);
+smalltalk.HLMoveMethodToClassCommand.klass);
 
 smalltalk.addMethod(
 "_label",
@@ -499,14 +485,14 @@ selector: "label",
 category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return "select a class";
-}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMethodMoveToClassSelectionCommand.klass)})},
+return smalltalk.withContext(function($ctx1) { 
return "to class";
+}, function($ctx1) {$ctx1.fill(self,"label",{},smalltalk.HLMoveMethodToClassCommand.klass)})},
 args: [],
-source: "label\x0a\x09^ 'select a class'",
+source: "label\x09\x0a\x09^ 'to class'",
 messageSends: [],
 referencedClasses: []
 }),
-smalltalk.HLMethodMoveToClassSelectionCommand.klass);
+smalltalk.HLMoveMethodToClassCommand.klass);
 
 
 smalltalk.addClass('HLMoveMethodToProtocolCommand', smalltalk.HLMoveMethodToCommand, [], 'Helios-Commands-Browser');

+ 105 - 63
js/Helios-Commands-Core.deploy.js

@@ -1,33 +1,19 @@
 smalltalk.addPackage('Helios-Commands-Core');
-smalltalk.addClass('HLCommand', smalltalk.Object, [], 'Helios-Commands-Core');
-smalltalk.addMethod(
-"_activeBlock",
-smalltalk.method({
-selector: "activeBlock",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=(function(){
-return smalltalk.withContext(function($ctx2) {
return true;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"activeBlock",{},smalltalk.HLCommand)})},
-messageSends: []}),
-smalltalk.HLCommand);
-
+smalltalk.addClass('HLCommand', smalltalk.Object, ['input'], 'Helios-Commands-Core');
 smalltalk.addMethod(
 "_asActionBinding",
 smalltalk.method({
 selector: "asActionBinding",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_activeBlock_(_st(self)._key(),_st(self)._label(),_st(self)._activeBlock()))._callback_((function(){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._execute();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_(_st(self)._key(),_st(self)._label());
+_st($2)._command_(self);
+$3=_st($2)._yourself();
+$1=$3;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"asActionBinding",{},smalltalk.HLCommand)})},
-messageSends: ["callback:", "execute", "on:labelled:activeBlock:", "key", "label", "activeBlock"]}),
+messageSends: ["command:", "on:labelled:", "key", "label", "yourself"]}),
 smalltalk.HLCommand);
 
 smalltalk.addMethod(
@@ -61,6 +47,17 @@ return $1;
 messageSends: ["on:labelled:", "key", "label"]}),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_commandError_",
+smalltalk.method({
+selector: "commandError:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._error_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"commandError:",{aString:aString},smalltalk.HLCommand)})},
+messageSends: ["error:"]}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_documentation",
 smalltalk.method({
@@ -84,6 +81,68 @@ return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$
 messageSends: []}),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_input",
+smalltalk.method({
+selector: "input",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@input"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLCommand)})},
+messageSends: []}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_input_",
+smalltalk.method({
+selector: "input:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+self["@input"]=aString;
+$1=self["@input"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input:",{aString:aString},smalltalk.HLCommand)})},
+messageSends: []}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_inputCompletion",
+smalltalk.method({
+selector: "inputCompletion",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return [];
+}, function($ctx1) {$ctx1.fill(self,"inputCompletion",{},smalltalk.HLCommand)})},
+messageSends: []}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_inputLabel",
+smalltalk.method({
+selector: "inputLabel",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._label();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLCommand)})},
+messageSends: ["label"]}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_isActive",
+smalltalk.method({
+selector: "isActive",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLCommand)})},
+messageSends: []}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_isBindingGroup",
 smalltalk.method({
@@ -97,6 +156,17 @@ return $1;
 messageSends: ["not", "includesKey:", "methodDictionary", "class"]}),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_isInputRequired",
+smalltalk.method({
+selector: "isInputRequired",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return false;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLCommand)})},
+messageSends: []}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_key",
 smalltalk.method({
@@ -137,37 +207,6 @@ messageSends: ["add:", "asBinding"]}),
 smalltalk.HLCommand);
 
 
-smalltalk.addMethod(
-"_asBindingOn_",
-smalltalk.method({
-selector: "asBindingOn:",
-fn: function (aBinding){
-var self=this;
-var instance;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-instance=_st(_st(self)._new())._asBinding();
-_st(aBinding)._add_(instance);
-$1=instance;
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asBindingOn:",{aBinding:aBinding,instance:instance},smalltalk.HLCommand.klass)})},
-messageSends: ["asBinding", "new", "add:"]}),
-smalltalk.HLCommand.klass);
-
-smalltalk.addMethod(
-"_concreteSubclasses",
-smalltalk.method({
-selector: "concreteSubclasses",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._subclasses())._select_((function(each){
-return smalltalk.withContext(function($ctx2) {
return _st(each)._isConcrete();
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"concreteSubclasses",{},smalltalk.HLCommand.klass)})},
-messageSends: ["select:", "isConcrete", "subclasses"]}),
-smalltalk.HLCommand.klass);
-
 smalltalk.addMethod(
 "_documentation",
 smalltalk.method({
@@ -224,7 +263,7 @@ var newBinding;
 return smalltalk.withContext(function($ctx1) { 
var $1;
 $1=_st(self)._isConcrete();
 if(smalltalk.assert($1)){
-newBinding=_st(self)._asBindingOn_(aBinding);
+newBinding=_st(self)._registerOn_(aBinding);
 newBinding;
 } else {
 newBinding=aBinding;
@@ -234,7 +273,7 @@ _st(_st(self)._subclasses())._do_((function(each){
 return smalltalk.withContext(function($ctx2) {
return _st(each)._registerConcreteClassesOn_(newBinding);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:",{aBinding:aBinding,newBinding:newBinding},smalltalk.HLCommand.klass)})},
-messageSends: ["ifTrue:ifFalse:", "asBindingOn:", "isConcrete", "do:", "registerConcreteClassesOn:", "subclasses"]}),
+messageSends: ["ifTrue:ifFalse:", "registerOn:", "isConcrete", "do:", "registerConcreteClassesOn:", "subclasses"]}),
 smalltalk.HLCommand.klass);
 
 smalltalk.addMethod(
@@ -332,18 +371,21 @@ smalltalk.method({
 selector: "registerConcreteClassesOn:for:",
 fn: function (aBinding,aModel){
 var self=this;
+var newBinding;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(_st(self)._concreteSubclasses())._do_((function(each){
-var binding;
-return smalltalk.withContext(function($ctx2) {
binding=_st(each)._registerOn_for_(aBinding,aModel);
-binding;
-$1=_st(binding)._isBindingGroup();
+$1=_st(self)._isConcrete();
 if(smalltalk.assert($1)){
-return _st(each)._registerConcreteClassesOn_for_(binding,aModel);
+newBinding=_st(self)._registerOn_for_(aBinding,aModel);
+newBinding;
+} else {
+newBinding=aBinding;
+newBinding;
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each,binding:binding},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:for:",{aBinding:aBinding,aModel:aModel},smalltalk.HLModelCommand.klass)})},
-messageSends: ["do:", "registerOn:for:", "ifTrue:", "registerConcreteClassesOn:for:", "isBindingGroup", "concreteSubclasses"]}),
+_st(_st(self)._subclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each)._registerConcreteClassesOn_for_(newBinding,aModel);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:for:",{aBinding:aBinding,aModel:aModel,newBinding:newBinding},smalltalk.HLModelCommand.klass)})},
+messageSends: ["ifTrue:ifFalse:", "registerOn:for:", "isConcrete", "do:", "registerConcreteClassesOn:for:", "subclasses"]}),
 smalltalk.HLModelCommand.klass);
 
 smalltalk.addMethod(

+ 143 - 81
js/Helios-Commands-Core.js

@@ -1,25 +1,5 @@
 smalltalk.addPackage('Helios-Commands-Core');
-smalltalk.addClass('HLCommand', smalltalk.Object, [], 'Helios-Commands-Core');
-smalltalk.addMethod(
-"_activeBlock",
-smalltalk.method({
-selector: "activeBlock",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=(function(){
-return smalltalk.withContext(function($ctx2) {
return true;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"activeBlock",{},smalltalk.HLCommand)})},
-args: [],
-source: "activeBlock\x0a\x09^ [ true ]",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLCommand);
-
+smalltalk.addClass('HLCommand', smalltalk.Object, ['input'], 'Helios-Commands-Core');
 smalltalk.addMethod(
 "_asActionBinding",
 smalltalk.method({
@@ -27,15 +7,16 @@ selector: "asActionBinding",
 category: 'converting',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_activeBlock_(_st(self)._key(),_st(self)._label(),_st(self)._activeBlock()))._callback_((function(){
-return smalltalk.withContext(function($ctx2) {
return _st(self)._execute();
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
+$2=_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_(_st(self)._key(),_st(self)._label());
+_st($2)._command_(self);
+$3=_st($2)._yourself();
+$1=$3;
 return $1;
 }, function($ctx1) {$ctx1.fill(self,"asActionBinding",{},smalltalk.HLCommand)})},
 args: [],
-source: "asActionBinding\x0a\x09^ (HLBindingAction on: self key labelled: self label activeBlock: self activeBlock)\x0a    \x09callback: [ self execute ]",
-messageSends: ["callback:", "execute", "on:labelled:activeBlock:", "key", "label", "activeBlock"],
+source: "asActionBinding\x0a\x09^ (HLBindingAction on: self key labelled: self label)\x0a    \x09command: self;\x0a\x09\x09yourself",
+messageSends: ["command:", "on:labelled:", "key", "label", "yourself"],
 referencedClasses: ["HLBindingAction"]
 }),
 smalltalk.HLCommand);
@@ -81,6 +62,22 @@ referencedClasses: ["HLBindingGroup"]
 }),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_commandError_",
+smalltalk.method({
+selector: "commandError:",
+category: 'error handling',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._error_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"commandError:",{aString:aString},smalltalk.HLCommand)})},
+args: ["aString"],
+source: "commandError: aString\x0a\x09self error: aString",
+messageSends: ["error:"],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_documentation",
 smalltalk.method({
@@ -114,6 +111,93 @@ referencedClasses: []
 }),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_input",
+smalltalk.method({
+selector: "input",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=self["@input"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLCommand)})},
+args: [],
+source: "input\x0a\x09^ input",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_input_",
+smalltalk.method({
+selector: "input:",
+category: 'accessing',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+self["@input"]=aString;
+$1=self["@input"];
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input:",{aString:aString},smalltalk.HLCommand)})},
+args: ["aString"],
+source: "input: aString\x0a\x09^ input := aString",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_inputCompletion",
+smalltalk.method({
+selector: "inputCompletion",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return [];
+}, function($ctx1) {$ctx1.fill(self,"inputCompletion",{},smalltalk.HLCommand)})},
+args: [],
+source: "inputCompletion\x0a\x09^ #()",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_inputLabel",
+smalltalk.method({
+selector: "inputLabel",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(self)._label();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"inputLabel",{},smalltalk.HLCommand)})},
+args: [],
+source: "inputLabel\x0a\x09^ self label",
+messageSends: ["label"],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
+smalltalk.addMethod(
+"_isActive",
+smalltalk.method({
+selector: "isActive",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLCommand)})},
+args: [],
+source: "isActive\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_isBindingGroup",
 smalltalk.method({
@@ -132,6 +216,22 @@ referencedClasses: []
 }),
 smalltalk.HLCommand);
 
+smalltalk.addMethod(
+"_isInputRequired",
+smalltalk.method({
+selector: "isInputRequired",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return false;
+}, function($ctx1) {$ctx1.fill(self,"isInputRequired",{},smalltalk.HLCommand)})},
+args: [],
+source: "isInputRequired\x0a\x09^ false",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLCommand);
+
 smalltalk.addMethod(
 "_key",
 smalltalk.method({
@@ -187,47 +287,6 @@ referencedClasses: []
 smalltalk.HLCommand);
 
 
-smalltalk.addMethod(
-"_asBindingOn_",
-smalltalk.method({
-selector: "asBindingOn:",
-category: 'converting',
-fn: function (aBinding){
-var self=this;
-var instance;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-instance=_st(_st(self)._new())._asBinding();
-_st(aBinding)._add_(instance);
-$1=instance;
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"asBindingOn:",{aBinding:aBinding,instance:instance},smalltalk.HLCommand.klass)})},
-args: ["aBinding"],
-source: "asBindingOn: aBinding\x0a\x09| instance |\x0a\x09\x0a\x09instance := self new asBinding.\x0a\x09aBinding add: instance.\x0a\x09^ instance",
-messageSends: ["asBinding", "new", "add:"],
-referencedClasses: []
-}),
-smalltalk.HLCommand.klass);
-
-smalltalk.addMethod(
-"_concreteSubclasses",
-smalltalk.method({
-selector: "concreteSubclasses",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._subclasses())._select_((function(each){
-return smalltalk.withContext(function($ctx2) {
return _st(each)._isConcrete();
-}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"concreteSubclasses",{},smalltalk.HLCommand.klass)})},
-args: [],
-source: "concreteSubclasses\x0a\x09^ self subclasses select: [ :each |\x0a\x09\x09each isConcrete ]",
-messageSends: ["select:", "isConcrete", "subclasses"],
-referencedClasses: []
-}),
-smalltalk.HLCommand.klass);
-
 smalltalk.addMethod(
 "_documentation",
 smalltalk.method({
@@ -305,7 +364,7 @@ var newBinding;
 return smalltalk.withContext(function($ctx1) { 
var $1;
 $1=_st(self)._isConcrete();
 if(smalltalk.assert($1)){
-newBinding=_st(self)._asBindingOn_(aBinding);
+newBinding=_st(self)._registerOn_(aBinding);
 newBinding;
 } else {
 newBinding=aBinding;
@@ -316,8 +375,8 @@ return smalltalk.withContext(function($ctx2) {
return _st(each)._registerConcret
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:",{aBinding:aBinding,newBinding:newBinding},smalltalk.HLCommand.klass)})},
 args: ["aBinding"],
-source: "registerConcreteClassesOn: aBinding\x0a\x09| newBinding |\x0a\x09\x0a\x09self isConcrete\x0a\x09\x09ifTrue: [ newBinding := self asBindingOn: aBinding ]\x0a\x09\x09ifFalse: [ newBinding := aBinding ].\x0a\x09\x09\x0a\x09self subclasses do: [ :each | each registerConcreteClassesOn: newBinding ]",
-messageSends: ["ifTrue:ifFalse:", "asBindingOn:", "isConcrete", "do:", "registerConcreteClassesOn:", "subclasses"],
+source: "registerConcreteClassesOn: aBinding\x0a\x09| newBinding |\x0a\x09\x0a\x09self isConcrete\x0a\x09\x09ifTrue: [ newBinding := self registerOn: aBinding ]\x0a\x09\x09ifFalse: [ newBinding := aBinding ].\x0a\x09\x09\x0a\x09self subclasses do: [ :each | each registerConcreteClassesOn: newBinding ]",
+messageSends: ["ifTrue:ifFalse:", "registerOn:", "isConcrete", "do:", "registerConcreteClassesOn:", "subclasses"],
 referencedClasses: []
 }),
 smalltalk.HLCommand.klass);
@@ -453,20 +512,23 @@ selector: "registerConcreteClassesOn:for:",
 category: 'registration',
 fn: function (aBinding,aModel){
 var self=this;
+var newBinding;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-_st(_st(self)._concreteSubclasses())._do_((function(each){
-var binding;
-return smalltalk.withContext(function($ctx2) {
binding=_st(each)._registerOn_for_(aBinding,aModel);
-binding;
-$1=_st(binding)._isBindingGroup();
+$1=_st(self)._isConcrete();
 if(smalltalk.assert($1)){
-return _st(each)._registerConcreteClassesOn_for_(binding,aModel);
+newBinding=_st(self)._registerOn_for_(aBinding,aModel);
+newBinding;
+} else {
+newBinding=aBinding;
+newBinding;
 };
-}, function($ctx2) {$ctx2.fillBlock({each:each,binding:binding},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:for:",{aBinding:aBinding,aModel:aModel},smalltalk.HLModelCommand.klass)})},
+_st(_st(self)._subclasses())._do_((function(each){
+return smalltalk.withContext(function($ctx2) {
return _st(each)._registerConcreteClassesOn_for_(newBinding,aModel);
+}, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
+return self}, function($ctx1) {$ctx1.fill(self,"registerConcreteClassesOn:for:",{aBinding:aBinding,aModel:aModel,newBinding:newBinding},smalltalk.HLModelCommand.klass)})},
 args: ["aBinding", "aModel"],
-source: "registerConcreteClassesOn: aBinding for: aModel\x0a\x09self concreteSubclasses do: [ :each | | binding |\x0a\x09\x09binding := each registerOn: aBinding for: aModel.\x0a\x09\x09binding isBindingGroup ifTrue: [\x0a\x09\x09\x09each registerConcreteClassesOn: binding for: aModel ] ]",
-messageSends: ["do:", "registerOn:for:", "ifTrue:", "registerConcreteClassesOn:for:", "isBindingGroup", "concreteSubclasses"],
+source: "registerConcreteClassesOn: aBinding for: aModel\x0a\x09| newBinding |\x0a\x09\x0a\x09self isConcrete\x0a\x09\x09ifTrue: [ newBinding := self registerOn: aBinding for: aModel ]\x0a\x09\x09ifFalse: [ newBinding := aBinding ].\x0a\x09\x09\x0a\x09self subclasses do: [ :each |\x0a\x09\x09each registerConcreteClassesOn: newBinding for: aModel ]",
+messageSends: ["ifTrue:ifFalse:", "registerOn:for:", "isConcrete", "do:", "registerConcreteClassesOn:for:", "subclasses"],
 referencedClasses: []
 }),
 smalltalk.HLModelCommand.klass);

+ 209 - 229
js/Helios-KeyBindings.deploy.js

@@ -6,9 +6,29 @@ smalltalk.method({
 selector: "applyOn:",
 fn: function (aKeyBinder){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._subclassResponsibility();
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder}, smalltalk.HLBinding)})},
-messageSends: ["subclassResponsibility"]}),
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBinding)})},
+messageSends: []}),
+smalltalk.HLBinding);
+
+smalltalk.addMethod(
+"_applyOn_then_",
+smalltalk.method({
+selector: "applyOn:then:",
+fn: function (aKeyBinder,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"applyOn:then:",{aKeyBinder:aKeyBinder,aBlock:aBlock},smalltalk.HLBinding)})},
+messageSends: []}),
+smalltalk.HLBinding);
+
+smalltalk.addMethod(
+"_atKey_",
+smalltalk.method({
+selector: "atKey:",
+fn: function (aKey){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return nil;
+}, function($ctx1) {$ctx1.fill(self,"atKey:",{aKey:aKey},smalltalk.HLBinding)})},
+messageSends: []}),
 smalltalk.HLBinding);
 
 smalltalk.addMethod(
@@ -38,24 +58,13 @@ messageSends: ["subclassResponsibility"]}),
 smalltalk.HLBinding);
 
 smalltalk.addMethod(
-"_isBindingAction",
-smalltalk.method({
-selector: "isBindingAction",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
return false;
-}, function($ctx1) {$ctx1.fill(self,"isBindingAction",{}, smalltalk.HLBinding)})},
-messageSends: []}),
-smalltalk.HLBinding);
-
-smalltalk.addMethod(
-"_isBindingGroup",
+"_isFinal",
 smalltalk.method({
-selector: "isBindingGroup",
+selector: "isFinal",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
return false;
-}, function($ctx1) {$ctx1.fill(self,"isBindingGroup",{}, smalltalk.HLBinding)})},
+}, function($ctx1) {$ctx1.fill(self,"isFinal",{},smalltalk.HLBinding)})},
 messageSends: []}),
 smalltalk.HLBinding);
 
@@ -108,10 +117,10 @@ messageSends: []}),
 smalltalk.HLBinding);
 
 smalltalk.addMethod(
-"_renderBindingOn_actionOn_",
+"_renderActionFor_html_",
 smalltalk.method({
-selector: "renderBindingOn:actionOn:",
-fn: function (html,aBinder){
+selector: "renderActionFor:html:",
+fn: function (aBinder,html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$6,$2;
 $1=_st(html)._span();
@@ -129,7 +138,7 @@ return smalltalk.withContext(function($ctx3) {
return _st(aBinder)._applyBinding
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
 return $6;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"renderBindingOn:actionOn:",{html:html,aBinder:aBinder},smalltalk.HLBinding)})},
+return self}, function($ctx1) {$ctx1.fill(self,"renderActionFor:html:",{aBinder:aBinder,html:html},smalltalk.HLBinding)})},
 messageSends: ["class:", "span", "with:", "asLowercase", "shortcut", "a", "displayLabel", "onClick:", "applyBinding:"]}),
 smalltalk.HLBinding);
 
@@ -175,175 +184,95 @@ messageSends: ["key:", "new", "label:", "yourself"]}),
 smalltalk.HLBinding.klass);
 
 
-smalltalk.addClass('HLBindingAction', smalltalk.HLBinding, ['callback', 'activeBlock'], 'Helios-KeyBindings');
-smalltalk.addMethod(
-"_activeBlock",
-smalltalk.method({
-selector: "activeBlock",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$1;
-$2=self["@activeBlock"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@activeBlock"]=(function(){
-return smalltalk.withContext(function($ctx2) {
return true;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=self["@activeBlock"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"activeBlock",{},smalltalk.HLBindingAction)})},
-messageSends: ["ifNil:"]}),
-smalltalk.HLBindingAction);
-
-smalltalk.addMethod(
-"_activeBlock_",
-smalltalk.method({
-selector: "activeBlock:",
-fn: function (aBlock){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@activeBlock"]=aBlock;
-return self}, function($ctx1) {$ctx1.fill(self,"activeBlock:",{aBlock:aBlock},smalltalk.HLBindingAction)})},
-messageSends: []}),
-smalltalk.HLBindingAction);
-
+smalltalk.addClass('HLBindingAction', smalltalk.HLBinding, ['command'], 'Helios-KeyBindings');
 smalltalk.addMethod(
 "_applyOn_",
 smalltalk.method({
 selector: "applyOn:",
 fn: function (aKeyBinder){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._command())._isInputRequired();
+if(smalltalk.assert($1)){
+_st(aKeyBinder)._selectBinding_(_st(self)._inputBinding());
+} else {
+_st(_st(self)._command())._execute();
 };
-_st(aKeyBinder)._applyBindingAction_(self);
 return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingAction)})},
-messageSends: ["ifFalse:", "isActive", "applyBindingAction:"]}),
+messageSends: ["ifTrue:ifFalse:", "selectBinding:", "inputBinding", "execute", "command", "isInputRequired"]}),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_callback",
+"_command",
 smalltalk.method({
-selector: "callback",
+selector: "command",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@callback"];
+$1=self["@command"];
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"callback",{}, smalltalk.HLBindingAction)})},
+}, function($ctx1) {$ctx1.fill(self,"command",{},smalltalk.HLBindingAction)})},
 messageSends: []}),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_callback_",
+"_command_",
 smalltalk.method({
-selector: "callback:",
-fn: function (aBlock){
+selector: "command:",
+fn: function (aCommand){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@callback"]=aBlock;
-return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock}, smalltalk.HLBindingAction)})},
+return smalltalk.withContext(function($ctx1) { 
self["@command"]=aCommand;
+return self}, function($ctx1) {$ctx1.fill(self,"command:",{aCommand:aCommand},smalltalk.HLBindingAction)})},
 messageSends: []}),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_isActive",
+"_inputBinding",
 smalltalk.method({
-selector: "isActive",
+selector: "inputBinding",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._activeBlock())._value();
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$5,$1;
+$2=_st((smalltalk.HLBindingInput || HLBindingInput))._new();
+_st($2)._label_(_st(_st(self)._command())._inputLabel());
+_st($2)._callback_((function(val){
+return smalltalk.withContext(function($ctx2) {
$3=_st(self)._command();
+_st($3)._input_(val);
+$4=_st($3)._execute();
+return $4;
+}, function($ctx2) {$ctx2.fillBlock({val:val},$ctx1)})}));
+$5=_st($2)._yourself();
+$1=$5;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingAction)})},
-messageSends: ["value", "activeBlock"]}),
+}, function($ctx1) {$ctx1.fill(self,"inputBinding",{},smalltalk.HLBindingAction)})},
+messageSends: ["label:", "inputLabel", "command", "new", "callback:", "input:", "execute", "yourself"]}),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_isBindingAction",
+"_isActive",
 smalltalk.method({
-selector: "isBindingAction",
+selector: "isActive",
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
-}, function($ctx1) {$ctx1.fill(self,"isBindingAction",{}, smalltalk.HLBindingAction)})},
-messageSends: []}),
-smalltalk.HLBindingAction);
-
-
-smalltalk.addMethod(
-"_on_labelled_activeBlock_",
-smalltalk.method({
-selector: "on:labelled:activeBlock:",
-fn: function (anInteger,aString,aBlock){
-var self=this;
-var instance;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
-instance=smalltalk.HLBinding.klass.fn.prototype._on_labelled_.apply(_st(self), [anInteger,aString]);
-$2=instance;
-_st($2)._activeBlock_(aBlock);
-$3=_st($2)._yourself();
-$1=$3;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._command())._isActive();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"on:labelled:activeBlock:",{anInteger:anInteger,aString:aString,aBlock:aBlock,instance:instance},smalltalk.HLBindingAction.klass)})},
-messageSends: ["on:labelled:", "activeBlock:", "yourself"]}),
-smalltalk.HLBindingAction.klass);
-
-
-smalltalk.addClass('HLBindingInput', smalltalk.HLBindingAction, ['input'], 'Helios-KeyBindings');
-smalltalk.addMethod(
-"_applyOn_",
-smalltalk.method({
-selector: "applyOn:",
-fn: function (aBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-_st(aBinder)._applyBindingInput_with_(self,_st(self)._input());
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aBinder:aBinder},smalltalk.HLBindingInput)})},
-messageSends: ["ifFalse:", "isActive", "applyBindingInput:with:", "input"]}),
-smalltalk.HLBindingInput);
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingAction)})},
+messageSends: ["isActive", "command"]}),
+smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_input",
+"_isFinal",
 smalltalk.method({
-selector: "input",
+selector: "isFinal",
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self["@input"])._asJQuery())._val();
+$1=_st(_st(_st(self)._command())._isInputRequired())._not();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLBindingInput)})},
-messageSends: ["val", "asJQuery"]}),
-smalltalk.HLBindingInput);
-
-smalltalk.addMethod(
-"_renderBindingOn_actionOn_",
-smalltalk.method({
-selector: "renderBindingOn:actionOn:",
-fn: function (html,aBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
-$1=_st(html)._span();
-_st($1)._class_("command");
-$2=_st($1)._with_((function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(html)._input();
-_st($3)._class_("search-query");
-$4=_st($3)._placeholder_(_st(self)._displayLabel());
-self["@input"]=$4;
-return self["@input"];
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-_st(_st(self["@input"])._asJQuery())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"renderBindingOn:actionOn:",{html:html,aBinder:aBinder},smalltalk.HLBindingInput)})},
-messageSends: ["class:", "span", "with:", "input", "placeholder:", "displayLabel", "focus", "asJQuery"]}),
-smalltalk.HLBindingInput);
+}, function($ctx1) {$ctx1.fill(self,"isFinal",{},smalltalk.HLBindingAction)})},
+messageSends: ["not", "isInputRequired", "command"]}),
+smalltalk.HLBindingAction);
 
 
 
@@ -391,21 +320,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"addActionKey:labelled:callback:"
 messageSends: ["add:", "callback:", "on:labelled:", "yourself"]}),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_addActionKey_labelled_command_",
-smalltalk.method({
-selector: "addActionKey:labelled:command:",
-fn: function (anInteger,aString,aCommand){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_(anInteger,aString);
-_st($1)._command_(aCommand);
-$2=_st($1)._yourself();
-_st(self)._add_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"addActionKey:labelled:command:",{anInteger:anInteger,aString:aString,aCommand:aCommand}, smalltalk.HLBindingGroup)})},
-messageSends: ["add:", "command:", "on:labelled:", "yourself"]}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_addGroupKey_labelled_",
 smalltalk.method({
@@ -417,23 +331,6 @@ return self}, function($ctx1) {$ctx1.fill(self,"addGroupKey:labelled:",{anIntege
 messageSends: ["add:", "on:labelled:"]}),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_applyOn_",
-smalltalk.method({
-selector: "applyOn:",
-fn: function (aKeyBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-_st(aKeyBinder)._applyBindingGroup_(self);
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingGroup)})},
-messageSends: ["ifFalse:", "isActive", "applyBindingGroup:"]}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_at_",
 smalltalk.method({
@@ -534,17 +431,6 @@ return $1;
 messageSends: ["notEmpty", "activeBindings"]}),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_isBindingGroup",
-smalltalk.method({
-selector: "isBindingGroup",
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
-}, function($ctx1) {$ctx1.fill(self,"isBindingGroup",{}, smalltalk.HLBindingGroup)})},
-messageSends: []}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_renderOn_html_",
 smalltalk.method({
@@ -562,6 +448,113 @@ smalltalk.HLBindingGroup);
 
 
 
+smalltalk.addClass('HLBindingInput', smalltalk.HLBinding, ['input', 'callback'], 'Helios-KeyBindings');
+smalltalk.addMethod(
+"_applyOn_",
+smalltalk.method({
+selector: "applyOn:",
+fn: function (aKeyBinder){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._evaluate_(_st(self)._input());
+return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingInput)})},
+messageSends: ["evaluate:", "input"]}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_callback",
+smalltalk.method({
+selector: "callback",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@callback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@callback"]=(function(value){
+return smalltalk.withContext(function($ctx2) {
}, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})});
+$1=self["@callback"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"callback",{},smalltalk.HLInputBinding)})},
+messageSends: ["ifNil:"]}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_callback_",
+smalltalk.method({
+selector: "callback:",
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@callback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock},smalltalk.HLInputBinding)})},
+messageSends: []}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_evaluate_",
+smalltalk.method({
+selector: "evaluate:",
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._callback())._value_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"evaluate:",{aString:aString},smalltalk.HLBindingInput)})},
+messageSends: ["value:", "callback"]}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_input",
+smalltalk.method({
+selector: "input",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self["@input"])._asJQuery())._val();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLBindingInput)})},
+messageSends: ["val", "asJQuery"]}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_isActive",
+smalltalk.method({
+selector: "isActive",
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingInput)})},
+messageSends: []}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_renderActionFor_html_",
+smalltalk.method({
+selector: "renderActionFor:html:",
+fn: function (aBinder,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2,$5;
+$1=_st(html)._span();
+_st($1)._class_("command");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
$3=_st(html)._input();
+_st($3)._class_("search-query");
+$4=_st($3)._placeholder_(_st(self)._displayLabel());
+self["@input"]=$4;
+return self["@input"];
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st(self["@input"])._onKeyPress_((function(event){
+return smalltalk.withContext(function($ctx2) {
$5=_st(_st(event)._keyCode()).__eq((13));
+if(smalltalk.assert($5)){
+return _st(self)._applyOn_(aBinder);
+};
+}, function($ctx2) {$ctx2.fillBlock({event:event},$ctx1)})}));
+_st(_st(self["@input"])._asJQuery())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderActionFor:html:",{aBinder:aBinder,html:html},smalltalk.HLBindingInput)})},
+messageSends: ["class:", "span", "with:", "input", "placeholder:", "displayLabel", "onKeyPress:", "ifTrue:", "applyOn:", "=", "keyCode", "focus", "asJQuery"]}),
+smalltalk.HLBindingInput);
+
+
+
 smalltalk.addClass('HLKeyBinder', smalltalk.Object, ['modifierKey', 'helper', 'bindings', 'selectedBinding'], 'Helios-KeyBindings');
 smalltalk.addMethod(
 "_activate",
@@ -602,45 +595,20 @@ smalltalk.method({
 selector: "applyBinding:",
 fn: function (aBinding){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(aBinding)._applyOn_(self);
-return self}, function($ctx1) {$ctx1.fill(self,"applyBinding:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
-messageSends: ["applyOn:"]}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingAction_",
-smalltalk.method({
-selector: "applyBindingAction:",
-fn: function (aBinding){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(aBinding)._callback())._value();
-_st(self)._deactivate();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingAction:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
-messageSends: ["value", "callback", "deactivate"]}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingGroup_",
-smalltalk.method({
-selector: "applyBindingGroup:",
-fn: function (aBinding){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@selectedBinding"]=aBinding;
-_st(_st(self)._helper())._refresh();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingGroup:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
-messageSends: ["refresh", "helper"]}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingInput_with_",
-smalltalk.method({
-selector: "applyBindingInput:with:",
-fn: function (aBinding,value){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(aBinding)._callback())._value_(value);
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$1=_st(aBinding)._isActive();
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+_st(self)._selectBinding_(aBinding);
+_st(aBinding)._applyOn_(self);
+$3=_st(aBinding)._isFinal();
+if(smalltalk.assert($3)){
 _st(self)._deactivate();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingInput:with:",{aBinding:aBinding,value:value},smalltalk.HLKeyBinder)})},
-messageSends: ["value:", "callback", "deactivate"]}),
+};
+return self}, function($ctx1) {$ctx1.fill(self,"applyBinding:",{aBinding:aBinding},smalltalk.HLKeyBinder)})},
+messageSends: ["ifFalse:", "isActive", "selectBinding:", "applyOn:", "ifTrue:", "deactivate", "isFinal"]}),
 smalltalk.HLKeyBinder);
 
 smalltalk.addMethod(
@@ -841,6 +809,18 @@ return $1;
 messageSends: ["is:", "asJQuery", ",", "cssClass", "helper"]}),
 smalltalk.HLKeyBinder);
 
+smalltalk.addMethod(
+"_selectBinding_",
+smalltalk.method({
+selector: "selectBinding:",
+fn: function (aBinding){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@selectedBinding"]=aBinding;
+_st(_st(self)._helper())._refresh();
+return self}, function($ctx1) {$ctx1.fill(self,"selectBinding:",{aBinding:aBinding},smalltalk.HLKeyBinder)})},
+messageSends: ["refresh", "helper"]}),
+smalltalk.HLKeyBinder);
+
 smalltalk.addMethod(
 "_selectedBinding",
 smalltalk.method({
@@ -965,10 +945,10 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(_st(_st(aBindingGroup)._activeBindings())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(_st(a)._key()).__lt(_st(b)._key());
 }, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(each){
-return smalltalk.withContext(function($ctx2) {
return _st(each)._renderBindingOn_actionOn_(html,_st(self)._keyBinder());
+return smalltalk.withContext(function($ctx2) {
return _st(each)._renderActionFor_html_(_st(self)._keyBinder(),html);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderBindingGroup:on:",{aBindingGroup:aBindingGroup,html:html},smalltalk.HLKeyBinderHelper)})},
-messageSends: ["do:", "renderBindingOn:actionOn:", "keyBinder", "sorted:", "<", "key", "activeBindings"]}),
+messageSends: ["do:", "renderActionFor:html:", "keyBinder", "sorted:", "<", "key", "activeBindings"]}),
 smalltalk.HLKeyBinderHelper);
 
 smalltalk.addMethod(

+ 275 - 305
js/Helios-KeyBindings.js

@@ -7,11 +7,41 @@ selector: "applyOn:",
 category: 'actions',
 fn: function (aKeyBinder){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(self)._subclassResponsibility();
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder}, smalltalk.HLBinding)})},
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBinding)})},
 args: ["aKeyBinder"],
-source: "applyOn: aKeyBinder\x0a\x09self subclassResponsibility",
-messageSends: ["subclassResponsibility"],
+source: "applyOn: aKeyBinder",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLBinding);
+
+smalltalk.addMethod(
+"_applyOn_then_",
+smalltalk.method({
+selector: "applyOn:then:",
+category: 'actions',
+fn: function (aKeyBinder,aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return self}, function($ctx1) {$ctx1.fill(self,"applyOn:then:",{aKeyBinder:aKeyBinder,aBlock:aBlock},smalltalk.HLBinding)})},
+args: ["aKeyBinder", "aBlock"],
+source: "applyOn: aKeyBinder then: aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLBinding);
+
+smalltalk.addMethod(
+"_atKey_",
+smalltalk.method({
+selector: "atKey:",
+category: 'accessing',
+fn: function (aKey){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return nil;
+}, function($ctx1) {$ctx1.fill(self,"atKey:",{aKey:aKey},smalltalk.HLBinding)})},
+args: ["aKey"],
+source: "atKey: aKey\x0a\x09^ nil",
+messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HLBinding);
@@ -53,32 +83,16 @@ referencedClasses: []
 smalltalk.HLBinding);
 
 smalltalk.addMethod(
-"_isBindingAction",
+"_isFinal",
 smalltalk.method({
-selector: "isBindingAction",
+selector: "isFinal",
 category: 'testing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
return false;
-}, function($ctx1) {$ctx1.fill(self,"isBindingAction",{}, smalltalk.HLBinding)})},
+}, function($ctx1) {$ctx1.fill(self,"isFinal",{},smalltalk.HLBinding)})},
 args: [],
-source: "isBindingAction\x0a\x09^ false",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBinding);
-
-smalltalk.addMethod(
-"_isBindingGroup",
-smalltalk.method({
-selector: "isBindingGroup",
-category: 'testing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
return false;
-}, function($ctx1) {$ctx1.fill(self,"isBindingGroup",{}, smalltalk.HLBinding)})},
-args: [],
-source: "isBindingGroup\x0a\x09^ false",
+source: "isFinal\x0a\x09\x22 Answer true if the receiver is the final binding of a sequence \x22\x0a\x09\x0a\x09^ false",
 messageSends: [],
 referencedClasses: []
 }),
@@ -153,11 +167,11 @@ referencedClasses: []
 smalltalk.HLBinding);
 
 smalltalk.addMethod(
-"_renderBindingOn_actionOn_",
+"_renderActionFor_html_",
 smalltalk.method({
-selector: "renderBindingOn:actionOn:",
+selector: "renderActionFor:html:",
 category: 'rendering',
-fn: function (html,aBinder){
+fn: function (aBinder,html){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$5,$6,$2;
 $1=_st(html)._span();
@@ -175,9 +189,9 @@ return smalltalk.withContext(function($ctx3) {
return _st(aBinder)._applyBinding
 }, function($ctx3) {$ctx3.fillBlock({},$ctx1)})}));
 return $6;
 }, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-return self}, function($ctx1) {$ctx1.fill(self,"renderBindingOn:actionOn:",{html:html,aBinder:aBinder},smalltalk.HLBinding)})},
-args: ["html", "aBinder"],
-source: "renderBindingOn: html actionOn: aBinder\x0a\x0a\x09html span class: 'command'; with: [\x0a\x09\x09html span \x0a\x09\x09\x09class: 'label'; \x0a\x09\x09\x09with: self shortcut asLowercase.\x0a  \x09\x09html a \x0a        \x09class: 'action'; \x0a            with: self displayLabel;\x0a  \x09\x09\x09onClick: [ aBinder applyBinding: self ] ]",
+return self}, function($ctx1) {$ctx1.fill(self,"renderActionFor:html:",{aBinder:aBinder,html:html},smalltalk.HLBinding)})},
+args: ["aBinder", "html"],
+source: "renderActionFor: aBinder html: html\x0a\x09html span class: 'command'; with: [\x0a\x09\x09html span \x0a\x09\x09\x09class: 'label'; \x0a\x09\x09\x09with: self shortcut asLowercase.\x0a  \x09\x09html a \x0a        \x09class: 'action'; \x0a            with: self displayLabel;\x0a  \x09\x09\x09onClick: [ aBinder applyBinding: self ] ]",
 messageSends: ["class:", "span", "with:", "asLowercase", "shortcut", "a", "displayLabel", "onClick:", "applyBinding:"],
 referencedClasses: []
 }),
@@ -240,49 +254,7 @@ referencedClasses: []
 smalltalk.HLBinding.klass);
 
 
-smalltalk.addClass('HLBindingAction', smalltalk.HLBinding, ['callback', 'activeBlock'], 'Helios-KeyBindings');
-smalltalk.addMethod(
-"_activeBlock",
-smalltalk.method({
-selector: "activeBlock",
-category: 'accessing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $2,$1;
-$2=self["@activeBlock"];
-if(($receiver = $2) == nil || $receiver == undefined){
-self["@activeBlock"]=(function(){
-return smalltalk.withContext(function($ctx2) {
return true;
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})});
-$1=self["@activeBlock"];
-} else {
-$1=$2;
-};
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"activeBlock",{},smalltalk.HLBindingAction)})},
-args: [],
-source: "activeBlock\x0a\x09^ activeBlock ifNil: [ activeBlock := [ true ] ]",
-messageSends: ["ifNil:"],
-referencedClasses: []
-}),
-smalltalk.HLBindingAction);
-
-smalltalk.addMethod(
-"_activeBlock_",
-smalltalk.method({
-selector: "activeBlock:",
-category: 'accessing',
-fn: function (aBlock){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@activeBlock"]=aBlock;
-return self}, function($ctx1) {$ctx1.fill(self,"activeBlock:",{aBlock:aBlock},smalltalk.HLBindingAction)})},
-args: ["aBlock"],
-source: "activeBlock: aBlock\x0a\x09activeBlock := aBlock",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBindingAction);
-
+smalltalk.addClass('HLBindingAction', smalltalk.HLBinding, ['command'], 'Helios-KeyBindings');
 smalltalk.addMethod(
 "_applyOn_",
 smalltalk.method({
@@ -290,180 +262,117 @@ selector: "applyOn:",
 category: 'actions',
 fn: function (aKeyBinder){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._command())._isInputRequired();
+if(smalltalk.assert($1)){
+_st(aKeyBinder)._selectBinding_(_st(self)._inputBinding());
+} else {
+_st(_st(self)._command())._execute();
 };
-_st(aKeyBinder)._applyBindingAction_(self);
 return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingAction)})},
 args: ["aKeyBinder"],
-source: "applyOn: aKeyBinder\x0a\x09self isActive ifFalse: [ ^ self ].\x0a\x09\x0a\x09aKeyBinder applyBindingAction: self",
-messageSends: ["ifFalse:", "isActive", "applyBindingAction:"],
+source: "applyOn: aKeyBinder\x0a\x09self command isInputRequired\x0a\x09\x09ifTrue: [ aKeyBinder selectBinding: self inputBinding ]\x0a\x09\x09ifFalse: [ self command execute ]",
+messageSends: ["ifTrue:ifFalse:", "selectBinding:", "inputBinding", "execute", "command", "isInputRequired"],
 referencedClasses: []
 }),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_callback",
+"_command",
 smalltalk.method({
-selector: "callback",
+selector: "command",
 category: 'accessing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=self["@callback"];
+$1=self["@command"];
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"callback",{}, smalltalk.HLBindingAction)})},
+}, function($ctx1) {$ctx1.fill(self,"command",{},smalltalk.HLBindingAction)})},
 args: [],
-source: "callback\x0a\x09^ callback",
+source: "command\x0a\x09^ command",
 messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_callback_",
+"_command_",
 smalltalk.method({
-selector: "callback:",
+selector: "command:",
 category: 'accessing',
-fn: function (aBlock){
+fn: function (aCommand){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@callback"]=aBlock;
-return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock}, smalltalk.HLBindingAction)})},
-args: ["aBlock"],
-source: "callback: aBlock\x0a\x09callback := aBlock",
+return smalltalk.withContext(function($ctx1) { 
self["@command"]=aCommand;
+return self}, function($ctx1) {$ctx1.fill(self,"command:",{aCommand:aCommand},smalltalk.HLBindingAction)})},
+args: ["aCommand"],
+source: "command: aCommand\x0a\x09command := aCommand",
 messageSends: [],
 referencedClasses: []
 }),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_isActive",
+"_inputBinding",
 smalltalk.method({
-selector: "isActive",
-category: 'testing',
+selector: "inputBinding",
+category: 'accessing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self)._activeBlock())._value();
+return smalltalk.withContext(function($ctx1) { 
var $2,$3,$4,$5,$1;
+$2=_st((smalltalk.HLBindingInput || HLBindingInput))._new();
+_st($2)._label_(_st(_st(self)._command())._inputLabel());
+_st($2)._callback_((function(val){
+return smalltalk.withContext(function($ctx2) {
$3=_st(self)._command();
+_st($3)._input_(val);
+$4=_st($3)._execute();
+return $4;
+}, function($ctx2) {$ctx2.fillBlock({val:val},$ctx1)})}));
+$5=_st($2)._yourself();
+$1=$5;
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingAction)})},
+}, function($ctx1) {$ctx1.fill(self,"inputBinding",{},smalltalk.HLBindingAction)})},
 args: [],
-source: "isActive\x0a\x09^ self activeBlock value",
-messageSends: ["value", "activeBlock"],
-referencedClasses: []
+source: "inputBinding\x0a\x09^ HLBindingInput new\x0a\x09\x09label: self command inputLabel;\x0a\x09\x09callback: [ :val | \x0a\x09\x09\x09self command \x0a\x09\x09\x09\x09input: val;\x0a\x09\x09\x09\x09execute ];\x0a\x09\x09yourself",
+messageSends: ["label:", "inputLabel", "command", "new", "callback:", "input:", "execute", "yourself"],
+referencedClasses: ["HLBindingInput"]
 }),
 smalltalk.HLBindingAction);
 
 smalltalk.addMethod(
-"_isBindingAction",
+"_isActive",
 smalltalk.method({
-selector: "isBindingAction",
+selector: "isActive",
 category: 'testing',
 fn: function (){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
-}, function($ctx1) {$ctx1.fill(self,"isBindingAction",{}, smalltalk.HLBindingAction)})},
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self)._command())._isActive();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingAction)})},
 args: [],
-source: "isBindingAction\x0a\x09^ true",
-messageSends: [],
+source: "isActive\x0a\x09^ self command isActive",
+messageSends: ["isActive", "command"],
 referencedClasses: []
 }),
 smalltalk.HLBindingAction);
 
-
 smalltalk.addMethod(
-"_on_labelled_activeBlock_",
+"_isFinal",
 smalltalk.method({
-selector: "on:labelled:activeBlock:",
-category: 'instance creation',
-fn: function (anInteger,aString,aBlock){
-var self=this;
-var instance;
-return smalltalk.withContext(function($ctx1) { 
var $2,$3,$1;
-instance=smalltalk.HLBinding.klass.fn.prototype._on_labelled_.apply(_st(self), [anInteger,aString]);
-$2=instance;
-_st($2)._activeBlock_(aBlock);
-$3=_st($2)._yourself();
-$1=$3;
-return $1;
-}, function($ctx1) {$ctx1.fill(self,"on:labelled:activeBlock:",{anInteger:anInteger,aString:aString,aBlock:aBlock,instance:instance},smalltalk.HLBindingAction.klass)})},
-args: ["anInteger", "aString", "aBlock"],
-source: "on: anInteger labelled: aString activeBlock: aBlock\x0a\x09| instance |\x0a\x09\x0a\x09instance := super on: anInteger labelled: aString.\x0a\x09^ instance \x0a\x09\x09activeBlock: aBlock;\x0a\x09\x09yourself",
-messageSends: ["on:labelled:", "activeBlock:", "yourself"],
-referencedClasses: []
-}),
-smalltalk.HLBindingAction.klass);
-
-
-smalltalk.addClass('HLBindingInput', smalltalk.HLBindingAction, ['input'], 'Helios-KeyBindings');
-smalltalk.addMethod(
-"_applyOn_",
-smalltalk.method({
-selector: "applyOn:",
-category: 'actions',
-fn: function (aBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-_st(aBinder)._applyBindingInput_with_(self,_st(self)._input());
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aBinder:aBinder},smalltalk.HLBindingInput)})},
-args: ["aBinder"],
-source: "applyOn: aBinder\x0a\x09self isActive ifFalse: [ ^ self ].\x0a\x09\x0a\x09aBinder applyBindingInput: self with: self input",
-messageSends: ["ifFalse:", "isActive", "applyBindingInput:with:", "input"],
-referencedClasses: []
-}),
-smalltalk.HLBindingInput);
-
-smalltalk.addMethod(
-"_input",
-smalltalk.method({
-selector: "input",
-category: 'actions',
+selector: "isFinal",
+category: 'testing',
 fn: function (){
 var self=this;
 return smalltalk.withContext(function($ctx1) { 
var $1;
-$1=_st(_st(self["@input"])._asJQuery())._val();
+$1=_st(_st(_st(self)._command())._isInputRequired())._not();
 return $1;
-}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLBindingInput)})},
+}, function($ctx1) {$ctx1.fill(self,"isFinal",{},smalltalk.HLBindingAction)})},
 args: [],
-source: "input\x0a\x09^ input asJQuery val",
-messageSends: ["val", "asJQuery"],
+source: "isFinal\x0a\x09^ self command isInputRequired not",
+messageSends: ["not", "isInputRequired", "command"],
 referencedClasses: []
 }),
-smalltalk.HLBindingInput);
-
-smalltalk.addMethod(
-"_renderBindingOn_actionOn_",
-smalltalk.method({
-selector: "renderBindingOn:actionOn:",
-category: 'rendering',
-fn: function (html,aBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2;
-$1=_st(html)._span();
-_st($1)._class_("command");
-$2=_st($1)._with_((function(){
-return smalltalk.withContext(function($ctx2) {
$3=_st(html)._input();
-_st($3)._class_("search-query");
-$4=_st($3)._placeholder_(_st(self)._displayLabel());
-self["@input"]=$4;
-return self["@input"];
-}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
-_st(_st(self["@input"])._asJQuery())._focus();
-return self}, function($ctx1) {$ctx1.fill(self,"renderBindingOn:actionOn:",{html:html,aBinder:aBinder},smalltalk.HLBindingInput)})},
-args: ["html", "aBinder"],
-source: "renderBindingOn: html actionOn: aBinder\x0a\x0a\x09html span \x0a\x09\x09class: 'command'; \x0a\x09\x09with: [\x0a\x09\x09\x09\x22html form\x0a\x09\x09\x09\x09class: 'form-search';\x0a\x09\x09\x09\x09with: [\x0a\x09\x09\x09\x09\x09html div\x0a\x09\x09\x09\x09\x09  class: 'input-append';\x0a\x09\x09\x09\x09\x09  with: [\x0a\x09\x09\x09\x09\x09\x09html input\x0a\x09\x09\x09\x09\x09\x09\x09type: 'text';\x0a\x09\x09\x09\x09\x09\x09\x09class: 'search-query';\x0a\x09\x09\x09\x09\x09\x09\x09placeholder: self displayLabel.\x0a\x09\x09\x09\x09\x09\x09html button\x0a\x09\x09\x09\x09\x09\x09\x09type: 'submit';\x0a\x09\x09\x09\x09\x09\x09\x09class: 'btn';\x0a\x09\x09\x09\x09\x09\x09\x09with: 'Ok' ] ] ]\x0a\x09\x09\x22\x0a\x09\x09input := html input\x0a\x09\x09\x09class: 'search-query';\x0a\x09\x09\x09placeholder: self displayLabel ].\x0a\x09\x09input asJQuery focus",
-messageSends: ["class:", "span", "with:", "input", "placeholder:", "displayLabel", "focus", "asJQuery"],
-referencedClasses: []
-}),
-smalltalk.HLBindingInput);
+smalltalk.HLBindingAction);
 
 
 
@@ -526,26 +435,6 @@ referencedClasses: ["HLBindingAction"]
 }),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_addActionKey_labelled_command_",
-smalltalk.method({
-selector: "addActionKey:labelled:command:",
-category: 'accessing',
-fn: function (anInteger,aString,aCommand){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st((smalltalk.HLBindingAction || HLBindingAction))._on_labelled_(anInteger,aString);
-_st($1)._command_(aCommand);
-$2=_st($1)._yourself();
-_st(self)._add_($2);
-return self}, function($ctx1) {$ctx1.fill(self,"addActionKey:labelled:command:",{anInteger:anInteger,aString:aString,aCommand:aCommand}, smalltalk.HLBindingGroup)})},
-args: ["anInteger", "aString", "aCommand"],
-source: "addActionKey: anInteger labelled: aString command: aCommand\x0a\x09self add: ((HLBindingAction on: anInteger labelled: aString)\x0a    \x09command: aCommand;\x0a        yourself)",
-messageSends: ["add:", "command:", "on:labelled:", "yourself"],
-referencedClasses: ["HLBindingAction"]
-}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_addGroupKey_labelled_",
 smalltalk.method({
@@ -562,28 +451,6 @@ referencedClasses: ["HLBindingGroup"]
 }),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_applyOn_",
-smalltalk.method({
-selector: "applyOn:",
-category: 'actions',
-fn: function (aKeyBinder){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
var $1,$2;
-$1=_st(self)._isActive();
-if(! smalltalk.assert($1)){
-$2=self;
-return $2;
-};
-_st(aKeyBinder)._applyBindingGroup_(self);
-return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingGroup)})},
-args: ["aKeyBinder"],
-source: "applyOn: aKeyBinder\x0a\x09self isActive ifFalse: [ ^ self ].\x0a\x09\x0a\x09aKeyBinder applyBindingGroup: self",
-messageSends: ["ifFalse:", "isActive", "applyBindingGroup:"],
-referencedClasses: []
-}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_at_",
 smalltalk.method({
@@ -714,22 +581,6 @@ referencedClasses: []
 }),
 smalltalk.HLBindingGroup);
 
-smalltalk.addMethod(
-"_isBindingGroup",
-smalltalk.method({
-selector: "isBindingGroup",
-category: 'testing',
-fn: function (){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
return true;
-}, function($ctx1) {$ctx1.fill(self,"isBindingGroup",{}, smalltalk.HLBindingGroup)})},
-args: [],
-source: "isBindingGroup\x0a\x09^ true",
-messageSends: [],
-referencedClasses: []
-}),
-smalltalk.HLBindingGroup);
-
 smalltalk.addMethod(
 "_renderOn_html_",
 smalltalk.method({
@@ -752,6 +603,148 @@ smalltalk.HLBindingGroup);
 
 
 
+smalltalk.addClass('HLBindingInput', smalltalk.HLBinding, ['input', 'callback'], 'Helios-KeyBindings');
+smalltalk.addMethod(
+"_applyOn_",
+smalltalk.method({
+selector: "applyOn:",
+category: 'actions',
+fn: function (aKeyBinder){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(self)._evaluate_(_st(self)._input());
+return self}, function($ctx1) {$ctx1.fill(self,"applyOn:",{aKeyBinder:aKeyBinder},smalltalk.HLBindingInput)})},
+args: ["aKeyBinder"],
+source: "applyOn: aKeyBinder\x0a\x09self evaluate: self input",
+messageSends: ["evaluate:", "input"],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_callback",
+smalltalk.method({
+selector: "callback",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $2,$1;
+$2=self["@callback"];
+if(($receiver = $2) == nil || $receiver == undefined){
+self["@callback"]=(function(value){
+return smalltalk.withContext(function($ctx2) {
}, function($ctx2) {$ctx2.fillBlock({value:value},$ctx1)})});
+$1=self["@callback"];
+} else {
+$1=$2;
+};
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"callback",{},smalltalk.HLInputBinding)})},
+args: [],
+source: "callback\x0a\x09^ callback ifNil: [ callback := [ :value | ] ]",
+messageSends: ["ifNil:"],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_callback_",
+smalltalk.method({
+selector: "callback:",
+category: 'accessing',
+fn: function (aBlock){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@callback"]=aBlock;
+return self}, function($ctx1) {$ctx1.fill(self,"callback:",{aBlock:aBlock},smalltalk.HLInputBinding)})},
+args: ["aBlock"],
+source: "callback: aBlock\x0a\x09callback := aBlock",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_evaluate_",
+smalltalk.method({
+selector: "evaluate:",
+category: 'actions',
+fn: function (aString){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
_st(_st(self)._callback())._value_(aString);
+return self}, function($ctx1) {$ctx1.fill(self,"evaluate:",{aString:aString},smalltalk.HLBindingInput)})},
+args: ["aString"],
+source: "evaluate: aString\x0a\x09self callback value: aString",
+messageSends: ["value:", "callback"],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_input",
+smalltalk.method({
+selector: "input",
+category: 'accessing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1;
+$1=_st(_st(self["@input"])._asJQuery())._val();
+return $1;
+}, function($ctx1) {$ctx1.fill(self,"input",{},smalltalk.HLBindingInput)})},
+args: [],
+source: "input\x0a\x09^ input asJQuery val",
+messageSends: ["val", "asJQuery"],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_isActive",
+smalltalk.method({
+selector: "isActive",
+category: 'testing',
+fn: function (){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
return true;
+}, function($ctx1) {$ctx1.fill(self,"isActive",{},smalltalk.HLBindingInput)})},
+args: [],
+source: "isActive\x0a\x09^ true",
+messageSends: [],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+smalltalk.addMethod(
+"_renderActionFor_html_",
+smalltalk.method({
+selector: "renderActionFor:html:",
+category: 'accessing',
+fn: function (aBinder,html){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
var $1,$3,$4,$2,$5;
+$1=_st(html)._span();
+_st($1)._class_("command");
+$2=_st($1)._with_((function(){
+return smalltalk.withContext(function($ctx2) {
$3=_st(html)._input();
+_st($3)._class_("search-query");
+$4=_st($3)._placeholder_(_st(self)._displayLabel());
+self["@input"]=$4;
+return self["@input"];
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1)})}));
+_st(self["@input"])._onKeyPress_((function(event){
+return smalltalk.withContext(function($ctx2) {
$5=_st(_st(event)._keyCode()).__eq((13));
+if(smalltalk.assert($5)){
+return _st(self)._applyOn_(aBinder);
+};
+}, function($ctx2) {$ctx2.fillBlock({event:event},$ctx1)})}));
+_st(_st(self["@input"])._asJQuery())._focus();
+return self}, function($ctx1) {$ctx1.fill(self,"renderActionFor:html:",{aBinder:aBinder,html:html},smalltalk.HLBindingInput)})},
+args: ["aBinder", "html"],
+source: "renderActionFor: aBinder html: html\x0a\x09html span \x0a\x09\x09class: 'command'; \x0a\x09\x09with: [\x0a\x09\x09\x09input := html input\x0a\x09\x09\x09\x09class: 'search-query';\x0a\x09\x09\x09\x09placeholder: self displayLabel ].\x0a\x09\x09\x09\x09\x0a\x09input onKeyPress: [:event |\x0a\x09\x09event keyCode = 13 ifTrue: [\x0a\x09\x09\x09self applyOn: aBinder ] ].\x0a\x09\x09\x09\x09\x0a\x09input asJQuery focus",
+messageSends: ["class:", "span", "with:", "input", "placeholder:", "displayLabel", "onKeyPress:", "ifTrue:", "applyOn:", "=", "keyCode", "focus", "asJQuery"],
+referencedClasses: []
+}),
+smalltalk.HLBindingInput);
+
+
+
 smalltalk.addClass('HLKeyBinder', smalltalk.Object, ['modifierKey', 'helper', 'bindings', 'selectedBinding'], 'Helios-KeyBindings');
 smalltalk.addMethod(
 "_activate",
@@ -808,62 +801,22 @@ selector: "applyBinding:",
 category: 'actions',
 fn: function (aBinding){
 var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(aBinding)._applyOn_(self);
-return self}, function($ctx1) {$ctx1.fill(self,"applyBinding:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
-args: ["aBinding"],
-source: "applyBinding: aBinding\x0a    aBinding applyOn: self",
-messageSends: ["applyOn:"],
-referencedClasses: []
-}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingAction_",
-smalltalk.method({
-selector: "applyBindingAction:",
-category: 'actions',
-fn: function (aBinding){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(aBinding)._callback())._value();
+return smalltalk.withContext(function($ctx1) { 
var $1,$2,$3;
+$1=_st(aBinding)._isActive();
+if(! smalltalk.assert($1)){
+$2=self;
+return $2;
+};
+_st(self)._selectBinding_(aBinding);
+_st(aBinding)._applyOn_(self);
+$3=_st(aBinding)._isFinal();
+if(smalltalk.assert($3)){
 _st(self)._deactivate();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingAction:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
-args: ["aBinding"],
-source: "applyBindingAction: aBinding\x0a    aBinding callback value.\x0a\x09self deactivate",
-messageSends: ["value", "callback", "deactivate"],
-referencedClasses: []
-}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingGroup_",
-smalltalk.method({
-selector: "applyBindingGroup:",
-category: 'actions',
-fn: function (aBinding){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
self["@selectedBinding"]=aBinding;
-_st(_st(self)._helper())._refresh();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingGroup:",{aBinding:aBinding}, smalltalk.HLKeyBinder)})},
+};
+return self}, function($ctx1) {$ctx1.fill(self,"applyBinding:",{aBinding:aBinding},smalltalk.HLKeyBinder)})},
 args: ["aBinding"],
-source: "applyBindingGroup: aBinding\x0a    selectedBinding := aBinding.\x0a    self helper refresh",
-messageSends: ["refresh", "helper"],
-referencedClasses: []
-}),
-smalltalk.HLKeyBinder);
-
-smalltalk.addMethod(
-"_applyBindingInput_with_",
-smalltalk.method({
-selector: "applyBindingInput:with:",
-category: 'actions',
-fn: function (aBinding,value){
-var self=this;
-return smalltalk.withContext(function($ctx1) { 
_st(_st(aBinding)._callback())._value_(value);
-_st(self)._deactivate();
-return self}, function($ctx1) {$ctx1.fill(self,"applyBindingInput:with:",{aBinding:aBinding,value:value},smalltalk.HLKeyBinder)})},
-args: ["aBinding", "value"],
-source: "applyBindingInput: aBinding with: value\x0a    aBinding callback value: value.\x0a\x09self deactivate",
-messageSends: ["value:", "callback", "deactivate"],
+source: "applyBinding: aBinding\x0a\x09aBinding isActive ifFalse: [ ^ self ].\x0a\x09\x0a\x09self selectBinding: aBinding.\x0a    aBinding applyOn: self.\x0a\x09\x0a\x09aBinding isFinal ifTrue: [ self deactivate ]",
+messageSends: ["ifFalse:", "isActive", "selectBinding:", "applyOn:", "ifTrue:", "deactivate", "isFinal"],
 referencedClasses: []
 }),
 smalltalk.HLKeyBinder);
@@ -1126,6 +1079,23 @@ referencedClasses: []
 }),
 smalltalk.HLKeyBinder);
 
+smalltalk.addMethod(
+"_selectBinding_",
+smalltalk.method({
+selector: "selectBinding:",
+category: 'actions',
+fn: function (aBinding){
+var self=this;
+return smalltalk.withContext(function($ctx1) { 
self["@selectedBinding"]=aBinding;
+_st(_st(self)._helper())._refresh();
+return self}, function($ctx1) {$ctx1.fill(self,"selectBinding:",{aBinding:aBinding},smalltalk.HLKeyBinder)})},
+args: ["aBinding"],
+source: "selectBinding: aBinding\x09\x0a\x09selectedBinding := aBinding.\x0a\x09self helper refresh",
+messageSends: ["refresh", "helper"],
+referencedClasses: []
+}),
+smalltalk.HLKeyBinder);
+
 smalltalk.addMethod(
 "_selectedBinding",
 smalltalk.method({
@@ -1296,12 +1266,12 @@ var self=this;
 return smalltalk.withContext(function($ctx1) { 
_st(_st(_st(aBindingGroup)._activeBindings())._sorted_((function(a,b){
 return smalltalk.withContext(function($ctx2) {
return _st(_st(a)._key()).__lt(_st(b)._key());
 }, function($ctx2) {$ctx2.fillBlock({a:a,b:b},$ctx1)})})))._do_((function(each){
-return smalltalk.withContext(function($ctx2) {
return _st(each)._renderBindingOn_actionOn_(html,_st(self)._keyBinder());
+return smalltalk.withContext(function($ctx2) {
return _st(each)._renderActionFor_html_(_st(self)._keyBinder(),html);
 }, function($ctx2) {$ctx2.fillBlock({each:each},$ctx1)})}));
 return self}, function($ctx1) {$ctx1.fill(self,"renderBindingGroup:on:",{aBindingGroup:aBindingGroup,html:html},smalltalk.HLKeyBinderHelper)})},
 args: ["aBindingGroup", "html"],
-source: "renderBindingGroup: aBindingGroup on: html\x0a\x09(aBindingGroup activeBindings \x0a    \x09sorted: [ :a :b | a key < b key ])\x0a        do: [ :each | each renderBindingOn: html actionOn: self keyBinder ]",
-messageSends: ["do:", "renderBindingOn:actionOn:", "keyBinder", "sorted:", "<", "key", "activeBindings"],
+source: "renderBindingGroup: aBindingGroup on: html\x0a\x09(aBindingGroup activeBindings \x0a    \x09sorted: [ :a :b | a key < b key ])\x0a        do: [ :each | each renderActionFor: self keyBinder html: html ]",
+messageSends: ["do:", "renderActionFor:html:", "keyBinder", "sorted:", "<", "key", "activeBindings"],
 referencedClasses: []
 }),
 smalltalk.HLKeyBinderHelper);

+ 17 - 22
st/Helios-Commands-Browser.st

@@ -173,41 +173,36 @@ HLMoveMethodToCommand subclass: #HLMoveMethodToClassCommand
  instanceVariableNames: ''
  package: 'Helios-Commands-Browser'!
 
-!HLMoveMethodToClassCommand class methodsFor: 'accessing'!
-
-key
-	^ 67
-!
+!HLMoveMethodToClassCommand methodsFor: 'accessing'!
 
-label	
-	^ 'to class'
+inputLabel
+	^ 'Move method to class:'
 ! !
 
-HLMoveMethodToClassCommand subclass: #HLMethodMoveToClassSelectionCommand
- instanceVariableNames: ''
- package: 'Helios-Commands-Browser'!
-
-!HLMethodMoveToClassSelectionCommand methodsFor: 'actions'!
+!HLMoveMethodToClassCommand methodsFor: 'executing'!
 
-execute: aClass
-	self model moveMethodToClass: aClass
+execute
+	| class |
+	class := Smalltalk current at: self input.
+	class ifNil: [ self commandError: 'No class named: ', self input ].
+	
+	self model moveMethodToClass: class
 ! !
 
-!HLMethodMoveToClassSelectionCommand methodsFor: 'converting'!
+!HLMoveMethodToClassCommand methodsFor: 'testing'!
 
-asBinding
-	^ (HLBindingInput on: self key labelled: self label activeBlock: self activeBlock)
-    	callback: [:ex | self execute: ex ]
+isInputRequired
+	^ true
 ! !
 
-!HLMethodMoveToClassSelectionCommand class methodsFor: 'accessing'!
+!HLMoveMethodToClassCommand class methodsFor: 'accessing'!
 
 key
-	^ 13 "enter"
+	^ 67
 !
 
-label
-	^ 'select a class'
+label	
+	^ 'to class'
 ! !
 
 HLMoveMethodToCommand subclass: #HLMoveMethodToProtocolCommand

+ 43 - 27
st/Helios-Commands-Core.st

@@ -1,18 +1,30 @@
 Smalltalk current createPackage: 'Helios-Commands-Core'!
 Object subclass: #HLCommand
- instanceVariableNames: ''
+ instanceVariableNames: 'input'
  package: 'Helios-Commands-Core'!
 
 !HLCommand methodsFor: 'accessing'!
 
-activeBlock
-	^ [ true ]
-!
-
 documentation
 	^ self class documentation
 !
 
+input
+	^ input
+!
+
+input: aString
+	^ input := aString
+!
+
+inputCompletion
+	^ #()
+!
+
+inputLabel
+	^ self label
+!
+
 key
 	^ self class key
 !
@@ -24,8 +36,9 @@ label
 !HLCommand methodsFor: 'converting'!
 
 asActionBinding
-	^ (HLBindingAction on: self key labelled: self label activeBlock: self activeBlock)
-    	callback: [ self execute ]
+	^ (HLBindingAction on: self key labelled: self label)
+    	command: self;
+		yourself
 !
 
 asBinding
@@ -40,6 +53,12 @@ asGroupBinding
 		labelled: self label
 ! !
 
+!HLCommand methodsFor: 'error handling'!
+
+commandError: aString
+	self error: aString
+! !
+
 !HLCommand methodsFor: 'executing'!
 
 execute
@@ -53,17 +72,20 @@ registerOn: aBinding
 
 !HLCommand methodsFor: 'testing'!
 
+isActive
+	^ true
+!
+
 isBindingGroup
 	^ (self class methodDictionary includesKey: 'execute') not
+!
+
+isInputRequired
+	^ false
 ! !
 
 !HLCommand class methodsFor: 'accessing'!
 
-concreteSubclasses
-	^ self subclasses select: [ :each |
-		each isConcrete ]
-!
-
 documentation
 	^ ''
 !
@@ -76,23 +98,13 @@ label
 	^ ''
 ! !
 
-!HLCommand class methodsFor: 'converting'!
-
-asBindingOn: aBinding
-	| instance |
-	
-	instance := self new asBinding.
-	aBinding add: instance.
-	^ instance
-! !
-
 !HLCommand class methodsFor: 'registration'!
 
 registerConcreteClassesOn: aBinding
 	| newBinding |
 	
 	self isConcrete
-		ifTrue: [ newBinding := self asBindingOn: aBinding ]
+		ifTrue: [ newBinding := self registerOn: aBinding ]
 		ifFalse: [ newBinding := aBinding ].
 		
 	self subclasses do: [ :each | each registerConcreteClassesOn: newBinding ]
@@ -151,10 +163,14 @@ for: aModel
 !HLModelCommand class methodsFor: 'registration'!
 
 registerConcreteClassesOn: aBinding for: aModel
-	self concreteSubclasses do: [ :each | | binding |
-		binding := each registerOn: aBinding for: aModel.
-		binding isBindingGroup ifTrue: [
-			each registerConcreteClassesOn: binding for: aModel ] ]
+	| newBinding |
+	
+	self isConcrete
+		ifTrue: [ newBinding := self registerOn: aBinding for: aModel ]
+		ifFalse: [ newBinding := aBinding ].
+		
+	self subclasses do: [ :each |
+		each registerConcreteClassesOn: newBinding for: aModel ]
 !
 
 registerOn: aBinding for: aModel

+ 88 - 112
st/Helios-KeyBindings.st

@@ -5,6 +5,10 @@ Object subclass: #HLBinding
 
 !HLBinding methodsFor: 'accessing'!
 
+atKey: aKey
+	^ nil
+!
+
 displayLabel
 	^ self label
 !
@@ -32,13 +36,14 @@ shortcut
 !HLBinding methodsFor: 'actions'!
 
 applyOn: aKeyBinder
-	self subclassResponsibility
+!
+
+applyOn: aKeyBinder then: aBlock
 ! !
 
 !HLBinding methodsFor: 'rendering'!
 
-renderBindingOn: html actionOn: aBinder
-
+renderActionFor: aBinder html: html
 	html span class: 'command'; with: [
 		html span 
 			class: 'label'; 
@@ -58,11 +63,9 @@ isActive
 	^ self subclassResponsibility
 !
 
-isBindingAction
-	^ false
-!
-
-isBindingGroup
+isFinal
+	" Answer true if the receiver is the final binding of a sequence "
+	
 	^ false
 ! !
 
@@ -76,98 +79,45 @@ on: anInteger labelled: aString
 ! !
 
 HLBinding subclass: #HLBindingAction
- instanceVariableNames: 'callback activeBlock'
+ instanceVariableNames: 'command'
  package: 'Helios-KeyBindings'!
 
 !HLBindingAction methodsFor: 'accessing'!
 
-activeBlock
-	^ activeBlock ifNil: [ activeBlock := [ true ] ]
+command
+	^ command
 !
 
-activeBlock: aBlock
-	activeBlock := aBlock
-!
-
-callback
-	^ callback
+command: aCommand
+	command := aCommand
 !
 
-callback: aBlock
-	callback := aBlock
+inputBinding
+	^ HLBindingInput new
+		label: self command inputLabel;
+		callback: [ :val | 
+			self command 
+				input: val;
+				execute ];
+		yourself
 ! !
 
 !HLBindingAction methodsFor: 'actions'!
 
 applyOn: aKeyBinder
-	self isActive ifFalse: [ ^ self ].
-	
-	aKeyBinder applyBindingAction: self
+	self command isInputRequired
+		ifTrue: [ aKeyBinder selectBinding: self inputBinding ]
+		ifFalse: [ self command execute ]
 ! !
 
 !HLBindingAction methodsFor: 'testing'!
 
 isActive
-	^ self activeBlock value
+	^ self command isActive
 !
 
-isBindingAction
-	^ true
-! !
-
-!HLBindingAction class methodsFor: 'instance creation'!
-
-on: anInteger labelled: aString activeBlock: aBlock
-	| instance |
-	
-	instance := super on: anInteger labelled: aString.
-	^ instance 
-		activeBlock: aBlock;
-		yourself
-! !
-
-HLBindingAction subclass: #HLBindingInput
- instanceVariableNames: 'input'
- package: 'Helios-KeyBindings'!
-
-!HLBindingInput methodsFor: 'actions'!
-
-applyOn: aBinder
-	self isActive ifFalse: [ ^ self ].
-	
-	aBinder applyBindingInput: self with: self input
-!
-
-input
-	^ input asJQuery val
-! !
-
-!HLBindingInput methodsFor: 'rendering'!
-
-renderBindingOn: html actionOn: aBinder
-
-	html span 
-		class: 'command'; 
-		with: [
-			"html form
-				class: 'form-search';
-				with: [
-					html div
-					  class: 'input-append';
-					  with: [
-						html input
-							type: 'text';
-							class: 'search-query';
-							placeholder: self displayLabel.
-						html button
-							type: 'submit';
-							class: 'btn';
-							with: 'Ok' ] ] ]
-		"
-		input := html input
-			class: 'search-query';
-			placeholder: self displayLabel ].
-		input asJQuery focus
+isFinal
+	^ self command isInputRequired not
 ! !
 
 HLBinding subclass: #HLBindingGroup
@@ -190,12 +140,6 @@ addActionKey: anInteger labelled: aString callback: aBlock
         yourself)
 !
 
-addActionKey: anInteger labelled: aString command: aCommand
-	self add: ((HLBindingAction on: anInteger labelled: aString)
-    	command: aCommand;
-        yourself)
-!
-
 addGroupKey: anInteger labelled: aString
 	self add: (HLBindingGroup on: anInteger labelled: aString)
 !
@@ -229,14 +173,6 @@ displayLabel
 	^ super displayLabel, '...'
 ! !
 
-!HLBindingGroup methodsFor: 'actions'!
-
-applyOn: aKeyBinder
-	self isActive ifFalse: [ ^ self ].
-	
-	aKeyBinder applyBindingGroup: self
-! !
-
 !HLBindingGroup methodsFor: 'rendering'!
 
 renderOn: aBindingHelper html: html
@@ -248,9 +184,54 @@ renderOn: aBindingHelper html: html
 
 isActive
 	^ self activeBindings notEmpty
+! !
+
+HLBinding subclass: #HLBindingInput
+ instanceVariableNames: 'input callback'
+ package: 'Helios-KeyBindings'!
+
+!HLBindingInput methodsFor: 'accessing'!
+
+callback
+	^ callback ifNil: [ callback := [ :value | ] ]
+!
+
+callback: aBlock
+	callback := aBlock
+!
+
+input
+	^ input asJQuery val
+!
+
+renderActionFor: aBinder html: html
+	html span 
+		class: 'command'; 
+		with: [
+			input := html input
+				class: 'search-query';
+				placeholder: self displayLabel ].
+				
+	input onKeyPress: [:event |
+		event keyCode = 13 ifTrue: [
+			self applyOn: aBinder ] ].
+				
+	input asJQuery focus
+! !
+
+!HLBindingInput methodsFor: 'actions'!
+
+applyOn: aKeyBinder
+	self evaluate: self input
 !
 
-isBindingGroup
+evaluate: aString
+	self callback value: aString
+! !
+
+!HLBindingInput methodsFor: 'testing'!
+
+isActive
 	^ true
 ! !
 
@@ -293,22 +274,12 @@ activate
 !
 
 applyBinding: aBinding
-    aBinding applyOn: self
-!
-
-applyBindingAction: aBinding
-    aBinding callback value.
-	self deactivate
-!
-
-applyBindingGroup: aBinding
-    selectedBinding := aBinding.
-    self helper refresh
-!
-
-applyBindingInput: aBinding with: value
-    aBinding callback value: value.
-	self deactivate
+	aBinding isActive ifFalse: [ ^ self ].
+	
+	self selectBinding: aBinding.
+    aBinding applyOn: self.
+	
+	aBinding isFinal ifTrue: [ self deactivate ]
 !
 
 deactivate
@@ -318,6 +289,11 @@ deactivate
 
 flushBindings
 	bindings := nil
+!
+
+selectBinding: aBinding	
+	selectedBinding := aBinding.
+	self helper refresh
 ! !
 
 !HLKeyBinder methodsFor: 'defaults'!
@@ -453,7 +429,7 @@ registerBindings
 renderBindingGroup: aBindingGroup on: html
 	(aBindingGroup activeBindings 
     	sorted: [ :a :b | a key < b key ])
-        do: [ :each | each renderBindingOn: html actionOn: self keyBinder ]
+        do: [ :each | each renderActionFor: self keyBinder html: html ]
 !
 
 renderBindingOn: html