//
Lively Kernel canvas
Draft
Property
Completion
Menu
40
true
Marko
wants
CTRL
+
SPACE
....
20
null
1
cop.create(
'ProperyCompletionMenuLayer'
).
refineClass
(TextMorph,
{
propertyCompletionMenuItemsFor:
function
(obj)
{
return
Properties.all(obj).collect(
function
(ea)
{
return
[ea,
function
()
{}
]
}
)
}
,
showPropertyCompletionMenuFor:
function
(obj)
{
var
menu
=
new
MenuMorph([[
"Hello"
,
function
()
{}
]
],
this
);
menu.openInWorld(
this
.getPosition())
return
menu
}
,
onKeyDown:
function
(evt)
{
if
(evt.getKeyCode()
==
Event.KEY_SPACEBAR
&&
evt.isCtrlDown())
{
var
cursor
=
this
.selectionRange[
0
];
var
lastChar
=
this
.textString.substring(cursor
-
1
,
cursor);
if
(lastChar
==
"."
)
{
var
lastWordRange
=
this
.locale.selectWord(
this
.textString,
cursor
-
1
)
var
word
=
this
.textString.substring(lastWordRange[
0
],
lastWordRange[
1
]
+
1
)
if
(word)
{
var
lastWord
=
this
.textString.substring(lastWordRange[
0
],
cursor);
}
}
}
return
cop.proceed(evt)
}
}
)
$morph(
'exampleText'
).setWithLayers([ProperyCompletionMenuLayer])
9
bla.
exampleObject:
Hi!
exampleObject:
Hi!
2
null
false
true
null
false
TabCompletion.js:TabCompletionLayer
false
null
true
false
X
false
null
true
false
false
M
false
null
true
false
false
–
false
null
true
false
false
null
false
http://www.lively-kernel.org/repository/webwerkstatt/lively/
true
true
true
true
true
true
true
0
0.1
1
true
true
codebase
false
null
true
false
true
local
false
null
true
false
true
Base.js
(not
parsed)
false
false
true
false
true
0
false
bindings.js
(not
parsed)
false
false
true
false
true
0
false
bootstrap.js
(not
parsed)
false
false
true
false
true
0
false
CanvasExpt.js
(not
parsed)
false
false
true
false
true
0
false
ChangeSet.js
(not
parsed)
false
false
true
false
true
0
false
Connector.js
(not
parsed)
false
false
true
false
true
0
false
Contributions.js
(not
parsed)
false
false
true
false
true
0
false
Core.js
(not
parsed)
false
false
true
false
true
0
false
Data.js
(not
parsed)
false
false
true
false
true
0
false
defaultconfig.js
(not
parsed)
false
false
true
false
true
0
false
demofx.js
(not
parsed)
false
false
true
false
true
0
false
EmuDom.js
(not
parsed)
false
false
true
false
true
0
false
Examples.js
(not
parsed)
false
false
true
false
true
0
false
Fabrik.js
(not
parsed)
false
false
true
false
true
0
false
FileUploadWidget.js
(not
parsed)
false
false
true
false
true
0
false
Graffle.js
(not
parsed)
false
false
true
false
true
0
false
GridLayout.js
(not
parsed)
false
false
true
false
true
0
false
Helper.js
(not
parsed)
false
false
true
false
true
0
false
ide.js
(not
parsed)
false
false
true
false
true
0
false
JSON.js
(not
parsed)
false
false
true
false
true
0
false
LayerableMorphs.js
(not
parsed)
false
false
true
false
true
0
false
lk-js-parser.ometa
(not
parsed)
false
false
true
false
true
0
false
LKFileParser.js
(not
parsed)
false
false
true
false
true
0
false
LKFileParser.ometa
(not
parsed)
false
false
true
false
true
0
false
LKWiki.js
(not
parsed)
false
false
true
false
true
0
false
Local
code
false
false
true
false
true
0
false
localconfig.js
(not
parsed)
false
false
true
false
true
0
false
Main.js
(not
parsed)
false
false
true
false
true
0
false
miniprototype.js
(not
parsed)
false
false
true
false
true
0
false
Network.js
(not
parsed)
false
false
true
false
true
0
false
obsolete.js
(not
parsed)
false
false
true
false
true
0
false
Ometa.js
(not
parsed)
false
false
true
false
true
0
false
Persistence.js
(not
parsed)
false
false
true
false
true
0
false
phone.js
(not
parsed)
false
false
true
false
true
0
false
Presentation.js
(not
parsed)
false
false
true
false
true
0
false
rhino-compat.js
(not
parsed)
false
false
true
false
true
0
false
scene.js
(not
parsed)
false
false
true
false
true
0
false
Scripting.js
(not
parsed)
false
false
true
false
true
0
false
SerializationRefactoring.js
(not
parsed)
false
false
true
false
true
0
false
simpleMain.js
(not
parsed)
false
false
true
false
true
0
false
SmalltalkParser.js
(not
parsed)
false
false
true
false
true
0
false
SmalltalkParser.ometa
(not
parsed)
false
false
true
false
true
0
false
SmalltalkParserSupport.js
(not
parsed)
false
false
true
false
true
0
false
SmartRefSerialization.js
(not
parsed)
false
false
true
false
true
0
false
SpellChecker.js
(not
parsed)
false
false
true
false
true
0
false
Storage.js
(not
parsed)
false
false
true
false
true
0
false
Styles.js
(not
parsed)
false
false
true
false
true
0
false
SyntaxHighlighting.js
(not
parsed)
false
false
true
false
true
0
false
TabCompletion.js
false
false
true
false
true
0
false
TestFramework.js
(not
parsed)
false
false
true
false
true
0
false
TestRunnerExtensions.js
(not
parsed)
false
false
true
false
true
0
false
Text.js
(not
parsed)
false
false
true
false
true
0
false
TileScripting.js
(not
parsed)
false
false
true
false
true
0
false
Tools.js
(not
parsed)
false
false
true
false
true
0
false
TouchSupport.js
(not
parsed)
false
false
true
false
true
0
false
Undo.js
(not
parsed)
false
false
true
false
true
0
false
WebPIM.js
(not
parsed)
false
false
true
false
true
0
false
Widgets.js
(not
parsed)
false
false
true
false
true
0
false
WikiParser.js
(not
parsed)
false
false
true
false
true
0
false
WikiParser.ometa
(not
parsed)
false
false
true
false
true
0
false
WikiWidget.js
(not
parsed)
false
false
true
false
true
0
false
208
null
48
null
true
true
true
0.7619367849349855
0.1
1
true
null
null
null
null
true
true
TabCompletion
false
false
true
false
true
0
false
TabCompletion
(extension)
false
false
true
false
true
0
false
TabCompletionLayer
false
false
true
false
true
0
false
208
null
2
null
true
true
true
0
0.1
1
true
null
null
null
null
true
true
TextMorph
false
false
true
false
true
0
false
208
null
-1
null
null
true
true
true
0
0.1
1
true
null
null
null
null
true
true
-----
false
false
true
false
true
0
false
208
null
-1
null
null
true
true
true
0
0.1
1
true
null
null
null
null
true
true
20
null
cop.create(
'TabCompletionLayer'
).
refineClass
(TextMorph,
{
tabCompletionChoicesForLastWord:
function
(lastWord)
{
var
selector
=
function
(ea)
{
return
ea.startsWith(lastWord)
}
;
var
choices
=
this
.checkForPropertyChoicesAt(
this
.selectionRange[
0
]);
//
console.log("choices
"
+
choices)
var
allChoices
=
TabCompletion.allSymbols();
if
(choices)
{
allChoices
=
allChoices.concat(choices.uniq().select(selector)).sort();
}
var
localCoices
=
TabCompletion.extractLocalSymbols(
this
.textString);
localCoices
=
localCoices.reject(
function
(ea)
{
return
ea
==
"lastWord"
}
);
//
don't
match
yourself
var
selectedAllChoices
=
allChoices.select(selector);
var
selectedLocalChoices
=
localCoices.select(selector);
;
return
selectedAllChoices.concat(selectedLocalChoices).uniq().sort()
}
,
tabCompletionForLastWord:
function
(lastWord,
backward)
{
if
(
this
.tabReplacePrefix
!==
lastWord)
{
this
.tabReplaceListIndex
=
0
;
this
.tabReplacePrefix
=
lastWord;
}
;
var
choices
=
this
.tabCompletionChoicesForLastWord(lastWord);
//
||
(this.selectionString().length
==
0)
if
(
this
.tabReplaceListIndex
===
undefined
)
{
this
.tabReplaceListIndex
=
0
;
}
else
{
this
.tabReplaceListIndex
=
this
.tabReplaceListIndex
+
(backward
?
-
1
:
1
);
this
.tabReplaceListIndex
=
(
this
.tabReplaceListIndex)
%
choices.size();
if
(
this
.tabReplaceListIndex
<
0
)
{
this
.tabReplaceListIndex
=
this
.tabReplaceListIndex
+
choices.size();
}
}
//
console.log("choices:
"
+
choices
+
"
"
+
this.tabReplaceListIndex);
return
choices[
this
.tabReplaceListIndex];
}
,
allPropertiesOf:
function
(object)
{
if
(
typeof
object
!==
'object'
)
throw
new
TypeError
(
'not
an
object'
);
var
names
=
[];
//
check
behavior
wrt
arrays
for
(
var
name
in
object)
{
names.push(name);
}
return
names;
}
,
checkForLastExpression:
function
(cursor)
{
var
index
=
this
.textString.lastIndexOf(
"\n"
,
cursor
-
1
);
if
(index
!==
-
1
)
{
var
exp
=
this
.textString.substring(index,
cursor
);
//
console.log("exp
"
+
exp
+
"
index
"
+
index)
//
"hello.".match(/[\n
\t]*([A-Za-z0-9]+)\.([A-Za-z0-9]*)$/)
//
"hello.wo".match(/[\n
\t]*([A-Za-z0-9]+)\.([A-Za-z0-9]*)$/)
//
"bla(hello.wo".match(/[\n
\t]*([A-Za-z0-9]+)\.([A-Za-z0-9]*)$/)
var
m
=
exp.match(
/[\n
\t]*([A-Za-z0-9]+)\.([A-Za-z0-9]*)$/
)
if
(m)
{
return
m[
1
]
}
}
}
,
checkForPropertyChoicesAt:
function
(cursor)
{
var
lastExpression
=
this
.checkForLastExpression(cursor);
//
console.log("lastExpression:
"
+
lastExpression
)
var
propertiesChoices;
if
(lastExpression)
{
try
{
return
this
.allPropertiesOf(
eval
(lastExpression))
}
catch
(er)
{
//
console.log("failed
to
eval"
+
lastExpression
+
"
for
tab
completion")
}
}
}
,
onKeyDown:
function
(evt)
{
if
(evt.getKeyCode()
==
Event.KEY_TAB)
{
var
cursor
=
this
.selectionRange[
0
];
var
lastChar
=
this
.textString.substring(cursor
-
1
,
cursor);
var
lastWordRange
=
this
.locale.selectWord(
this
.textString,
cursor
-
1
)
var
word
=
this
.textString.substring(lastWordRange[
0
],
lastWordRange[
1
]
+
1
)
if
(word)
{
var
lastWord
=
this
.textString.substring(lastWordRange[
0
],
cursor);
}
//
console.log("lastWordRange
"
+
lastWordRange);
//
console.log("lastWord
"
+
lastWord)
if
(cursor
>=
lastWordRange[
0
]
&&
lastWord
&&
(lastChar
!=
"\t"
)
&&
(lastChar
!=
"\n"
)
&&
!evt.isAltDown())
{
var
m
=
lastWord.match(
/([A-Za-z0-9]+)$/
)
if
(m)
{
lastWord
=
m[
1
];
}
var
fullReplace
=
this
.tabCompletionForLastWord(lastWord,
evt.isShiftDown());
//
console.log("fullReplace
"
+
fullReplace)
if
(fullReplace)
{
var
replace
=
fullReplace.substring(lastWord.length,
fullReplace.length);
}
;
//
console.log("lastWord
"
+
lastWord)
if
(replace)
{
this
.replaceSelectionfromKeyboard(replace);
this
.setSelectionRange(cursor,
cursor
+
replace.size());
}
else
{
//
do
nothing...
whait
for
more
typing
the
shell
makes
a
sound
a
this
point
}
}
else
{
this
.replaceSelectionfromKeyboard(
"\t"
);
}
evt.stop();
return
}
this
.tabReplaceListIndex
=
undefined
return
cop.proceed(evt)
}
,
}
);
= lastWordRange[0] && lastWord && (lastChar != \"\\t\") && (lastChar != \"\\n\") && !evt.isAltDown()) {\t\t\t\n\t\t\t\t\n\t\t\t\tvar m = lastWord.match(/([A-Za-z0-9]+)$/)\n\t\t\t\tif (m) {\n\t\t\t\t\tlastWord = m[1];\n\t\t\t\t}\n\t\t\t\tvar fullReplace = this.tabCompletionForLastWord(lastWord, evt.isShiftDown());\n\t\t\t\t// console.log(\"fullReplace \" + fullReplace)\n\t\t\t\tif (fullReplace) {\n\t\t\t\t\t\tvar replace = fullReplace.substring(lastWord.length, fullReplace.length);\n\t\t\t\t};\n\t\t\t\t// console.log(\"lastWord \" + lastWord)\n\t\t\t\tif (replace) {\n\t\t\t\t\tthis.replaceSelectionfromKeyboard(replace);\n\t\t\t\t\tthis.setSelectionRange(cursor, cursor + replace.size());\n\t\t\t\t} else {\n\t\t\t\t\t// do nothing... whait for more typing the shell makes a sound a this point \n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.replaceSelectionfromKeyboard(\"\\t\");\n\t\t\t}\n\t\t\tevt.stop();\n\t\t\treturn \n\t\t}\n\t\tthis.tabReplaceListIndex = undefined\n\t\treturn cop.proceed(evt)\n\t},\n\n});\n"]]>
118
true
true
2000000
0.5
= lastWordRange[0] && lastWord && (lastChar != \"\\t\") && (lastChar != \"\\n\") && !evt.isAltDown()) {\t\t\t\n\t\t\t\t\n\t\t\t\tvar m = lastWord.match(/([A-Za-z0-9]+)$/)\n\t\t\t\tif (m) {\n\t\t\t\t\tlastWord = m[1];\n\t\t\t\t}\n\t\t\t\tvar fullReplace = this.tabCompletionForLastWord(lastWord, evt.isShiftDown());\n\t\t\t\t// console.log(\"fullReplace \" + fullReplace)\n\t\t\t\tif (fullReplace) {\n\t\t\t\t\t\tvar replace = fullReplace.substring(lastWord.length, fullReplace.length);\n\t\t\t\t};\n\t\t\t\t// console.log(\"lastWord \" + lastWord)\n\t\t\t\tif (replace) {\n\t\t\t\t\tthis.replaceSelectionfromKeyboard(replace);\n\t\t\t\t\tthis.setSelectionRange(cursor, cursor + replace.size());\n\t\t\t\t} else {\n\t\t\t\t\t// do nothing... whait for more typing the shell makes a sound a this point \n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.replaceSelectionfromKeyboard(\"\\t\");\n\t\t\t}\n\t\t\tevt.stop();\n\t\t\treturn \n\t\t}\n\t\tthis.tabReplaceListIndex = undefined\n\t\treturn cop.proceed(evt)\n\t},\n\n});\n"]]>
true
true
0
0.1
1
true
true
20
null
true
true
true
true
0
0.1
1
true
true
Add
module
false
null
true
false
true
Load
all
false
null
true
false
true
LineNo
false
null
true
false
true
Refresh
false
null
true
false
true
Eval
on
false
null
true
false
true
Sort
false
null
true
false
true
View
as...
false
null
true
false
true
true
= lastWordRange[0] && lastWord && (lastChar != \"\\t\") && (lastChar != \"\\n\") && !evt.isAltDown()) {\t\t\t\n\t\t\t\t\n\t\t\t\tvar m = lastWord.match(/([A-Za-z0-9]+)$/)\n\t\t\t\tif (m) {\n\t\t\t\t\tlastWord = m[1];\n\t\t\t\t}\n\t\t\t\tvar fullReplace = this.tabCompletionForLastWord(lastWord, evt.isShiftDown());\n\t\t\t\t// console.log(\"fullReplace \" + fullReplace)\n\t\t\t\tif (fullReplace) {\n\t\t\t\t\t\tvar replace = fullReplace.substring(lastWord.length, fullReplace.length);\n\t\t\t\t};\n\t\t\t\t// console.log(\"lastWord \" + lastWord)\n\t\t\t\tif (replace) {\n\t\t\t\t\tthis.replaceSelectionfromKeyboard(replace);\n\t\t\t\t\tthis.setSelectionRange(cursor, cursor + replace.size());\n\t\t\t\t} else {\n\t\t\t\t\t// do nothing... whait for more typing the shell makes a sound a this point \n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.replaceSelectionfromKeyboard(\"\\t\");\n\t\t\t}\n\t\t\tevt.stop();\n\t\t\treturn \n\t\t}\n\t\tthis.tabReplaceListIndex = undefined\n\t\treturn cop.proceed(evt)\n\t},\n\n});\n"]]>
false
null
null
null
null
false
MorphTestCase
.
subclass
(
'ProperyCompletionMenuLayerTest'
,
{
setUp:
function
()
{
this
.sut
=
new
TextMorph(
new
Rectangle(
50
,
50
,
100
,
100
),
"foo."
)
this
.sut.setWithLayers([ProperyCompletionMenuLayer])
}
,
testShowPropertyCompletionMenuFor:
function
()
{
var
obj
=
{
foo:
function
()
{}
,
propA:
24
}
;
var
menu
=
this
.sut.showPropertyCompletionMenuFor(obj)
this
.assert(menu
instanceof
MenuMorph,
"is
no
menu"
)
}
,
testPropertyCompletionMenuItemsFor:
function
()
{
var
obj
=
{
foo:
function
()
{}
,
propA:
24
}
;
var
items
=
this
.sut.propertyCompletionMenuItemsFor(obj);
this
.assertEqual(items.size(),
2
,
"wrong
number
of
items"
);
}
,
}
)
7
null
null
null
Wiki
control
true
true
null
null
false
true
null
false
TestRunner
false
null
true
false
X
false
null
true
false
false
M
false
null
true
false
false
–
false
null
true
false
false
null
false
ProperyCompletionMenuLayerTest
(6ms)
false
false
true
false
true
0
false
603
null
-1
null
null
true
true
true
0
0.1
1
true
true
Run
TestCase
false
null
true
false
true
Run
All
TestCases
false
null
true
false
true
Refresh
false
null
true
false
true
null
Tests
run:
2
--
Tests
failed:
1
--
Time:
0.006s
null
1
ProperyCompletionMenuLayerTest.testPropertyCompletionMenuItemsFor
failed:
(wrong
number
of
items
(1
!=
2))
(undefined)
in
2
false
false
true
false
true
0
603.5
-1
null
null
true
true
true
0
0.1
1
true
true
true
false
null
null
null
null
false
null
object
to
look
in
1
filter
methods
and
props
1
obj
.
fo
29
//
null
78