std::tuple<os::fs::file, string, uintptr_t> OpenLangFile(string_view const Path, string_view const Mask, string_view const Language) { FN_RETURN_TYPE(OpenLangFile) CurrentFileData, EnglishFileData; for (const auto& FindData: os::fs::enum_files(path::join(Path, Mask))) { const auto CurrentFileName = path::join(Path, FindData.FileName); auto& CurrentFile = std::get<0>(CurrentFileData); auto& CurrentLngName = std::get<1>(CurrentFileData); auto& CurrentCodepage = std::get<2>(CurrentFileData); CurrentFile = os::fs::file(CurrentFileName, FILE_READ_DATA, FILE_SHARE_READ, nullptr, OPEN_EXISTING); if (CurrentFile) { CurrentCodepage = GetFileCodepage(CurrentFile, encoding::codepage::oem(), nullptr, false); if (GetLangParam(CurrentFile, L"Language"sv, CurrentLngName, nullptr, CurrentCodepage) && equal_icase(CurrentLngName, Language)) { return CurrentFileData; } if (equal_icase(CurrentLngName, L"English"sv)) { EnglishFileData = std::move(CurrentFileData); } } } if (std::get<0>(EnglishFileData)) return EnglishFileData; return CurrentFileData; }
static std::list<PreserveStyleToken> InternalPreserveStyleTokenize(const string& strStr, size_t From, size_t Length) { FN_RETURN_TYPE(InternalPreserveStyleTokenize) Result; std::vector<bool> Seps(Length, false); for (size_t I = From+1; I+1 < From+Length; I++) { if (IsPreserveStyleTokenSeparator(strStr[I]) && !IsPreserveStyleTokenSeparator(strStr[I-1]) && !IsPreserveStyleTokenSeparator(strStr[I+1])) { Seps[I-From] = true; } } size_t L = From; for (size_t I = From+1; I < From+Length; I++) { if (Seps[I-From]) { PreserveStyleToken T; T.Token = strStr.substr(L, I-L); T.PrependChar = 0; if (L >= From + 1 && Seps[L-1-From]) T.PrependChar = strStr[L-1]; Result.emplace_back(T); L = I+1; I++; continue; } if (!Seps[I-From-1] && IsLower(strStr[I-1]) && IsUpper(strStr[I])) { PreserveStyleToken T; T.Token = strStr.substr(L, I-L); T.PrependChar = 0; if (L >= From + 1 && Seps[L-1-From]) T.PrependChar = strStr[L-1]; Result.emplace_back(T); L = I; } } if (L < From+Length) { PreserveStyleToken T; T.Token = strStr.substr(L, From+Length-L); T.PrependChar = 0; if (L >= From + 1 && Seps[L-1-From]) T.PrependChar = strStr[L-1]; Result.emplace_back(T); } if (Result.size() > 1) { wchar_t PrependChar = std::next(Result.cbegin())->PrependChar; FOR (const auto& i, make_range(std::next(Result.cbegin(), 2), Result.cend())) { if (PrependChar != i.PrependChar) { Result.clear(); PreserveStyleToken T; T.Token = strStr.substr(From, Length); T.PrependChar = 0; T.TypeMask = 1 << UNKNOWN; Result.emplace_back(T); return Result; } } }
std::list<CommandLine::segment> CommandLine::GetPrompt() { FN_RETURN_TYPE(CommandLine::GetPrompt) Result; int NewPromptSize = DEFAULT_CMDLINE_WIDTH; const auto& PrefixColor = colors::PaletteColorToFarColor(COL_COMMANDLINEPREFIX); if (Global->Opt->CmdLine.UsePromptFormat) { const string_view Format = Global->Opt->CmdLine.strPromptFormat.Get(); auto Tail = Format.cbegin(); auto Color = PrefixColor; FOR_CONST_RANGE(Format, Iterator) { bool Stop; auto NewColor = PrefixColor; const auto NextIterator = colors::ExtractColorInNewFormat(Iterator, Format.cend(), NewColor, Stop); if (NextIterator == Iterator) { if (Stop) break; continue; } if (Iterator != Format.cbegin()) { Result.emplace_back(segment{ string(Tail, Iterator), Color }); } Iterator = NextIterator; Tail = Iterator; Color = NewColor; } Result.emplace_back(segment{ string(Tail, Format.cend()), Color }); for (auto Iterator = Result.begin(); Iterator != Result.end(); ++Iterator) { const auto strExpandedDestStr = os::env::expand(Iterator->Text); Iterator->Text.clear(); static const std::pair<wchar_t, wchar_t> ChrFmt[] = { {L'A', L'&'}, // $A - & (Ampersand) {L'B', L'|'}, // $B - | (pipe) {L'C', L'('}, // $C - ( (Left parenthesis) {L'F', L')'}, // $F - ) (Right parenthesis) {L'G', L'>'}, // $G - > (greater-than sign) {L'L', L'<'}, // $L - < (less-than sign) {L'Q', L'='}, // $Q - = (equal sign) {L'S', L' '}, // $S - (space) {L'$', L'$'}, // $$ - $ (dollar sign) }; FOR_CONST_RANGE(strExpandedDestStr, it) { auto& strDestStr = Iterator->Text; if (*it == L'$' && it + 1 != strExpandedDestStr.cend()) { const auto Chr = upper(*++it); const auto ItemIterator = std::find_if(CONST_RANGE(ChrFmt, Item) { return Item.first == Chr; }); if (ItemIterator != std::cend(ChrFmt)) { strDestStr += ItemIterator->second; } else { const auto& AddCollapsible = [&](string&& Str) { if (strDestStr.empty()) { strDestStr = std::move(Str); Iterator->Collapsible = true; } else { Iterator = Result.insert(std::next(Iterator), segment{ std::move(Str), Iterator->Colour, true }); } // No need to introduce a new segment if we're at the very end if (std::next(Iterator) != Result.end() && std::next(it) != strExpandedDestStr.cend()) { Iterator = Result.insert(std::next(Iterator), segment{ {}, Iterator->Colour, false }); } }; switch (Chr) { /* эти не реaлизованы $E - Escape code (ASCII code 27) $V - Windows version number $_ - Carriage return and linefeed */ case L'M': // $M - Отображение полного имени удаленного диска, связанного с именем текущего диска, или пустой строки, если текущий диск не является сетевым. { string strTemp; if (DriveLocalToRemoteName(DRIVE_UNKNOWN, m_CurDir[0], strTemp)) { AddCollapsible(std::move(strTemp)); } break; } case L'+': // $+ - Отображение нужного числа знаков плюс (+) в зависимости от текущей глубины стека каталогов PUSHD, по одному знаку на каждый сохраненный путь. { strDestStr.append(ppstack.size(), L'+'); break; } case L'H': // $H - Backspace (erases previous character) { if (!strDestStr.empty()) { strDestStr.pop_back(); } else { auto Prev = Iterator; while (Prev != Result.begin()) { --Prev; if (!Prev->Text.empty()) { Prev->Text.pop_back(); break; } } } break; } case L'@': // $@xx - Admin { if (it + 1 != strExpandedDestStr.cend()) { const auto lb = *++it; if (it + 1 != strExpandedDestStr.cend()) { const auto rb = *++it; if (os::security::is_admin()) { append(strDestStr, lb, msg(lng::MConfigCmdlinePromptFormatAdmin), rb); } } } break; } case L'D': // $D - Current date case L'T': // $T - Current time { strDestStr += MkStrFTime(Chr == L'D'? L"%D" : L"%T"); break; } case L'N': // $N - Current drive { const auto Type = ParsePath(m_CurDir); if(Type == root_type::drive_letter) strDestStr += upper(m_CurDir[0]); else if(Type == root_type::unc_drive_letter) strDestStr += upper(m_CurDir[4]); else strDestStr += L'?'; break; } case L'W': // $W - Текущий рабочий каталог (без указания пути) { const auto pos = FindLastSlash(m_CurDir); if (pos != string::npos) { AddCollapsible(m_CurDir.substr(pos + 1)); } break; } case L'P': // $P - Current drive and path { AddCollapsible(string{ m_CurDir }); break; } case L'#': //$#nn - max prompt width in % { if (it + 1 != strExpandedDestStr.end()) { size_t pos; if (from_string(string(it + 1, strExpandedDestStr.cend()), NewPromptSize, &pos)) it += pos; // else // bad format, NewPromptSize unchanged // TODO: diagnostics } } } if (it == strExpandedDestStr.cend()) { break; } } } else {