Thư viện Editline (và GNU readline) chỉ hoạt động với các khả năng của thiết bị đầu cuối. Để sử dụng các thư viện này với bảng điều khiển trong trò chơi của bạn, trước tiên bạn cần triển khai trình giả lập thiết bị đầu cuối (TTY).
Thay vào đó (vì làm điều đó cho một trò chơi sẽ rất điên rồ), tôi sẽ khuyên bạn nên thực hiện các chuyển động con trỏ và tự chỉnh sửa. Tôi đã từng viết một lớp C ++ để xử lý việc này cho bảng điều khiển trong trò chơi của riêng tôi cho chính xác mục đích này. Lớp học có tên là EditLine. Lớp xử lý các chuyển động con trỏ cơ bản, xóa char / word / line và lịch sử. Không có gì lạ mắt, nhưng bạn có thể thấy nó hữu ích. Tài liệu là thưa thớt hoặc không tồn tại, hy vọng bạn có thể tìm ra nó bằng mọi cách. Không có tự động hoàn thành, không may. Tôi đã thực hiện điều đó trong một lớp trên bằng cách sử dụng lớp này.
chỉnh sửa.h
#include <string>
#include <vector>
class EditLine {
public:
EditLine();
EditLine(const EditLine&);
~EditLine();
// assignment operator
EditLine& operator=(const EditLine&);
// comparison operators
bool operator==(const EditLine&) const;
bool operator!=(const EditLine&) const;
// edit commands
void accept_line();
void reject_line();
void insert_char(int);
void delete_char();
void backward_delete_char();
void delete_word();
void backward_delete_word();
void delete_line();
// motion commands
void beginning_of_line();
void end_of_line();
void forward_char();
void backward_char();
void forward_word();
void backward_word();
// history commands
void next_history();
void previous_history();
// accessors
int history_pos() const;
inline size_t history_size() const;
inline bool empty() const;
inline const std::string& line() const;
inline size_t length() const;
inline const std::string::size_type& cursor_pos() const;
// mutators
void set_line(const std::string& s);
void set_cursor_pos(std::string::size_type);
void reset_line();
private:
std::string line_;
std::string::size_type cursor_pos_;
std::vector< std::string > history_;
std::vector< std::string >::iterator last_iter_;
};
inline size_t EditLine::history_size() const { return history_.size(); }
inline const std::string& EditLine::line() const { return line_; }
inline const std::string::size_type& EditLine::cursor_pos() const { return cursor_pos_; }
inline bool EditLine::empty() const { return line_.empty(); }
inline size_t EditLine::length() const { return line_.length(); }
chỉnh sửa.cpp
#include "editline.h"
#include "string_utils.h"
#include <string>
namespace {
const std::string word_delims = " !@#$%^&*()+-={}[]:\"|;'\\<>?,./";
} // namespace
EditLine::EditLine()
: line_(std::string()),
cursor_pos_(0),
last_iter_(history_.end())
{
}
EditLine::EditLine(const EditLine& rhs)
{
*this = rhs;
}
EditLine::~EditLine()
{
}
EditLine& EditLine::operator=(const EditLine& rhs)
{
line_ = rhs.line_;
cursor_pos_ = rhs.cursor_pos_;
history_ = rhs.history_;
if (rhs.last_iter_ == rhs.history_.end())
last_iter_ = history_.end();
else {
last_iter_ = history_.begin();
std::advance(last_iter_, rhs.last_iter_ - rhs.history_.begin());
}
return *this;
}
void EditLine::set_line(const std::string& s)
{
line_ = s;
cursor_pos_ = line_.size();
}
void EditLine::set_cursor_pos(std::string::size_type pos)
{
if (pos > line_.size())
pos = line_.size();
cursor_pos_ = pos;
}
void EditLine::reset_line()
{
line_.clear();
cursor_pos_ = 0;
}
bool EditLine::operator==(const EditLine& rhs) const
{
return (line_ == rhs.line_ &&
cursor_pos_ == rhs.cursor_pos_ &&
history_ == rhs.history_ &&
history_pos() == rhs.history_pos());
}
bool EditLine::operator!=(const EditLine& rhs) const
{
return !operator==(rhs);
}
void EditLine::accept_line()
{
if (!line_.empty())
history_.push_back(line_);
line_.clear();
cursor_pos_ = 0;
last_iter_ = history_.end();
}
void EditLine::reject_line()
{
line_.clear();
cursor_pos_ = 0;
last_iter_ = history_.end();
}
void EditLine::insert_char(int c)
{
line_.insert(cursor_pos_, 1, c);
cursor_pos_++;
}
void EditLine::delete_char()
{
line_.erase(cursor_pos_, 1);
}
void EditLine::backward_delete_char()
{
if (cursor_pos_ > 0) {
line_.erase(cursor_pos_ - 1, 1);
cursor_pos_--;
}
}
void EditLine::delete_word()
{
std::string::size_type pos;
// check if cursor points on a word delim
if (word_delims.find(line_[cursor_pos_]) != std::string::npos) {
// cursor points on a word delim - remove everything from here to
// right up to first delim after this word.
pos = line_.find_first_not_of(word_delims, cursor_pos_+1);
if (pos != std::string::npos)
pos = line_.find_first_of(word_delims, pos+1);
} else {
// cursor is in the middle of a word - remove everything up to first
// delim.
pos = line_.find_first_of(word_delims, cursor_pos_+1);
}
if (pos != std::string::npos)
// removes everything right of cursor up to 'pos'
line_.replace(cursor_pos_, pos - cursor_pos_, "");
else
// removes everthing right of cursor
line_.erase(cursor_pos_);
}
void EditLine::backward_delete_word()
{
std::string::size_type pos;
if (cursor_pos_ == 0) return;
// check if char left of cursor is a word delim
if (word_delims.find(line_[cursor_pos_-1]) != std::string::npos) {
// left of cursor is a word delim - remove everything from left of
// cursor up to next word delim before current word.
pos = rfind_first_not_of(line_, word_delims, cursor_pos_-1);
if (pos != std::string::npos)
pos = rfind_first_of(line_, word_delims, pos);
} else {
// left of cursor is not a word delim - remove everything left of
// cursor up to next word delim.
pos = rfind_first_of(line_, word_delims, cursor_pos_-1);
}
if (pos != std::string::npos) {
// removes from right of pos and up to cursor
line_.erase(pos + 1, cursor_pos_ - pos - 1);
cursor_pos_ = pos + 1;
} else {
// removes everything from beginning up to cursor
line_.erase(0, cursor_pos_);
cursor_pos_ = 0;
}
}
void EditLine::delete_line()
{
line_.erase(cursor_pos_);
cursor_pos_ = line_.size();
}
void EditLine::beginning_of_line()
{
cursor_pos_ = 0;
}
void EditLine::end_of_line()
{
cursor_pos_ = line_.size();
}
void EditLine::forward_char()
{
if (cursor_pos_ < line_.size())
cursor_pos_++;
}
void EditLine::backward_char()
{
if (cursor_pos_ > 0)
cursor_pos_--;
}
void EditLine::forward_word()
{
std::string::size_type pos;
pos = line_.find_first_of(word_delims, cursor_pos_);
if (pos != std::string::npos)
cursor_pos_ = pos + 1;
else
cursor_pos_ = line_.size();
}
void EditLine::backward_word()
{
if (cursor_pos_ <= 1) {
cursor_pos_ = 0;
return;
}
std::string::size_type pos, cursor_pos;
cursor_pos = cursor_pos_;
if (cursor_pos >= 2)
cursor_pos -= 2;
bool found = false;
for (int i = (int) cursor_pos; i >= 0; --i) {
if (word_delims.find(line_[i]) != std::string::npos) {
pos = (std::string::size_type) i;
found = true;
break;
}
}
if (found)
cursor_pos_ = pos + 1;
else
cursor_pos_ = 0;
}
void EditLine::next_history()
{
if (!history_.empty()) {
if (last_iter_ == history_.end() || ++last_iter_ == history_.end())
last_iter_ = history_.begin();
line_ = *last_iter_;
cursor_pos_ = line_.size();
}
}
void EditLine::previous_history()
{
if (!history_.empty()) {
if (last_iter_ != history_.begin())
--last_iter_;
else
last_iter_ = --history_.end();
line_ = *last_iter_;
cursor_pos_ = line_.size();
}
}
int EditLine::history_pos() const
{
if (last_iter_ == history_.end())
return -1;
return last_iter_ - history_.begin();
}
chuỗi_utils.h
std::string::size_type rfind_first_not_of(const std::string& s,
const std::string& delims,
std::string::size_type pos);
std::string::size_type rfind_first_of(const std::string& s,
const std::string& delims,
std::string::size_type pos);
chuỗi_utils.cpp
std::string::size_type rfind_first_not_of(const std::string& s,
const std::string& delims, std::string::size_type pos)
{
std::string::size_type p = pos;
while (delims.find(s[p]) != std::string::npos) {
if (p == 0) // not found
return std::string::npos;
--p;
}
return p;
}
std::string::size_type rfind_first_of(const std::string& s,
const std::string& delims, std::string::size_type pos)
{
std::string::size_type p = pos;
while (delims.find(s[p]) == std::string::npos) {
if (p == 0) // not found
return std::string::npos;
--p;
}
return p;
}