/** * Copyright (c) 2022, Timothy Stack * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Timothy Stack nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lnav_breadcrumb_hh #define lnav_breadcrumb_hh #include #include "base/attr_line.hh" #include "fmt/format.h" #include "mapbox/variant.hpp" namespace breadcrumb { struct possibility { possibility(std::string key, attr_line_t value) : p_key(std::move(key)), p_display_value(std::move(value)) { } explicit possibility(std::string key) : p_key(key), p_display_value(key) {} possibility() = default; bool operator<(const possibility& rhs) const { return p_key < rhs.p_key; } bool operator>(const possibility& rhs) const { return rhs < *this; } bool operator<=(const possibility& rhs) const { return !(rhs < *this); } bool operator>=(const possibility& rhs) const { return !(*this < rhs); } static bool sort_cmp(const possibility& lhs, const possibility& rhs) { static constexpr const char* TOKENS = "[](){}"; auto lhsf = string_fragment::from_str(lhs.p_key).trim(TOKENS); auto rhsf = string_fragment::from_str(rhs.p_key).trim(TOKENS); return strnatcasecmp( lhsf.length(), lhsf.data(), rhsf.length(), rhsf.data()) < 0; } std::string p_key; attr_line_t p_display_value; }; using crumb_possibilities = std::function()>; struct crumb { using key_t = mapbox::util::variant; using perform = std::function; crumb(std::string key, attr_line_t al, crumb_possibilities cp, perform performer) : c_key(std::move(key)), c_display_value(std::move(al)), c_possibility_provider(std::move(cp)), c_performer(std::move(performer)) { } crumb(std::string key, crumb_possibilities cp, perform performer) : c_key(key), c_display_value(key), c_possibility_provider(std::move(cp)), c_performer(std::move(performer)) { } explicit crumb(size_t index, crumb_possibilities cp, perform performer) : c_key(index), c_display_value(fmt::format(FMT_STRING("[{}]"), index)), c_possibility_provider(std::move(cp)), c_performer(std::move(performer)) { } explicit crumb(key_t key, crumb_possibilities cp, perform performer) : c_key(key), c_display_value(key.match( [](std::string str) { return str; }, [](size_t index) { return fmt::format(FMT_STRING("[{}]"), index); })), c_possibility_provider(std::move(cp)), c_performer(std::move(performer)) { } crumb& with_possible_range(size_t count) { this->c_possible_range = count; if (count == 0) { this->c_search_placeholder = "(Array is empty)"; } else if (count == 1) { this->c_search_placeholder = "(Array contains a single element)"; } else { this->c_search_placeholder = fmt::format( FMT_STRING("(Enter a number from 0 to {})"), count - 1); } return *this; } enum class expected_input_t { exact, index, index_or_exact, anything, }; key_t c_key; attr_line_t c_display_value; crumb_possibilities c_possibility_provider; perform c_performer; nonstd::optional c_possible_range; expected_input_t c_expected_input{expected_input_t::exact}; std::string c_search_placeholder; }; } // namespace breadcrumb #endif