Tab completion

Everything about development and the OpenMW source code.
Locked
User avatar
lgromanowski
Site Admin
Posts: 1193
Joined: 05 Aug 2011, 22:21
Location: Wroclaw, Poland
Contact:

Tab completion

Post by lgromanowski » 13 Aug 2011, 21:10

mach1723 wrote: I am sure most developers here are familiar with the shell concept of command completion(http://en.wikipedia.org/wiki/Tab_completion), anyway I am opening this thread to report on the progress of this feature.

My intended goal with this feature is to have console commands be auto-completed at the press of a tab key.

Now for the progress report, the only progress I have as of now is finding the console code and adding a function prototype.

http://github.com/Mach1723/openmw/tree/tab_completion
The branch ^_^
ap0 wrote: Realy nice idea !
next step : zsh in my morrowind o/
mach1723 wrote: https://github.com/Mach1723/openmw/comm ... 8c806b720b

I have made some nice progress on this, I think all the keyword matching bits in "components/compiler/extensions.cpp:Extensions::searchPartialKeyword" should work right now, but I can't call "searchPartialKeyword" from console.cpp, I think I need to move the Console::match() function to somewhere higher up in the class structure.

Here are my current compile errors:

Code: Select all

[ 49%] Building CXX object apps/openmw/CMakeFiles/openmw.dir/mwgui/console.cpp.o
/home/*/code/openmw/apps/openmw/mwgui/console.cpp: In member function â??std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > MWGui::Console::match(const std::string&)â??:
/home/*/code/openmw/apps/openmw/mwgui/console.cpp:98: error: invalid use of incomplete type â??const struct Compiler::Extensionsâ??
/home/*/code/openmw/./components/compiler/scanner.hpp:13: error: forward declaration of â??const struct Compiler::Extensionsâ??
Star-Demon wrote: YES!

You are AWESOME for doing this.
Zini wrote: This is a rather problematic feature because of the extremely eccentric syntax of the MW scripting language.
The best we can reasonably hope for is getting a complete list of all valid instructions and identifiers and do the matching against it.

I suggest you leave getting this list to me. With your current implementation you are missing quite a few bits. I should be able to get a branch with this function ready today (unless something unexpected comes up).

Please consider, that MW identifier can contain spaces. These identifiers must be put in quotes ("Some Name"), but the list you will be getting from my function will not contain the quotes. Also consider, that an escaped quotation mark \" is not seen as beginning/ending an identifier.
Furthermore building the list will be quite expensive (performance wise). You should call the function once on the first tab-completion and the buffer the results.
Benbat wrote: At this point, wouldn't it be easier to use GNU readline for the command line ?
Zini wrote: Done. Please merge my tab_completion branch into your branch. Maybe you want to undo your last two commits, because they are mostly redundant now.

Oh, and another important point: Remember that the MW console is case insensitive.
mach1723 wrote: I have pushed the first chunklet of tab completion code now, at the moment it only matches the part of the input that would be the command(like 'coc'), next thing to do is splitting up the input String(space-delimited) so you could tab match a 'coc Balmor' style string.
Zini wrote: Haven't heard anything from you. Are you still on the task? As far as I understand it you are nearly done, right?
mach1723 wrote:
Zini wrote:Haven't heard anything from you. Are you still on the task? As far as I understand it you are nearly done, right?
It is nearly done, I have just been busy(and procrastinating), I will see if I can finish it by tommorow, if I recall all that's left to do is tab-complete the last space-seperated element of an input.
mach1723 wrote: After a refactor of what I now consider to be ugly tab completion code, I get the strings for matching nicely and just need to match these strings now and then tab completion should be done.

Image

https://github.com/Mach1723/openmw/comm ... d42e296e61
mach1723 wrote: Tab completion is finished!(barring obvious errors, code cleanup and improvement :mrgreen: ), going to check it merges with current master branch and then submit a pull request to zini.

EDIT:
It seems to merge and build fine, can't get openmw to run because of:

Code: Select all

ERROR: boost::filesystem::basic_directory_iterator constructor: No such file or directory: "/home/rzach/code/openmw/build/data"
I have the data dir pointing to the right path in openmw.cfg.

Here's the pull request link: https://github.com/zinnschlag/openmw/pull/9
Zini wrote: The master branch contains some changes related to path handling. Works well here, so I am not sure what is going wrong. Maybe Peppe can assist you (he wrote the path code).
Zini wrote: If I understand the code right when pressing the tab key it is supposed to check the last entered word against the list of valid keywords and names. Each keyword/name which contains this word is then printed to the console.

Here is what I experienced: After pressing tab OpenMW hung for several seconds. Then most of the printed list had scrolled out of the console (which can only hold a limited number of lines). The current solution does not scale well enough.

I would like to propose the following changes:

1. Instead of checking if the word is part of a valid identifier, check if it is the beginning of a valid identifier. That should cut down the number of matching candidates considerably.

2. Don't print anything to the console at all. Later (post 1.0) we might decide to implement a small scrollable popup-window (optional), that lists all candidates if there is more than one.
For now I suggest to just complete as much as you can.

Example: If these were the valid keywords:

item_1
item_2_a
item_2_b

after entering i and pressing tab the input field should contain item_. If the user enters a 2 and presses tab again, _ would be appended.
mach1723 wrote:
Zini wrote:If I understand the code right when pressing the tab key it is supposed to check the last entered word against the list of valid keywords and names. Each keyword/name which contains this word is then printed to the console.

Here is what I experienced: After pressing tab OpenMW hung for several seconds. Then most of the printed list had scrolled out of the console (which can only hold a limited number of lines). The current solution does not scale well enough.

I would like to propose the following changes:

1. Instead of checking if the word is part of a valid identifier, check if it is the beginning of a valid identifier. That should cut down the number of matching candidates considerably.

2. Don't print anything to the console at all. Later (post 1.0) we might decide to implement a small scrollable popup-window (optional), that lists all candidates if there is more than one.
For now I suggest to just complete as much as you can.

Example: If these were the valid keywords:

item_1
item_2_a
item_2_b

after entering i and pressing tab the input field should contain item_. If the user enters a 2 and presses tab again, _ would be appended.
Ok I have been trying to change the code to do it this way and have been failing, because my code is still pretty bad and hard to modify, so I am reading up on parsing and tokenization(which has already given me ideas on how to do this much better than I am right now).

Hopefully I will have some code soon.
Zini wrote: Your still on it? It just occurred to me, that this feature is almost trivial to implement, if you re-use parts of the compiler component, which already does most of the hard work. The most important classes here are Compiler::Scanner and Compiler::Parser. I can give you some more hints, if you are interested.
best regards,
Lukasz

Locked