Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ctrl+w handler #32

Merged
merged 5 commits into from
Oct 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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