Open ZachHaber opened 10 months ago
Autocomplete really is only meant to autocomplete the currently in progress word (if a character other than space is the last part of the in progress string, then that word needs autocompleted, but if a space is the last character then the autocompletion should be suggesting entirely new words to add at the end). The game sends you an array of the previous arguments already typed out so that you can have different autocomplete options sent based on what has already been typed.
However, going through and trying to make an example script to show you how it's expected to be done, I noticed some inconsistent behavior in how it sends that info to the your autocomplete function.
e.g. run autocomplete.js nonunique
(with no space at the end, nonunique is the word in progress) sends the same thing to the autocomplete function as if run autocomplete.js nonunique
(with a space at the end, the empty next word is what is being autocompleted).
So I'll keep this issue open to smooth out that inconsistency and then provide a reliable way to handle the autocompletion based on arguments already typed out
e.g.
run autocomplete.js nonunique
(with no space at the end, nonunique is the word in progress) sends the same thing to the autocomplete function as ifrun autocomplete.js nonunique
(with a space at the end, the empty next word is what is being autocompleted).
I had the same confusion before, as the player can hardly control either it is now to autocomplete the previous incomplete arg or to suggest candicates for the next one.
Here is an instance of autocomplete()
I used in a script, which uses args to control which Hash Upgrade to buy:
export function autocomplete(data, arrArgs) {
let arrHashUpgrades = Object.keys(objHashUpgrades)
let arrACargs = arrArgs.filter((arg) => !['-a'].includes(arg))
if (arrACargs.length === 0 || !arrHashUpgrades.includes(arrACargs[0])) {
return arrHashUpgrades
}
let upgradeArg = arrACargs[0]
if (upgradeArg === 'serverSecurity' || upgradeArg === 'serverMoney') {
return data.servers.filter((host) => !(fIsHS(host) || fIsSPS(host) || host === 'home'))
}
if (upgradeArg === 'companyFavor') {
return Object.keys(objCompanies)
}
return []
}
'-a' is excluded first as it is a flag to do some control. The purpose of all the rest logic is to make a judgement:
arrHashUpgrades
which contains argument-style Upgrade names.It generally works well, but for some rare cases it does not function as intended:
Note that there is a space padding the first arg serverSe
, indicates the first arg is done and I'm going to enter the second one. In this case I hope it will recognize the first arg as an forementioned "Otherwise" and provides nothing rather than arrHashUpgrades
A solution I can think of is: when the player hits tab and the string already inputted ends with space, push an empty string '' into the array containing args. The autocomplete()
will receive ['serverSe', '']
instead of ['serverSe']
and then can make a judgement.
The args
passed into the autocomplete
function appear to be inconsistent as well.
./script.js "test multi"|
+ tab gives ['test multi']
as a result
./script.js "test multi" |
+ tab gives `['test','multi'].
A solution I can think of is: when the player hits tab and the string already inputted ends with space, push an empty string '' into the array containing args. The
autocomplete()
will receive['serverSe', '']
instead of['serverSe']
and then can make a judgement.
I second that idea, so far it's the best one I can think of. Though I don't know how much it would break scripts.
The other idea I had was to add in a rawArgs
string property to both the autocomplete's data
arg as well as ns
so that people who want to can do more advanced parsing. The use-case I have in this would be solved by simply being able to check if the rawArgs
ends with a space. You could also give a little more detail for advanced parsing by adding in a cursorPosition
property that is the index the cursor is at in the rawArgs
string.
Also, for what its worth, this is my current autocomplete/flags setup with multi-word autcomplete, type inferences, shortcuts for flags (e.g. '-b'), and semi-validated options for flags as well: https://gist.github.com/ZachHaber/35762ae151fa5ee14348b24a8ff27ec0
There are still some issues with it, like ensuring that non-boolean options have to have a value after them before it will suggest further flags. For the most part, I've worked around the issue mentioned here by slicing the multi-word options strings based on the current multi-word string to allow autcomplete based off of the "current" word.
Multi-word autocomplete entries don't work well. If you have fairly unique entries, it'll mostly work. You still have to be aware that you need to add
"
around the options you return from theautocomplete
function, otherwise it won't autocomplete with quotes - which makes them separate arguments.If you have options that differ only after the first word, then the whole thing just fails as-is - even with quotes.
For example, use this as the autocomplete, and attempt to autocomplete "nonunique second word":
You'll get to
"nonunique se
and it will no-longer register any autocomplete options!If you then add
'seriously'
to the list of options (['"unique first"', '"nonunique second word"', '"nonunique sea word"', 'seriously']
), then it would autocomplete to"nonunique seriously
from"nonunique se
The only way around this is to do a ton of parsing in the autocomplete function to try and figure out what already exists, and then only return the next parts of matching options, and as was mentioned in #522, it's rather complex to try and figure out what is already set and what isn't.
Version: v2.5.2 (c6141f2ad)
I've already written myself a wrapper to deal with this issue (and a few more), but I just wanted to bring it to light, since I couldn't find a bug that dealt with this particular part of the autocomplete.
For reference: this came up as I was trying to add autocomplete for contract types.