Ticket #55 (new defect) — at Initial Version

Opened 13 years ago

Last modified 8 years ago

savannah: tab completion vs. spaces and escaping

Reported by: slavazanko Owned by:
Priority: major Milestone: 4.8.8
Component: mc-core Version: master
Keywords: Cc: ossi, egmont@…
Blocked By: Blocking:
Branch state: merged Votes for changeset:


Original: http://savannah.gnu.org/bugs/?18695

Submitted by:Egmont Koblinger <egmont>Submitted on:Fri 05 Jan 2007 01:07:06 PM UTC
Category:NoneSeverity:3 - Normal
Assigned to:NoneOpen/Closed:Open
Release:current (CVS or snapshot)Operating System:GNU/Linux


Fri 05 Jan 2007 01:53:04 PM UTC, comment #1:

Sounds familiar...

	Pavel Tsekov <ptsekov>
Project Administrator
Fri 05 Jan 2007 01:07:06 PM UTC, original submission:

Tab completion (Alt+Tab or Escape+Tab, I'll refer to these simply 
as Tab) works exactly the same way in the command line and in 
dialog boxes (such as copy/move file). The function complete() in 
src/complete.c only takes a widget as its input and performs the 

This approach is wrong, since the dialog boxes and the command line 
have different word splitting and escaping rules, they cannot be 
treated the same way. Currently they both have bugs. (I found these 
while trying to tidy up my mp3s, where lots of file and directory 
names contain spaces.)

In the file copy and similar dialogs, filenames are typed as pure 
strings without any kind of escaping, and a text entry only takes 
one filename. However, splitting at spaces is still performed. 
Suppose I have a directory named "/tmp/a bcde". I press F5/F6 on a 
file, and type "/tmp/a" and then Tab, it completes to "/tmp/a 
bcde". This is okay. But if I type "/tmp/a bc" and press Tab now, 
it completes to the files in the current directory whose name 
begins with "bc", due to the splitting at the space. Similarly, if 
I already have "/tmp/a bcde/" in the edit field, it won't complete 
to subdirectories or files of this directory. In this case the 
whole content of the field should be treated as one, not being 
split at spaces.

In the command line, splitting at spaces is okay, however, we would 
need some escaping and unescaping too, which doesn't happen. (Note: 
Esc followed by Enter correctly escapes the filename when it puts 
it into the cmdline.) Example: type "ls /tmp/a" and then Tab, 
you'll have "ls /tmp/a bcdefgh/" in the command line, which clearly 
won't list the contents of that directory due to the unescaped 
space character. Another example: type "ls /tmp/a\ b" and hit Tab, 
it won't complete to "ls /tmp/a\ bcde/", but it should.

I understand that it is beyond the scope of mc to perform a full 
shell syntax parsing (single and double quotes, nesting them etc.). 
This doesn't even happen when Esc Enter is pressed: backslashes are 
inserted even between quotes, but I'm fine with that. However, mc 
should produce proper escaping when inserting spaces or other 
special chars as a result of completion, and should be able to 
parse the backslash escaping it created (or the user typed) when 
doing further completion.

Obviously the current design of the complete() function to take 
only a widget is not okay (unless there's some room in the widget 
to store splitting and escaping rules). There are two main possible 
solutions I can see, but probably they'd eventually lead to 
basically the same code.

1) modify complete() so that it receives information on word 
splitting and escaping, so that it becomes more complex and 
probably more buggy and harder to maintain, but solves everything 
we need.

2) remove the word splitting code from complete(), so that it 
becomes simpler and perfect for the file copy/move widgets. 
Slightly modify its interface to take and return string and cursor 
positions instead of widget. Then make the command line editor 
split at unescaped spaces, unescape the resulted word, call 
complete() on this temporary string, escape the result of 
completion and put back in the command line.

Finally, we should check how the internal "cd" command handles its 
arguments. Currently it seems to do a lot of heuristics. For 
example, if I type "cd a\\\\b" (four backslashes) then it tries to 
change to the directory called "a\\\\b" (four backslashes) but if 
there's no such directory, it changes to "a\\b" (two backslashes). 
This seems to be terrible, and leads to bugs, e.g. if the cursor is 
on "a\\b" and I type "cd " followed by a Tab, I get the command "cd 
a\\\\b" and hence it'll change to "a\\\\b" which is not the desired 
directory. I'd remove all the heuristics and perform the usual 
command line unescaping, just as if it was an external command. 
Note: See TracTickets for help on using tickets.