Skip to content

Commit aca3819

Browse files
committed
refactor(LineReader): Make use of the LineReader class in a much simpler way
The LineReader is made a concrete class whose declaration is independent of the readline library. Only its implementation depends on the presence or absence of the readline library. The LineReader code is embedded in a new library : line_reader, to make the cli library independant of the USE_READLINE definition.
1 parent 7c7ca45 commit aca3819

5 files changed

Lines changed: 80 additions & 102 deletions

File tree

src/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ set(core_SOURCES
4848
core/Totp.cpp
4949
core/Translator.cpp
5050
cli/Utils.cpp
51-
cli/TextStream.cpp
5251
crypto/Crypto.cpp
5352
crypto/CryptoHash.cpp
5453
crypto/Random.cpp

src/cli/CMakeLists.txt

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,23 @@
1313
# You should have received a copy of the GNU General Public License
1414
# along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16-
set(cli_SOURCES
16+
# text_stream library
17+
add_library(text_stream STATIC TextStream.cpp)
18+
target_link_libraries(text_stream PUBLIC Qt6::Core)
19+
20+
# line_reader library
21+
add_library(line_reader STATIC LineReader.cpp)
22+
target_link_libraries(line_reader PUBLIC Qt6::Core)
23+
find_package(Readline MODULE)
24+
if(READLINE_FOUND)
25+
target_compile_definitions(line_reader PRIVATE "USE_READLINE")
26+
target_link_libraries(line_reader PRIVATE ${Readline_LIBRARY})
27+
else()
28+
target_link_libraries(line_reader PRIVATE text_stream)
29+
endif()
30+
31+
# cli library
32+
add_library(cli STATIC
1733
Add.cpp
1834
AddGroup.cpp
1935
Analyze.cpp
@@ -44,21 +60,13 @@ set(cli_SOURCES
4460
Search.cpp
4561
Show.cpp)
4662

47-
add_library(cli STATIC ${cli_SOURCES})
48-
target_link_libraries(cli ${ZXCVBN_LIBRARIES} Qt6::Core)
49-
50-
find_package(Readline)
51-
52-
if (READLINE_FOUND)
53-
target_compile_definitions(cli PUBLIC USE_READLINE)
54-
target_link_libraries(cli ${Readline_LIBRARY})
55-
endif()
63+
target_link_libraries(cli
64+
PRIVATE ${ZXCVBN_LIBRARIES} text_stream
65+
PUBLIC Qt6::Core)
5666

5767
add_executable(keepassxc-cli keepassxc-cli.cpp)
5868
target_link_libraries(keepassxc-cli
59-
${GPGERROR_LIBRARIES}
60-
cli
61-
keepassxc_core)
69+
PRIVATE ${GPGERROR_LIBRARIES} cli keepassxc_core line_reader)
6270

6371
install(TARGETS keepassxc-cli
6472
BUNDLE DESTINATION . COMPONENT Runtime

src/cli/LineReader.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#include "LineReader.h"
2+
#ifdef USE_READLINE
3+
#include <readline/history.h>
4+
#include <readline/readline.h>
5+
#else
6+
#include "TextStream.h"
7+
#endif
8+
9+
QString LineReader::readLine(const QString& prompt)
10+
{
11+
#ifdef USE_READLINE
12+
char* result = readline(prompt.toStdString().c_str());
13+
if (!result) {
14+
m_finished = true;
15+
return {};
16+
}
17+
add_history(result);
18+
QString qstr(result);
19+
free(result);
20+
return qstr;
21+
#else
22+
TextStream outStream(stdout, QIODevice::WriteOnly), inStream(stdin, QIODevice::ReadOnly);
23+
outStream << prompt;
24+
outStream.flush();
25+
QString result = inStream.readLine();
26+
if (result.isNull()) {
27+
m_finished = true;
28+
}
29+
return result;
30+
#endif
31+
}
32+
33+
bool LineReader::isFinished() const
34+
{
35+
return m_finished;
36+
}

src/cli/LineReader.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef LINEREADER_H
2+
#define LINEREADER_H
3+
4+
#include <QString>
5+
6+
class LineReader
7+
{
8+
bool m_finished{false};
9+
10+
public:
11+
LineReader() = default;
12+
LineReader(const LineReader&) = delete;
13+
~LineReader() = default;
14+
LineReader& operator=(const LineReader&) = delete;
15+
QString readLine(const QString& prompt);
16+
[[nodiscard]] bool isFinished() const;
17+
};
18+
19+
#endif // LINEREADER_H

src/cli/keepassxc-cli.cpp

Lines changed: 4 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#include <QFileInfo>
2020

2121
#include "Command.h"
22+
#include "LineReader.h"
2223
#include "Open.h"
23-
#include "TextStream.h"
2424
#include "Utils.h"
2525
#include "config-keepassx.h"
2626
#include "core/Bootstrap.h"
@@ -33,83 +33,6 @@
3333
#include <sanitizer/lsan_interface.h>
3434
#endif
3535

36-
#if defined(USE_READLINE)
37-
#include <readline/history.h>
38-
#include <readline/readline.h>
39-
#endif
40-
41-
class LineReader
42-
{
43-
public:
44-
virtual ~LineReader() = default;
45-
virtual QString readLine(QString prompt) = 0;
46-
virtual bool isFinished() = 0;
47-
};
48-
49-
class SimpleLineReader : public LineReader
50-
{
51-
public:
52-
SimpleLineReader()
53-
: inStream(stdin, QIODevice::ReadOnly)
54-
, outStream(stdout, QIODevice::WriteOnly)
55-
, finished(false)
56-
{
57-
}
58-
59-
QString readLine(QString prompt) override
60-
{
61-
outStream << prompt;
62-
outStream.flush();
63-
QString result = inStream.readLine();
64-
if (result.isNull()) {
65-
finished = true;
66-
}
67-
return result;
68-
}
69-
70-
bool isFinished() override
71-
{
72-
return finished;
73-
}
74-
75-
private:
76-
TextStream inStream;
77-
TextStream outStream;
78-
bool finished;
79-
};
80-
81-
#if defined(USE_READLINE)
82-
class ReadlineLineReader : public LineReader
83-
{
84-
public:
85-
ReadlineLineReader()
86-
: finished(false)
87-
{
88-
}
89-
90-
QString readLine(QString prompt) override
91-
{
92-
char* result = readline(prompt.toStdString().c_str());
93-
if (!result) {
94-
finished = true;
95-
return {};
96-
}
97-
add_history(result);
98-
QString qstr(result);
99-
free(result);
100-
return qstr;
101-
}
102-
103-
bool isFinished() override
104-
{
105-
return finished;
106-
}
107-
108-
private:
109-
bool finished;
110-
};
111-
#endif
112-
11336
int enterInteractiveMode(const QStringList& arguments)
11437
{
11538
auto& err = Utils::STDERR;
@@ -123,16 +46,9 @@ int enterInteractiveMode(const QStringList& arguments)
12346
return EXIT_FAILURE;
12447
};
12548

126-
QScopedPointer<LineReader> reader;
127-
#if defined(USE_READLINE)
128-
reader.reset(new ReadlineLineReader());
129-
#else
130-
reader.reset(new SimpleLineReader());
131-
#endif
132-
49+
LineReader reader;
13350
QSharedPointer<Database> currentDatabase(openCmd.currentDatabase);
13451

135-
QString command;
13652
while (true) {
13753
QString prompt;
13854
if (currentDatabase) {
@@ -142,8 +58,8 @@ int enterInteractiveMode(const QStringList& arguments)
14258
}
14359
}
14460
prompt += "> ";
145-
command = reader->readLine(prompt);
146-
if (reader->isFinished()) {
61+
QString command = reader.readLine(prompt);
62+
if (reader.isFinished()) {
14763
break;
14864
}
14965

0 commit comments

Comments
 (0)