Skip to content

Commit

Permalink
Ctrl+w handler (#32)
Browse files Browse the repository at this point in the history
* Start the ctrl+w implementation

* Fix an invalid free in the ctrl+l implementation

* Finish implementing ctrl + w

* Only print keys when they miss if KEYS_VERBOSE is YES

* Add ctrl+w and ctrl+l to the README under line editing
  • Loading branch information
allenh1 authored Oct 14, 2018
1 parent e3e59d0 commit 2e18186
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ In YaSh, one can...
* ctrl + right arrow to go to the next space
* ctrl + left arrow to go to the previous space
* ctrl + delete to remove the word to the right of the cursor
* ctrl + w to remove the word to the left of the cursor
* ctrl + l to run the clear command
* use arrow keys to move through history

History:
Expand Down
63 changes: 62 additions & 1 deletion src/shell-readline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,72 @@ bool read_line::handle_ctrl_l(std::string & _line)
if (!write_with_error(1, line.c_str(), line.size())) {
}
/* write back spaces for m_buff.len() */
std::unique_ptr<char> bspace(new char[m_buff.size()]);
auto bspace = std::make_unique<char[]>(m_buff.size());
memset(bspace.get(), '\b', m_buff.size());
return !write_with_error(1, bspace.get(), m_buff.size());
}

/**
* @brief Handle ctrl + w
*
* Ctrl + w removes the word to the left of the cursor
*
* @param _line The line to be mutated
* @return false unless bad thigns happen
*/
bool read_line::handle_ctrl_w(std::string & _line)
{
if (!_line.size()) {
/* this is a decidedly shorter type of no-op */
return false;
}
/* first, reverse iterate to the last ' ' in the string */
auto it = _line.end();
for (; *it != ' ' && it != _line.begin(); --it) {
/* don't push, since we're removing this */
}
/* wipe all to the right */
auto b_spaces = std::make_unique<char[]>(m_buff.size());
auto spaces = std::make_unique<char[]>(m_buff.size());
::memset(b_spaces.get(), '\b', m_buff.size());
::memset(spaces.get(), ' ', m_buff.size());
if (!write_with_error(1, spaces.get(), m_buff.size())) {
return true;
} else if (!write_with_error(1, b_spaces.get(), m_buff.size())) {
return true;
}
const size_t diff = _line.end() - it;
auto b_spaces2 = std::make_unique<char[]>(diff);
auto spaces2 = std::make_unique<char[]>(diff);
::memset(b_spaces2.get(), '\b', diff);
::memset(spaces2.get(), ' ', diff);
/* wipe the printed argument */
if (!write_with_error(1, b_spaces2.get(), diff)) {
return true;
} else if (!write_with_error(1, spaces2.get(), diff)) {
return true;
} else if (!write_with_error(1, b_spaces2.get(), diff)) {
return true;
}
/* remove the argument from _line */
_line.erase(it, _line.end());
/* now we print out the rest of the string and backtrack */
char * s = spaces.get();
auto buff = m_buff;
for (; buff.size(); buff.pop()) {
*(s++) = buff.top();
}
if (!_line.size()) {
/* this is a special case like 'asdf ' + ctrl + w */
return !(write_with_error(1, " ") &&
write_with_error(1, spaces.get(), m_buff.size()) &&
write_with_error(1, b_spaces.get(), m_buff.size()) &&
write_with_error(1, "\b"));
}
return !(write_with_error(1, spaces.get(), m_buff.size()) &&
write_with_error(1, b_spaces.get(), m_buff.size()));
}

/**
* @brief Handle ctrl + d
*
Expand Down
7 changes: 6 additions & 1 deletion src/shell-readline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class read_line
bool handle_ctrl_d(std::string & _line);
bool handle_ctrl_e(std::string & _line);
bool handle_ctrl_l(std::string & _line);
bool handle_ctrl_w(std::string & _line);
bool handle_ctrl_k();
bool handle_ctrl_del();
bool handle_ctrl_arrow(std::string & _line);
Expand Down Expand Up @@ -141,6 +142,8 @@ class read_line
continue;
} else if (input == 12 && !handle_ctrl_l(_line)) {
continue;
} else if (input == 23 && !handle_ctrl_w(_line)) {
continue;
} else if (input == 9 && !handle_tab(_line)) {
continue;
} else if (input == 27) {
Expand All @@ -159,11 +162,13 @@ class read_line
if (ch1 == 91 && ch2 == 66 && !handle_down_arrow(_line)) {continue;}
if (ch1 == 91 && ch2 == 67 && !handle_right_arrow(_line)) {continue;}
if (ch1 == 91 && ch2 == 68 && !handle_left_arrow(_line)) {continue;}
} else if (!strcmp(getenv("KEY_VERBOSE"), "YES")) {
std::cerr << "unknown input '" << static_cast<int>(input) << "'" << std::endl;
}
}

if (_line.size()) {
std::string _file = tilde_expand("~/.cache/yash_history");
const std::string _file = tilde_expand("~/.cache/yash_history");
int history_fd = open(_file.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0600);
if (!write_with_error(history_fd, _line.c_str(), _line.size())) {
return;
Expand Down

0 comments on commit 2e18186

Please sign in to comment.