Search code examples
javascripthtmljquerykeypressjquery-terminal

Changing the prompt to: ('') then back to previous after enter key pressed on jquery terminal


I have a JQuery terminal that i'm trying to make it similar to the MacOS terminal. When using the MacOS terminal, I noticed that whenever you press enter, the prompt will disappear for a sec, the reappear very quickly. Im trying to find out how I can make the same thing in my Jquery terminal, but work just like it, but without one problem that I have, here is the code so far:

<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/jquery"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery.terminal/js/jquery.terminal.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery.terminal/css/jquery.terminal.min.css"/>
</head>
<body>
<script>
$('body').terminal({
    echo: function(...args) {
        this.echo(args.join(" "))
    }
}, {

keydown: function(e) {
    
    if(e.key === 'Enter' || e.keyCode === 13) {
         
    var checkit = this.get_prompt();
         
                setTimeout(() => {
                    this.set_prompt('')         
                }, 10);
         
                setTimeout(() => {
                    this.set_prompt(checkit)
                }, 200);
  
}   else {
             
    }
},
    greetings: '',
    checkArity: false,
    prompt: 'MyNormalPrompt>'
    
});
</script>
</body>
</html>

Problem: as you can see if you try the demo, the prompt does disappear and then reappear just how I wanted, but if you try to press enter too quick, or hold it down, the prompt will just disappear completely.

What I tried: I took a look at this: Detect Long Press on Enter/OK Key on a caph-list Item which gave information of how to detect a long enter key press in javascript, and when implementing some of the code there to my jquery terminal, it sorta helped, but still wouldnt make the prompt stop disappearing.


Solution

  • You can use pause/resume:

    echo: function(...args) {
        term.pause();
        this.echo(args.join(" "));
        setTimeout(() => {
           this.resume();
        }, 200);
    }
    

    pause/resume is the same as returning a promise and resolving after a delay:

    const delay = time => new Promise(resolve => setTimeout(resolve, time));
    
    echo: async function(...args) {
        this.echo(args.join(" "))
        await delay(200);
    }
    

    I don't think there is a way to do this globally for all commands. But you can create a function that abstracts this away:

    const timeout = 200;
    
    const delayed = (fn) {
        return function(...args) {
            term.pause();
            fn.apply(this, args);
            setTimeout(() => {
               this.resume();
            }, timeout);
        };
    };
    
    echo: delayed(function(...args) {
        this.echo(args.join(" "));
    })
    

    You can do the same with the async approach.

    const timeout = 200;
    
    const delayed = (fn) {
        return async function(...args) {
            await fn.apply(this, args);
            await delay(timeout);
        };
    };
    

    In this case the function echo can be async or normal function:

    echo: delayed(async function(...args) {
        this.echo(args.join(" "));
    })
    

    You can also delay every method of an object, it's best to use a function as the interpreter where you can parse the command yourself and handle it on your own.

    const timeout = 200;
    const delay = time => new Promise(resolve => setTimeout(resolve, time));
    
    const delayed = obj => {
        return async function(command) {
            if (!command) {
                return;
            }
            const cmd = $.terminal.parse_command(command);
            if (obj[cmd.name]) {
                obj[cmd.name].apply(this, cmd.args);
            } else {
                this.error(`Wrong command: ${cmd.name}`);
            }
            await delay(timeout);
        }
    };
    
    const term = $('body').terminal(delayed({
        echo(...args) {
            this.echo(args.join(' '));
        }
    }));