Skip to content

Commit

Permalink
Merge pull request #41 from ardagnir/0.8
Browse files Browse the repository at this point in the history
0.8
  • Loading branch information
ardagnir authored Nov 20, 2016
2 parents f59ff8d + aac642d commit 4da353c
Show file tree
Hide file tree
Showing 18 changed files with 560 additions and 374 deletions.
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ To build bash so that it uses the system readline:
**Additional Notes**
- You can add the --nobuild flag to the setup script if you want to configure/build/install yourself.
- You can change what Vim binary is used by passing --vimbin=/path/to/vim to the setup script.
- You can install Athame locally by passing --nosudo --prefix=$HOME/local/ to the setup script for readline and bash.


##Setting up Athame Zsh
Expand All @@ -74,13 +75,14 @@ To build bash so that it uses the system readline:
./zsh_athame_setup.sh

**Additional Notes**
- You can add the --nobuild flag to the setup script if you want to configure/build/install yourself
- You can change what Vim binary is used by passing --vimbin=/path/to/vim to the setup script
- You can add the --nobuild flag to the setup script if you want to configure/build/install yourself.
- You can change what Vim binary is used by passing --vimbin=/path/to/vim to the setup script.
- You can install Athame locally by passing --nosudo --prefix=$HOME/local/ to the setup script.

##FAQ
####How do I use this?
It's just like Vim. Imagine your history is stored inside a Vim buffer (because it is!) with a blank line at the bottom. Your cursor starts on that blank line each time readline is called.
Unless you're in command mode, tabs and carriage returns are handled by readline/zsh.
Unless you're in command mode, some special chars (such as carriage return) are handled by readline/zsh.

Some commands (there's no specific code for these, it's just Vim):

Expand Down Expand Up @@ -113,6 +115,13 @@ This should include libreadline. If it doesn't, you need to build bash to use th

./bash_readline_setup.sh

####Which chars are sent to vim and which to readline/zsh?

Control-C usually sends a SIGNINT signal that is handled by zsh, readline, or the program that calls readline. For other keys:

- In readline, chars marked as rl_delete (usually Control-D), rl_newline (usually return), rl_complete (usually tab), and rl_clear_screen (usually Control-L) are sent to readline. All other keys are sent to vim.
- In zsh, Athame is hardcoded to send tab, Control-D, carriage return, new line, and Control-L to zsh. All other keys are sent to vim. This behavior will likely change in the future.

####I got the error "Couldn't load vim path"
Is Vim at the correct path? You can change the path Athame looks at with the --vimbin flag.

Expand Down Expand Up @@ -162,7 +171,7 @@ The best way to help is to look at the issue section and submit patches to fix b
If you have a shell that I'm missing, you can also try making a patch to communicate between it and Athame (see athame_readline.h and athame_zsh.h for the functions you need to implement).

####What about donations?
I'm not accepting any currently, but thanks.
I'm not accepting donations, but you should consider donating to the [EFF](https://supporters.eff.org/donate/) so that we don't end up living in a scary distopian future where everyone is forced to use emacs.


##Setting up Vim with clientserver
Expand Down
115 changes: 77 additions & 38 deletions athame.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,13 @@ void athame_init(int instream, FILE* outstream)
updated = 1;
athame_mode[0] = 'n';
athame_mode[1] = '\0';
athame_displaying_mode[0] = '\0';
last_vim_command[0] = '\0';
last_cmd_pos = 0;
athame_command[0] = '\0';
command_cursor = 0;
bottom_display[0] = '\0';
last_athame_mode[0] = '\0';
bottom_color = 0;
bottom_style = 0;
bottom_cursor = 0;
cs_confirmed = 0;
athame_failure = 0;

Expand All @@ -65,9 +69,9 @@ void athame_init(int instream, FILE* outstream)

servername = 0;
dir_name = 0;
slice_file_name = 0;
contents_file_name = 0;
update_file_name = 0;
meta_file_name = 0;
messages_file_name = 0;
vimbed_file_name = 0;

Expand All @@ -87,9 +91,9 @@ void athame_init(int instream, FILE* outstream)
//The pid establishes uniqueness between processes and makes debugging easier.
asprintf(&servername, "athame_%d_%d", getpid(), rand() % (1000000000));
asprintf(&dir_name, "/tmp/vimbed/%s", servername);
asprintf(&slice_file_name, "%s/slice.txt", dir_name);
asprintf(&contents_file_name, "%s/contents.txt", dir_name);
asprintf(&update_file_name, "%s/update.txt", dir_name);
asprintf(&meta_file_name, "%s/meta.txt", dir_name);
asprintf(&messages_file_name, "%s/messages.txt", dir_name);
if (getenv("ATHAME_VIMBED_LOCATION"))
{
Expand All @@ -113,16 +117,23 @@ void athame_init(int instream, FILE* outstream)

void athame_cleanup()
{
if(dev_null)
{
fclose(dev_null);
if(expr_pid > 0) {
kill(expr_pid, SIGTERM);
}
if(vim_pid)
{
kill(vim_pid, SIGTERM);
// forkpty will keep vim open on OSX if we don't close the fd
kill(vim_pid, SIGTERM);
close(vim_term);
waitpid(vim_pid, NULL, 0);
}
if(dev_null)
{
fclose(dev_null);
}
if(slice_file_name)
{
unlink(slice_file_name);
free(slice_file_name);
}
if(contents_file_name)
{
Expand All @@ -134,11 +145,6 @@ void athame_cleanup()
unlink(update_file_name);
free(update_file_name);
}
if(meta_file_name)
{
unlink(meta_file_name);
free(meta_file_name);
}
if(messages_file_name)
{
unlink(messages_file_name);
Expand All @@ -159,12 +165,19 @@ void athame_cleanup()
}
if(athame_failure)
{
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0);
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0, 0);
free((char*)athame_failure);
}
else if (athame_is_set("ATHAME_SHOW_MODE", 1))
{
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0);
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0, 0);
}
if(expr_pid > 0) {
wait_then_kill(expr_pid);
}
if(vim_pid)
{
wait_then_kill(vim_pid);
}
}

Expand All @@ -190,14 +203,17 @@ char athame_loop(int instream)
{
char returnVal = 0;
sent_to_vim = 0;
vim_sync = VIM_SYNC_YES;
time_to_sync = get_time();
last_athame_mode[0] = '\0';
bottom_display[0] = '\0';

// This is a performance step that allows us to bypass starting up vim if we aren't going to talk to it.
char first_char = (vim_stage != VIM_RUNNING) ? athame_get_first_char(instream) : 0;
if (first_char && athame_handle_special_char(first_char))
if (first_char && strchr(ap_nl, first_char))
{
return first_char;
}

athame_ensure_vim(0, 0);

if(!updated)
Expand All @@ -212,8 +228,6 @@ char athame_loop(int instream)

while(!returnVal && !athame_failure)
{
athame_bottom_mode();

struct timeval timeout;
int selected = 0;
if(first_char){
Expand All @@ -234,14 +248,25 @@ char athame_loop(int instream)
else if (selected == 2)
{
read(vim_term, athame_buffer, DEFAULT_BUFFER_SIZE-1);
athame_get_vim_info(1);
if (!athame_get_vim_info()) {
request_poll();
}
}
else if (selected == 0)
{
if(vim_sync >= VIM_SYNC_CHAR_BEHIND) {
vim_sync = VIM_SYNC_NEEDS_POLL;
}
}
else if (selected == -1)
{
char sig_result;
if (sig_result = ap_handle_signals())
{
return sig_result;
} else {
// Make sure we keep the mode drawn on a resize.
athame_bottom_mode();
}
}
if (time_to_poll >= 0 && time_to_poll < get_time()) {
Expand Down Expand Up @@ -279,36 +304,50 @@ char athame_loop(int instream)
}
if(!athame_failure)
{
if(returnVal != ' ' && returnVal != '\b'){
if(sent_to_vim)
{
if(strcmp(athame_mode, "i") == 0)
{
athame_send_to_vim('\x1d'); //<C-]> Finish abbrevs/kill mappings
}
athame_sleep(200, 0, 0);
athame_get_vim_info(0);
}
if (athame_is_set("ATHAME_SHOW_MODE", 1))
if(sent_to_vim)
{
// Should already be synced here, but this is a no-op in that case and
// it makes the code less fragile to make sure.
athame_force_vim_sync();
if(strcmp(athame_mode, "i") == 0)
{
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0);
athame_displaying_mode[0] = '\0';
athame_send_to_vim('\x1d'); //<C-]> Finish abbrevs/kill mappings
athame_force_vim_sync();
}
}
if (athame_is_set("ATHAME_SHOW_MODE", 1))
{
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0, 0);
}
updated = 0;
} else {
// If we ate the first_char, we should return it.
if(returnVal == 0) {
returnVal = first_char;
}
}

return returnVal;
}

void athame_after_bypass() {
if (athame_failure && athame_is_set("ATHAME_SHOW_ERROR", 1))
{
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0);
athame_bottom_display("", ATHAME_BOLD, ATHAME_DEFAULT, 0, 0);
}
}

// Redraw bottom stuff before handing off to a process that might block,
// like python.
void athame_char_handled() {
if (!ap_needs_to_leave()) {
athame_bottom_mode();
if (athame_is_set("ATHAME_ENABLED", 1) && !ap_needs_to_leave()) {
if(athame_failure)
{
athame_draw_failure();
}
else
{
athame_bottom_mode();
}
}
}
28 changes: 12 additions & 16 deletions athame_readline.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,10 @@ static void ap_display()
rl_redisplay();
}

static int ap_get_term_width()
static void ap_get_term_size(int* height, int* width)
{
int height, width;
_rl_sigwinch_resize_terminal(); //Incase the terminal changed size while readline wasn't looking.
rl_get_screen_size(&height, &width);
return width;
}

static int ap_get_term_height()
{
int height, width;
_rl_sigwinch_resize_terminal(); //Incase the terminal changed size while readline wasn't looking.
rl_get_screen_size(&height, &width);
return height;
rl_get_screen_size(height, width);
}

static int ap_get_prompt_length()
Expand All @@ -126,7 +116,7 @@ HISTORY_STATE* hs;
int hs_counter;
static void ap_get_history_start()
{
hs = history_get_history_state();
hs = history_get_history_state();
hs_counter = 0;
}

Expand All @@ -152,7 +142,7 @@ static int ap_needs_to_leave()
return rl_done || rl_num_chars_to_read > 0 && rl_end >= rl_num_chars_to_read;
}

static char* ap_get_slice(char* text, int start, int end)
static char* ap_get_substr(char* text, int start, int end)
{
int mbchars;
int pos_s = 0;
Expand Down Expand Up @@ -197,11 +187,13 @@ static char ap_handle_signals()

static char ap_delete;
static char ap_special[KEYMAP_SIZE];
static char ap_nl[KEYMAP_SIZE];

static void ap_set_control_chars()
{
// In default readline these are: tab, <C-D>, <C-L>, and all the newline keys.
int specialLen = 0;
int nlLen = 0;
ap_delete = '\x04';
for(int key = 0; key < KEYMAP_SIZE; key++)
{
Expand All @@ -212,8 +204,12 @@ static void ap_set_control_chars()
ap_delete = key;
ap_special[specialLen++] = key;
}
else if (_rl_keymap[key].function == rl_newline
|| _rl_keymap[key].function == rl_complete
else if (_rl_keymap[key].function == rl_newline)
{
ap_special[specialLen++] = key;
ap_nl[nlLen++] = key;
}
else if (_rl_keymap[key].function == rl_complete
|| _rl_keymap[key].function == rl_clear_screen)
{
ap_special[specialLen++] = key;
Expand Down
Loading

0 comments on commit 4da353c

Please sign in to comment.