29

I have enabled correction (I wouldn't call it autocorrection specifically because of this issue) in zsh by enabling setopt correct in my .zshrc.

Now, when I type dtae in a terminal, I get:

dtae        
zsh: correct 'dtae' to 'date' [nyae]? y
Tue Mar 31 11:39:31 CEST 2015

At this point I would like zsh to remember my decision. So the next time I type dtae it should automatically correct to date [1]. However, this does not happen, and zsh is again asking me what to do:

dtae
zsh: correct 'dtae' to 'date' [nyae]?

[1] Unless, of course, if at that time there exists an actual dtae command or alias.

Update:

I have managed to modify the zsh source code (file utils.c, function spckword) to create a custom file containing the aliases automatically created with the invocation of zsh's "correct" functionality:

original:

if (x == 'y' || x == ' ' || x == '\t') 
{
    *s = dupstring(best);
    if (hist)
    hwrep(best);
}

modified:

if (x == 'y' || x == ' ' || x == '\t')
{
    char *aliaspath = getenv("HOME");
    strcat(aliaspath, "/.zsh_correct_aliases");
    FILE *out = fopen(aliaspath, "ab+");
    fprintf(out, "alias %s=\'", *s);
    *s = dupstring(best);
    fprintf(out, "%s\'\n", *s);
    fclose(out);
    if (hist)
    hwrep(best);
}

Upon executing dtae, the following line is added to the file ~/.zsh_correct_aliases:

alias dtae='date'

However, I don't know how to source the newly modified ~/.zsh_correct_aliases file in-place.

myradio
  • 333
  • 1
  • 10
shrx
  • 445
  • 4
  • 6
  • 1
    Do you want it remembered only for the shell process lifetime, or that information stored in files. Should that remembered correction be immediately available to all currently running shell instances? Do you want the remembered correction removed when `dtae` spawns into existence or just disabled temporarily? – Stéphane Chazelas Mar 31 '15 at 11:23
  • 1
    @StéphaneChazelas 1) Stored in a single file would be best. 2) It would be a plus, but not strictly necessary. 3) Removed until `dtae` exists, then reinstated if/when `dtae` is not defined anymore. – shrx Mar 31 '15 at 11:38
  • 1
    @StéphaneChazelas please see my update, am I heading in the right direction? – shrx Mar 31 '15 at 13:48
  • 3
    It would probably make more sense to call a dedicated zsh hook function there (like a `command_not_found_handler` but at parsing time instead of runtime), and then implement the logic in zsh code. – Stéphane Chazelas Mar 31 '15 at 14:01
  • 1
    See the `precmd` hook to run commands before each prompt (like sourcing your zsh aliases) – Stéphane Chazelas Mar 31 '15 at 14:02
  • 1
    @StéphaneChazelas I understand what you mean with the handler but since I have absolutely no experience with C programming I'm afraid this is out of my reach. Will look into `precmd`. – shrx Mar 31 '15 at 14:03
  • 1
    You could suggest it to the zsh developers (zsh-workers mailing list). They're usually very reactive. – Stéphane Chazelas Mar 31 '15 at 14:28
  • 7
    I do not think this is considered good practice... I feel it is much more efficient to learn how to type correctly. – Peschke Sep 24 '15 at 20:40
  • 2
    I'm just curious, for this specific use at least, why not just have the code add the aliases to the end of .zshrc, or somehow do that same but by cating .zsh_correct_aliases into .zshrc. Obscursing that with some hashing, obscurity/variables, or better, as needed for security – olaf atchmi Jun 22 '16 at 10:18
  • what if you changed autocorrect so that `dtae` becomes `alias dtae=date; date`? – webb Jan 14 '17 at 19:28

2 Answers2

3

You could base your code on the built-in alias defined here

HashTable ht = aliastab;
ht->addnode(ht, ztrdup(wrong_value),
            createaliasnode(ztrdup(right_value), 0));

(not tested)

And add source ~/.zsh_correct_aliases to you .zshrc


EDIT: tested with source:

char *aliaspath = getenv("HOME");
strcat(aliaspath, "/.zsh_correct_aliases");

FILE *out = fopen(aliaspath, "ab+");
fprintf(out, "alias %s=\'", *s);

HashTable ht = aliastab;
ht->addnode(ht, ztrdup(*s),
    createaliasnode(ztrdup(best), 0));

*s = dupstring(best);
fprintf(out, "%s\'\n", *s);
fclose(out);
if (hist)
    hwrep(best);

It gives:

$ setopt correct 
$ dtea    
zsh: correct 'dtea' to 'date' [nyae]? y
lun. janv.  8 01:03:55 CET 2018  
$ alias  
dtea=date
$ dtea    
lun. janv.  8 01:07:42 CET 2018  
1

You could define a precmd function that sources ~/.zsh_correct_aliases.

William Hay
  • 323
  • 1
  • 10