-
Notifications
You must be signed in to change notification settings - Fork 123
kdb-complete minor improvements #1310
Changes from 2 commits
9373eaa
b10fd12
efdd4ba
5066db7
4a55d43
fc5cb51
fdc3c1d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,12 +24,11 @@ CompleteCommand::CompleteCommand () | |
{ | ||
} | ||
|
||
/* | ||
* McCabe complexity of 11, 1 caused by verbose switch so actually its ok | ||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please document what happens without arguments. Also fix SYNOPSIS There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. without arguments is like calling kdb complete "" (basically that means show me every possible completion if i haven't typed anything yet, which will be every possibility so namespaces, keys (expanded to nodes) and mountpoints). I'll document it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
int CompleteCommand::execute (const Cmdline & cl) | ||
{ | ||
if (cl.arguments.size () != 1) | ||
{ | ||
throw invalid_argument ("wrong number of arguments, 1 needed"); | ||
} | ||
if (cl.maxDepth <= cl.minDepth) | ||
{ | ||
throw invalid_argument ("the maximum depth has to be larger than the minimum depth"); | ||
|
@@ -49,10 +48,15 @@ int CompleteCommand::execute (const Cmdline & cl) | |
cout.unsetf (ios_base::skipws); | ||
} | ||
|
||
// Determine the actual root key, as for completion purpose originalRoot may not exist | ||
// For namespace completion, we get all available keys via / as the actual root and filter via the argument | ||
const bool hasArgument = cl.arguments.size () > 0; | ||
const string originalInput = hasArgument ? cl.arguments[cl.arguments.size () - 1] : ""; | ||
const Key originalUnprocessedKey (originalInput, KEY_END); | ||
KDB kdb; | ||
const Key originalRoot = cl.createKey (cl.arguments.size () - 1); | ||
Key root = originalRoot; | ||
// Determine the actual root key, as for completion purpose originalRoot may not exist | ||
// Maybe we want to complete an initial namespace, in that case bookmark expansion checks done by cl.createKey are useless | ||
const Key originalRoot = originalUnprocessedKey.isValid () ? cl.createKey (cl.arguments.size () - 1) : originalUnprocessedKey; | ||
Key root = originalUnprocessedKey.isValid () ? originalRoot : Key ("/", KEY_END); | ||
KeySet ks; | ||
printWarnings (cerr, root); | ||
|
||
|
@@ -71,7 +75,7 @@ int CompleteCommand::execute (const Cmdline & cl) | |
// Now analyze the completion possibilities and print the results | ||
addMountpoints (ks, root); | ||
KeySet virtualKeys; | ||
printResult (originalRoot, root, analyze (ks, root, virtualKeys, cl), virtualKeys, cl); | ||
printResults (originalInput, originalRoot, root, analyze (ks, root, virtualKeys, cl), virtualKeys, cl); | ||
printWarnings (cerr, root); | ||
|
||
return 0; | ||
|
@@ -102,6 +106,17 @@ void CompleteCommand::addMountpoints (KeySet & ks, const Key root) | |
printWarnings (cerr, mountpointPath); | ||
} | ||
|
||
void CompleteCommand::addNamespaces (map<Key, pair<int, int>> & hierarchy) | ||
{ | ||
// Currently assumed to be fixed, and they are on level 0 | ||
const string namespaces[] = { "spec/", "proc/", "dir/", "user/", "system/" }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be great if we do not need to hardcode it or at least get a warning/error if we add an namespace. See To get all namespaces might be a good addition in the c++ binding (or at least in libtools). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there a way to get all available namespaces, because i haven't found any? They only thing i've found are integer constants e.g. KEY_NS_DIR, but those can't really be translated back to a name like "dir/" right? keyGetNamespace can be used to get a key's namespace yes, but what if there is nothing in e.g. proc yet, then even by iterating all keys and checking their namespace, we wouldn't be able to get all the available namespaces. So if i add such method to the c++ bindings (though it might be even better to have such method on a lower level as its not really binding specific) wouldn't it end up returning a hardcoded list of namespaces? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it will return a hard-coded list of namespaces. But the function should return a warning if we choose to extend the namespaces. It is explained in the docu of But you are right, it might be overkill to add such trivial code in the binding or libtools. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok i did something which would detect both outdated namespaces and missing namespaces, however, i'm not really happy with the check being executed each single time and probably ruining completions at some point (when a namespace change happens). I though about only displaying it when using -v or -d, but then it would probably take a while to notice that kdb complete is not up to date. |
||
for (const auto ns : namespaces) | ||
{ | ||
Key nsKey (ns, KEY_END); | ||
hierarchy[nsKey] = pair<int, int> (1, 0); | ||
} | ||
} | ||
|
||
/* | ||
* McCabe complexity of 13, 3 caused by debug switches so actually its ok | ||
*/ | ||
|
@@ -111,6 +126,7 @@ const map<Key, pair<int, int>> CompleteCommand::analyze (const KeySet & ks, cons | |
stack<Key> keyStack; | ||
Key parent; | ||
Key last; | ||
addNamespaces (hierarchy); | ||
|
||
ks.rewind (); | ||
if (!(ks.next ())) | ||
|
@@ -184,16 +200,17 @@ void CompleteCommand::increaseCount (map<Key, pair<int, int>> & hierarchy, const | |
} | ||
|
||
/* | ||
* McCabe complexity of 12, 2 caused by debug/verbose switches so actually its ok | ||
* McCabe complexity of 11, 3 caused by verbose switch so actually its ok | ||
*/ | ||
void CompleteCommand::printResult (const Key originalRoot, const Key root, const map<Key, pair<int, int>> & hierarchy, | ||
const KeySet & virtualKeys, const Cmdline & cl) | ||
void CompleteCommand::printResults (const string originalInput, const Key originalRoot, const Key root, | ||
const map<Key, pair<int, int>> & hierarchy, const KeySet & virtualKeys, const Cmdline & cl) | ||
{ | ||
const function<bool(string)> filterPredicate = determineFilterPredicate (originalRoot, root); | ||
const function<bool(string)> filterPredicate = determineFilterPredicate (originalInput, originalRoot, root); | ||
|
||
// Adjust the output offset, in case the given string exists in the hierarchy but not in the original ks | ||
// or for namespace completion | ||
const bool limitMaxDepth = cl.maxDepth != numeric_limits<int>::max (); | ||
const int offset = originalRoot != root && virtualKeys.lookup (originalRoot); | ||
const int offset = originalRoot != root && virtualKeys.lookup (originalRoot) ? 1 : (originalRoot.getFullName ().empty () ? -1 : 0); | ||
const int minDepth = cl.minDepth + offset; | ||
const int maxDepth = limitMaxDepth ? cl.maxDepth + offset : cl.maxDepth; | ||
if (cl.verbose) | ||
|
@@ -210,35 +227,49 @@ void CompleteCommand::printResult (const Key originalRoot, const Key root, const | |
cout << endl; | ||
} | ||
|
||
if (cl.debug) | ||
for (const auto & it : hierarchy) | ||
{ | ||
cout << endl << "Dumping whole analyzation results" << endl; | ||
for (const auto & it : hierarchy) | ||
if (filterPredicate (it.first.getFullName ()) && it.second.second > minDepth && it.second.second <= maxDepth) | ||
{ | ||
cout << it.first << " " << it.second.first << " " << it.second.second << endl; | ||
printResult (it, cl.verbose); | ||
} | ||
cout << endl; | ||
} | ||
} | ||
|
||
for (const auto & it : hierarchy) | ||
void CompleteCommand::printResult (const pair<Key, pair<int, int>> & current, const bool verbose) | ||
{ | ||
cout << current.first; | ||
if (current.second.first > 1) | ||
{ | ||
if (filterPredicate (it.first.getFullName ()) && it.second.second > minDepth && it.second.second <= maxDepth) | ||
cout << "/ "; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do you add a trailing whitespace character after There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, of course this makes not much sense, moved the additional whitespace to the verbose output where it separates the number of children from the keyname. |
||
if (verbose) | ||
{ | ||
cout << it.first << (it.second.first > 1 ? " node " + to_string (it.second.first - 1) : " leaf") << endl; | ||
cout << "node " << to_string (current.second.first - 1); | ||
} | ||
} | ||
else if (verbose) | ||
{ | ||
cout << " leaf 0"; | ||
} | ||
if (verbose) | ||
{ | ||
cout << " " << current.second.second; | ||
} | ||
cout << endl; | ||
} | ||
|
||
const function<bool(string)> CompleteCommand::determineFilterPredicate (const Key originalRoot, const Key root) | ||
const function<bool(string)> CompleteCommand::determineFilterPredicate (const string originalInput, const Key originalRoot, const Key root) | ||
{ | ||
if (root == originalRoot) | ||
{ | ||
return [](string) { return true; }; | ||
} | ||
const string fullName = originalRoot.getFullName (); | ||
|
||
const bool namespaceCompletion = originalRoot.getFullName ().empty (); | ||
const string fullName = namespaceCompletion ? originalInput : originalRoot.getFullName (); | ||
return [=](string test) { | ||
// For cascading keys, we ignore the preceding namespace for filtering | ||
const int cascadationOffset = (root.isCascading () ? test.find ("/") : 0); | ||
const int cascadationOffset = (!namespaceCompletion && root.isCascading () ? test.find ("/") : 0); | ||
return fullName.size () <= test.size () && equal (fullName.begin (), fullName.end (), test.begin () + cascadationOffset); | ||
}; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo:
Correction: