TrinityCore
Loading...
Searching...
No Matches
CliRunnable.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
21
22#include "Common.h"
23#include "Errors.h"
24#include "ObjectMgr.h"
25#include "World.h"
27
28#include "CliRunnable.h"
29#include "Log.h"
30#include "Util.h"
31
32#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
33#include "Chat.h"
34#include "ChatCommand.h"
35#include <cstring>
36#include <readline/readline.h>
37#include <readline/history.h>
38#else
39#include <Windows.h>
40#endif
41
42static constexpr char CLI_PREFIX[] = "TC> ";
43
44static inline void PrintCliPrefix()
45{
46 printf("%s", CLI_PREFIX);
47}
48
49#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
50namespace Trinity::Impl::Readline
51{
52 static std::vector<std::string> vec;
53 char* cli_unpack_vector(char const*, int state)
54 {
55 static size_t i=0;
56 if (!state)
57 i = 0;
58 if (i < vec.size())
59 return strdup(vec[i++].c_str());
60 else
61 return nullptr;
62 }
63
64 char** cli_completion(char const* text, int /*start*/, int /*end*/)
65 {
66 ::rl_attempted_completion_over = 1;
67 vec = Trinity::ChatCommands::GetAutoCompletionsFor(CliHandler(nullptr,nullptr), text);
68 return ::rl_completion_matches(text, &cli_unpack_vector);
69 }
70
71 int cli_hook_func()
72 {
73 if (World::IsStopped())
74 ::rl_done = 1;
75 return 0;
76 }
77}
78#endif
79
80void utf8print(void* /*arg*/, std::string_view str)
81{
82#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
83 WriteWinConsole(str);
84#else
85{
87 fflush(stdout);
88}
89#endif
90}
91
92void commandFinished(void*, bool /*success*/)
93{
95 fflush(stdout);
96}
97
98#ifdef linux
99// Non-blocking keypress detector, when return pressed, return 1, else always return 0
100int kb_hit_return()
101{
102 struct timeval tv;
103 fd_set fds;
104 tv.tv_sec = 0;
105 tv.tv_usec = 0;
106 FD_ZERO(&fds);
107 FD_SET(STDIN_FILENO, &fds);
108 select(STDIN_FILENO+1, &fds, nullptr, nullptr, &tv);
109 return FD_ISSET(STDIN_FILENO, &fds);
110}
111#endif
112
115{
116#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
117 // print this here the first time
118 // later it will be printed after command queue updates
120#else
121 ::rl_attempted_completion_function = &Trinity::Impl::Readline::cli_completion;
122 {
123 static char BLANK = '\0';
124 ::rl_completer_word_break_characters = &BLANK;
125 }
126 ::rl_event_hook = &Trinity::Impl::Readline::cli_hook_func;
127#endif
128
129 if (sConfigMgr->GetBoolDefault("BeepAtStart", true))
130 printf("\a"); // \a = Alert
131
132#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
133 if (sConfigMgr->GetBoolDefault("FlashAtStart", true))
134 {
135 FLASHWINFO fInfo;
136 fInfo.cbSize = sizeof(FLASHWINFO);
137 fInfo.dwFlags = FLASHW_TRAY | FLASHW_TIMERNOFG;
138 fInfo.hwnd = GetConsoleWindow();
139 fInfo.uCount = 0;
140 fInfo.dwTimeout = 0;
141 FlashWindowEx(&fInfo);
142 }
143#endif
145 while (!World::IsStopped())
146 {
147 fflush(stdout);
148
149 std::string command;
150
151#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
152 if (!ReadWinConsole(command))
153 continue;
154#else
155 char* command_str = readline(CLI_PREFIX);
156 ::rl_bind_key('\t', ::rl_complete);
157 if (command_str != nullptr)
158 {
159 command = command_str;
160 free(command_str);
161 }
162#endif
163
164 if (!command.empty())
165 {
166 Optional<std::size_t> nextLineIndex = RemoveCRLF(command);
167 if (nextLineIndex && *nextLineIndex == 0)
168 {
169#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
171#endif
172 continue;
173 }
174
175 fflush(stdout);
176 sWorld->QueueCliCommand(new CliCommandHolder(nullptr, command.c_str(), &utf8print, &commandFinished));
177#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS
178 add_history(command.c_str());
179#endif
180 }
181 else if (feof(stdin))
182 {
184 }
185 }
186}
#define sConfigMgr
Definition Config.h:60
#define STRING_VIEW_FMT_ARG(str)
Definition Define.h:126
#define STRING_VIEW_FMT
Definition Define.h:125
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
bool WriteWinConsole(std::string_view str, bool error)
Definition Util.cpp:641
TC_COMMON_API Optional< std::size_t > RemoveCRLF(std::string &str)
Definition Util.cpp:654
bool ReadWinConsole(std::string &str, size_t size)
Definition Util.cpp:622
static void StopNow(uint8 exitcode)
Definition World.h:673
static bool IsStopped()
Definition World.h:674
void CliThread()
Thread start
static void PrintCliPrefix()
static constexpr char CLI_PREFIX[]
void utf8print(void *, std::string_view str)
void commandFinished(void *, bool)
#define sWorld
Definition World.h:900
@ SHUTDOWN_EXIT_CODE
Definition World.h:63
TC_GAME_API std::vector< std::string > GetAutoCompletionsFor(ChatHandler const &handler, std::string_view cmd)
Storage class for commands issued for delayed execution.
Definition World.h:536