terminal/src/inc/til/replace.h
Mike Griese dcc2799457
Add support for iterable, nested commands (#6856)
## Summary of the Pull Request

This PR adds support for both _nested_ and _iterable_ commands in the Command palette.
![nested-commands-000](https://user-images.githubusercontent.com/18356694/87072916-2d991c00-c1e2-11ea-8917-a70e8b8b9803.gif)

* **Nested commands**: These are commands that include additional sub-commands. When the user selects on of these, the palette will update to only show the nested commands.
* **Iterable commands**: These are commands what allow the user to define only a single command, which is repeated once for every profile. (in the future, also repeated for color schemes, themes, etc.)

The above gif uses the following json:

```json
        {
            "name": "Split Pane...",
            "commands": [
                {
                    "iterateOn": "profiles",
                    "name": "Split with ${profile.name}...",
                    "commands": [
                        { "command": { "action": "splitPane", "profile": "${profile.name}", "split": "automatic" } },
                        { "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" } },
                        { "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" } }
                    ]
                }
            ]
        },
```

## References

## PR Checklist
* [x] Closes #3994
* [x] I work here
* [x] Tests added/passed
* [ ] Requires documentation to be updated - Sure does, but we'll finish polishing this first.

## Detailed Description of the Pull Request / Additional comments

We've now gotta keep the original json for a command around, so that once we know what all the profiles will be, we can expand the commands that need it. 

We've also got to parse commands recursively, because they might have any number of child commands.

These together made the command parsing a _lot_ more complicated, but it feels good so far.

## Validation Steps Performed
* wrote a bunch of tests
* Played with it a bunch
2020-08-13 21:22:46 +00:00

74 lines
2.5 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
namespace til
{
namespace details
{
template<typename T>
struct view_type_oracle
{
};
template<>
struct view_type_oracle<std::string>
{
using type = std::string_view;
};
template<>
struct view_type_oracle<std::wstring>
{
using type = std::wstring_view;
};
}
// Method Description:
// - This is a function for finding all occurences of a given string
// `needle` in a larger string `haystack`, and replacing them with the
// string `replacement`.
// - This find/replace is done in-place, leaving `haystack` modified as a result.
// Arguments:
// - haystack: The string to find and replace in
// - needle: The string to search for
// - replacement: The string to replace `needle` with
// Return Value:
// - <none>
template<typename T>
void replace_needle_in_haystack_inplace(T& haystack,
const typename details::view_type_oracle<T>::type& needle,
const typename details::view_type_oracle<T>::type& replacement)
{
auto pos{ T::npos };
while ((pos = haystack.rfind(needle, pos)) != T::npos)
{
haystack.replace(pos, needle.size(), replacement);
}
}
// Method Description:
// - This is a function for finding all occurences of a given string
// `needle` in a larger string `haystack`, and replacing them with the
// string `replacement`.
// - This find/replace is done on a copy of `haystack`, leaving `haystack`
// unmodified, and returning a new string.
// Arguments:
// - haystack: The string to search for `needle` in.
// - needle: The string to search for
// - replacement: The string to replace `needle` with
// Return Value:
// - a copy of `haystack` with all instances of `needle` replaced with `replacement`.`
template<typename T>
T replace_needle_in_haystack(const T& haystack,
const typename details::view_type_oracle<T>::type& needle,
const typename details::view_type_oracle<T>::type& replacement)
{
std::basic_string<typename T::value_type> result{ haystack };
replace_needle_in_haystack_inplace(result, needle, replacement);
return result;
}
}