didn't play a lot with resulting code, mostly reviewed it
note: dir "c:\\Programs Files\\"\<tab\> should circle among the subdirectories... current code doesn't
also dir c\<tab\> (with a first file displayed), then reduce size of console window to be shorter than input line, will display input on line after the prompt
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101938
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + }
> + lstrcatW(searchstr, L"*");
> + TRACE("New search: [%s]\n", wine_dbgstr_w(searchstr));
> +
> + sc.isDirSearch = IsDirectoryOperation(inputBuffer, inputBufferLength);
> + }
> +
> + FindNextMatchingDirectoryEntry(searchstr, &sc);
> +
> + if (sc.haveSearchResult) {
> + /* If this is our first time through here for this search, we need to find the insert position
> + * for the results. Note that this is very likely not the same location as the search position.
> + */
> + if (!sc.insertPos) {
> + /* If user entered a backslash after quotes, remove the quotes. */
> + if (curPos > 2 && inputBuffer[curPos-2] == L'\"' && inputBuffer[curPos-1] == L'\\') {
I think quote handling is not done as it should
from what I see on native: quotes are added when generated word does contain characters that would need to be escaped (eg ' ', but didn't check all the others)
need quote is an attribute of current filename (ie they are removed when the new (partial) matching file no longer needs them) ; so quotes shouldn't be part of the SEARCH_CONTEXT, but only used for display (basically: go to beg of word; if needs quotes, print quote; print (partial) word; print ending quotes (if needed)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101937
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + } else {
> + cc = len;
> + while (cc > 0 && inputBuffer[cc] != L' ' && inputBuffer[cc] != L'\t') {
> + cc--;
> + }
> + }
> + }
> +
> + if (cc != sc->searchPos || inputBuffer[sc->searchPos] == L'\\') {
> + cc++;
> + }
> +
> + sc->insertPos = cc;
> +}
> +
> +static void FindNextMatchingDirectoryEntry(const WCHAR *searchstr, PSEARCH_CONTEXT sc)
a couple of comments here:
* actually, this is not exactly how native (Win10) behaves: native captures the list of matching files at first tab usage, and doesn't update that list if eg. a file matching the pattern is added
* the way done here is a bit more dynamic (as it would capture file creation/deletion), and I don't think it matters much from a user perspective
the main thing I'm concerned about is that code to handle backwards shift-tab will be a bit more painful, and also the restart case (when the matched file is deleted)
I think code would be simpler and more readable when storing the list of files, but I won't block on that. I let you pick up your favorite one.
if you keep current logic, it seems to me that:
* \-\>hadOneMatch is only used locally, and should rather be a local variable
* \-\>hasSearchResult would make more sense be return value from this function
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101936
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + int lastStartQuote;
> + int searchPos;
> + int insertPos;
> +} SEARCH_CONTEXT, *PSEARCH_CONTEXT;
> +
> +
> +static BOOL IsDirectoryOperation(const WCHAR *inputBuffer, const ULONG inputBufferLength)
> +{
> + int cc = 0;
> + BOOL ret = FALSE;
> +
> + while (cc < inputBufferLength && (inputBuffer[cc] == L' ' || inputBuffer[cc] == L'\t')) {
> + cc++;
> + }
> +
> + if ((cc + 2 < inputBufferLength && (inputBuffer[cc + 2] == L' ' || inputBuffer[cc + 2] == L'\t')) &&
questionning about finding the end of first word algorithm
native behavior is very inconsistent
`>cd\windows`
(note that there's no space between "cd" and "\\"). is supported as command, but tab-completion on "windows" doesn't work
**but**
`>cd"\windows"`
(idem no space, but with quotes). isn't supported as a command, but tab-completion does work
since this relates to corner cases of user interaction, I'm not sure we want to mimic all these broken behaviors
for consistency I'd rather suggest that you use `WCMD_parameter` to split the edit line into separate words you can then work upon
this at least will provide consistency across all the code
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101935
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + }
> + oldCurPos = curPos;
> + curPos = 0;
> + while (curPos < len &&
> + inputBuffer[curPos] != L'\t' &&
> + inputBuffer[curPos] != L'\x1B'
> + ) {
> +
> + curPos++;
> + }
> + /* curPos is often numRead - 1, but not always, as in the case where history is retrieved
> + * and then user backspaces to somewhere mid-string and then hits Tab.
> + */
> + TRACE("numRead: %lu, curPos: %u\n", *numRead, curPos);
> +
> + switch (inputBuffer[curPos]) {
looks to be that curPos can be \> \*numRead, hence reading garbage in that case
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101933
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + /* curPos is often numRead - 1, but not always, as in the case where history is retrieved
> + * and then user backspaces to somewhere mid-string and then hits Tab.
> + */
> + TRACE("numRead: %lu, curPos: %u\n", *numRead, curPos);
> +
> + switch (inputBuffer[curPos]) {
> + case L'\t':
> + TRACE("TAB: [%s]\n", wine_dbgstr_w(inputBuffer));
> + inputBuffer[curPos] = L'\0';
> + len = curPos;
> + sc.haveSearchResult = FALSE;
> +
> + /* See if we need to reset an existing search. */
> + if (sc.hSearch != INVALID_HANDLE_VALUE) {
> + /* If tab key was hit at a different location than last time */
> + if (curPos != oldCurPos) {
that's not sufficient, you have also to compare that inputbuffer up to current pos hasn't changed since previous call
(eg directory with za, za2 and zb zb2 files... circle twice from "za", replace "za" by "zb" and circle with tab...)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101932
eric pouech (@epo) commented about programs/cmd/lineedit.c:
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
> + */
> +
> +#define WIN32_LEAN_AND_MEAN
> +
> +#include "wcmd.h"
> +#include "wine/debug.h"
> +
> +WINE_DEFAULT_DEBUG_CHANNEL(cmd);
> +
> +typedef struct _SEARCH_CONTEXT
> +{
> + HANDLE hSearch;
in new code, we tend not to use camel case for function names or fields but rather snake case
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_101930