add command completion to console

This commit is contained in:
Eduardo Bart 2011-11-01 16:32:48 -02:00
parent 59017205b0
commit d2e8e1d774
15 changed files with 96 additions and 20 deletions

View File

@ -30,6 +30,57 @@ local function navigateCommand(step)
end end
end end
local function completeCommand()
local cursorPos = commandLineEdit:getCursorPos()
if cursorPos == 0 then return end
local commandBegin = string.sub(commandLineEdit:getText(), 1, cursorPos)
local possibleCommands = {}
-- create a list containing all globals
local allVars = table.copy(_G)
table.merge(allVars, commandEnv)
-- match commands
for k,v in pairs(allVars) do
if string.sub(k, 1, cursorPos) == commandBegin then
table.insert(possibleCommands, k)
end
end
-- complete command with one match
if #possibleCommands == 1 then
commandLineEdit:setText(possibleCommands[1])
-- show command matches
elseif #possibleCommands > 0 then
print('>> ' .. commandBegin)
-- expand command
local expandedComplete = commandBegin
local done = false
while not done do
cursorPos = #commandBegin+1
if #possibleCommands[1] < cursorPos then
break
end
expandedComplete = commandBegin .. string.sub(possibleCommands[1], cursorPos, cursorPos)
for i,v in ipairs(possibleCommands) do
if string.sub(v, 1, #expandedComplete) ~= expandedComplete then
done = true
end
end
if not done then
commandBegin = expandedComplete
end
end
commandLineEdit:setText(commandBegin)
for i,v in ipairs(possibleCommands) do
print(v)
end
end
end
local function onKeyPress(widget, keyCode, keyChar, keyboardModifiers) local function onKeyPress(widget, keyCode, keyChar, keyboardModifiers)
if keyboardModifiers == KeyboardNoModifier then if keyboardModifiers == KeyboardNoModifier then
-- execute current command -- execute current command
@ -46,6 +97,10 @@ local function onKeyPress(widget, keyCode, keyChar, keyboardModifiers)
elseif keyCode == KeyDown then elseif keyCode == KeyDown then
navigateCommand(-1) navigateCommand(-1)
return true return true
-- complete command
elseif keyCode == KeyTab then
completeCommand()
return true
end end
end end
return false return false
@ -102,6 +157,18 @@ function Console.addLine(text, color)
end end
function Console.executeCommand(command) function Console.executeCommand(command)
-- detect and convert commands with simple syntax
local realCommand
if commandEnv[command] then
if type(commandEnv[command]) == "function" then
realCommand = command .. '()'
else
realCommand = 'print(' .. command .. ')'
end
else
realCommand = command
end
-- reset current history index -- reset current history index
currentHistoryIndex = 0 currentHistoryIndex = 0
@ -112,7 +179,7 @@ function Console.executeCommand(command)
Console.addLine(">> " .. command, "#ffffff") Console.addLine(">> " .. command, "#ffffff")
-- load command buffer -- load command buffer
local func, err = loadstring(command, "@") local func, err = loadstring(realCommand, "@")
-- check for syntax errors -- check for syntax errors
if not func then if not func then

View File

@ -33,4 +33,5 @@ RectPanel
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: commandSymbolLabel.right anchors.left: commandSymbolLabel.right
anchors.right: parent.right anchors.right: parent.right
margin.left: 5
font: terminus-14px-bold font: terminus-14px-bold

View File

@ -10,6 +10,8 @@ Module
- core_ui - core_ui
onLoad: | onLoad: |
require 'ext/table'
require 'ext/string'
require 'constants' require 'constants'
require 'util' require 'util'
require 'widget' require 'widget'

View File

@ -19,7 +19,7 @@ function MessageBox.create(title, text, flags)
label:resizeToText() label:resizeToText()
-- set window size based on label size -- set window size based on label size
window:setWidth(label:getWidth() + 48) window:setWidth(math.max(label:getWidth() + 48, 120))
window:setHeight(label:getHeight() + 64) window:setHeight(label:getHeight() + 64)
window:updateParentLayout() window:updateParentLayout()

View File

@ -24,3 +24,9 @@ function connect(object, signalsAndSlots)
end end
end end
end end
function dumpWidgets()
for i=1,UI.root:getChildCount() do
print(UI.root:getChildByIndex(i):getId())
end
end

View File

@ -8,9 +8,9 @@ FlatPanel < Panel
TopPanel < Panel TopPanel < Panel
height: 34 height: 34
border-image: image:
source: /core_ui/images/top_panel.png source: /core_ui/images/top_panel.png
border-bottom: 3 repeated: true
RoundedPanel < Panel RoundedPanel < Panel
background-color: #ffffffdd background-color: #ffffffdd

View File

@ -14,4 +14,5 @@ Panel
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin.top: 1
focusable: false focusable: false

View File

@ -34,17 +34,6 @@ TopPanel
margin.top: 3 margin.top: 3
margin.right: 6 margin.right: 6
UIWidget
size: 16 16
image: /core_ui/icons/exit.png
anchors.centerIn: parent
phantom: true
TopButton
anchors.top: prev.top
anchors.right: prev.left
margin.right: 6
UIWidget UIWidget
size: 16 16 size: 16 16
image: /core_ui/icons/logout.png image: /core_ui/icons/logout.png

View File

@ -183,9 +183,11 @@ void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords,
if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty()) if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty())
return; return;
bool mustStopDrawing = false;
if(!m_drawing) { if(!m_drawing) {
bindTexture(texture); bindTexture(texture);
startDrawing(); startDrawing();
mustStopDrawing = true;
} }
// render many repeated texture rects // render many repeated texture rects
@ -212,7 +214,7 @@ void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords,
} }
} }
if(!m_drawing) if(mustStopDrawing)
stopDrawing(); stopDrawing();
} }

View File

@ -30,6 +30,7 @@
Image::Image() Image::Image()
{ {
m_fixedRatio = false; m_fixedRatio = false;
m_repeated = false;
} }
void Image::loadFromOTML(const OTMLNodePtr& imageNode) void Image::loadFromOTML(const OTMLNodePtr& imageNode)
@ -37,13 +38,14 @@ void Image::loadFromOTML(const OTMLNodePtr& imageNode)
// load configs from otml node // load configs from otml node
std::string source = imageNode->hasValue() ? imageNode->value() : imageNode->valueAt("source"); std::string source = imageNode->hasValue() ? imageNode->value() : imageNode->valueAt("source");
bool smooth = imageNode->valueAt("smooth", false); bool smooth = imageNode->valueAt("smooth", false);
m_textureCoords = imageNode->valueAt("coords", Rect());
m_fixedRatio = imageNode->valueAt("fixed ratio", false); m_fixedRatio = imageNode->valueAt("fixed ratio", false);
m_repeated = imageNode->valueAt("repeated", false);
// load texture // load texture
m_texture = g_textures.getTexture(source); m_texture = g_textures.getTexture(source);
if(!m_texture) if(!m_texture)
throw OTMLException(imageNode, "could not load image texture"); throw OTMLException(imageNode, "could not load image texture");
m_textureCoords = imageNode->valueAt("coords", Rect(Point(0,0),m_texture->getSize()));
// enable texture bilinear filter // enable texture bilinear filter
if(smooth) if(smooth)
@ -65,6 +67,9 @@ void Image::draw(const Rect& screenCoords)
g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize));
} else { } else {
if(m_repeated)
g_graphics.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords);
else
g_graphics.drawTexturedRect(screenCoords, m_texture, m_textureCoords); g_graphics.drawTexturedRect(screenCoords, m_texture, m_textureCoords);
} }
} }

View File

@ -40,6 +40,7 @@ protected:
TexturePtr m_texture; TexturePtr m_texture;
Rect m_textureCoords; Rect m_textureCoords;
bool m_fixedRatio; bool m_fixedRatio;
bool m_repeated;
}; };
#endif #endif

View File

@ -108,6 +108,7 @@ void LuaInterface::registerFunctions()
g_lua.bindClassMemberFunction<UILineEdit>("getText", &UILineEdit::getText); g_lua.bindClassMemberFunction<UILineEdit>("getText", &UILineEdit::getText);
g_lua.bindClassMemberFunction<UILineEdit>("setText", &UILineEdit::setText); g_lua.bindClassMemberFunction<UILineEdit>("setText", &UILineEdit::setText);
g_lua.bindClassMemberFunction<UILineEdit>("clearText", &UILineEdit::clearText); g_lua.bindClassMemberFunction<UILineEdit>("clearText", &UILineEdit::clearText);
g_lua.bindClassMemberFunction<UILineEdit>("getCursorPos", &UILineEdit::getCursorPos);
// UIWindow // UIWindow
g_lua.registerClass<UIWindow, UIWidget>(); g_lua.registerClass<UIWindow, UIWidget>();

View File

@ -92,7 +92,7 @@ void push_luavalue(const std::string& str)
bool luavalue_cast(int index, std::string& str) bool luavalue_cast(int index, std::string& str)
{ {
str = g_lua.toString(index); str = g_lua.toString(index);
if(str.empty() && !g_lua.isString(index)) if(str.empty() && g_lua.isString(index) && !g_lua.isNil())
return false; return false;
return true; return true;
} }

View File

@ -50,6 +50,7 @@ public:
std::string getText() const { return m_text; } std::string getText() const { return m_text; }
std::string getDisplayedText(); std::string getDisplayedText();
int getTextPos(Point pos); int getTextPos(Point pos);
int getCursorPos() const { return m_cursorPos; }
protected: protected:
virtual void onStyleApply(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);

View File

@ -105,7 +105,7 @@ void UIWidget::render()
// debug draw box // debug draw box
//g_graphics.bindColor(Fw::green); //g_graphics.bindColor(Fw::green);
//g_graphics.drawBoundingRect(child->getRect()); //g_graphics.drawBoundingRect(child->getRect());
//g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Color::red); //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red);
g_graphics.setOpacity(oldOpacity); g_graphics.setOpacity(oldOpacity);
} }