PrismJS / prism

Lightweight, robust, elegant syntax highlighting.
https://prismjs.com
MIT License
12.24k stars 1.29k forks source link

Possibly useful mod for the command-line plugin #1021

Open oletizi opened 8 years ago

oletizi commented 8 years ago

Hi folks,

I needed to hack in support for multiple different prompts in a single command-line block to the command-line plugin. It's pretty straightforward (see code snippet below).

It adds an option to specify prompts on a per-line basis by setting the prompt attribute to something like this:

1|myPromptText;2-3|myOtherPrompt;4,8|myThirdPrompt

Of course, if you don't use the augmented prompt syntax, then the prompt syntax works the standard way.

You may or may not want to add support for this to the command-line module, but I thought since I found it useful, others may, too.

Cheers, --Orion


        if (promptText !== '') {
            if (promptText.includes('|')) {
                // promptText format : 1|myPromptText;2-3|myOtherPrompt;4,8|myThirdPrompt
                // promptChunks: an array of
                var promptChunks = promptText.split(';');
                // prompts: an array of line number => prompt text
                var prompts = [];
                for (var i = 0; i < promptChunks.length; i++) {
                    // promptSections: 0 - line range; 1 - prompt value
                    var promptSections = promptChunks[i].split('|');
                    var promptValue = promptSections[1];
                    var promptRanges = promptSections[0].split(',');
                    for (var p = 0; p < promptRanges.length; p++) {
                        var promptRange = promptRanges[p].split('-');
                        var promptStart = parseInt(promptRange[0]);
                        var promptEnd = promptStart;
                        if (promptRange.length === 2) {
                            promptEnd = parseInt(promptRange[1]);
                        }
                        if (!isNaN(promptStart) && !isNaN(promptEnd)) {
                            for (var j = promptStart; j <= promptEnd; j++) {
                                var index = j-1;
                                prompts[index] = promptValue;
                            }
                        }
                    }
                }
                for (var i = 0; i < lines.length; i++) {
                    var thePrompt = typeof prompts[i] === "undefined" ? ": >" : prompts[i];
                    lines[i] = '';
                }
                lines = lines.join('');
            } else {
                lines = lines.join('');
            }
        } else {
            var user = pre.getAttribute('data-user') || 'user';
            var host = pre.getAttribute('data-host') || 'localhost';
            lines = lines.join('');
        }
derek-shnosh commented 5 years ago

@oletizi, I stumbled upon this while trying to find a way to have prompts for switch configuration examples. Having no JS experience, I took a stab at adapting your hack to the changes in the current command-line plugin but can't seem to get it working quite right.

Whenever I configure multiple prompts, they all return undefined they work but it seems that the undefined value is appended as many times as the line number (n); if you have an opportunity to take a look, I'd greatly appreciate any input you may have.

Here is a fiddle for reference

image

Modified hack...

    if (promptText !== '') {
        if (promptText.includes('|')) {
            // promptText format : 1|myPromptText;2-3|myOtherPrompt;4,8|myThirdPrompt
            // promptChunks: an array of
            var promptChunks = promptText.split(';');
            // prompts: an array of line number => prompt text
            var prompts = [];
            for (var i = 0; i < promptChunks.length; i++) {
                // promptSections: 0 - line range; 1 - prompt value
                var promptSections = promptChunks[i].split('|');
                var promptValue = promptSections[1];
                var promptRanges = promptSections[0].split(',');
                for (var p = 0; p < promptRanges.length; p++) {
                    var promptRange = promptRanges[p].split('-');
                    var promptStart = parseInt(promptRange[0]);
                    var promptEnd = promptStart;
                    if (promptRange.length === 2) {
                        promptEnd = parseInt(promptRange[1]);
                    }
                    if (!isNaN(promptStart) && !isNaN(promptEnd)) {
                        for (var j = promptStart; j <= promptEnd; j++) {
                            var index = j-1;
                            prompts[index] = promptValue;
                        }
                    }
                }
            }
            for (var i = 0; i < promptLines.length; i++) {
                var promptText = typeof prompts[i] === "undefined" ? ": >" : prompts[i];
                promptLines[i] = '<span data-prompt="' + promptText + '"></span>';
            }
            promptLines = promptLines.join('<span data-prompt="' + promptText + '"></span>');
        } else {
            promptLines = promptLines.join('<span data-prompt="' + promptText + '"></span>');
        }
    } else {
        var user = getAttribute('data-user', 'user');
        var host = getAttribute('data-host', 'localhost');
        promptLines = promptLines.join('<span data-user="' + user + '" data-host="' + host + '"></span>');
    }
derek-shnosh commented 5 years ago

Well then, guess I just needed a clearer head; got it sorted out but would appreciate any validation.

First, removed the redundant join content after the for loop.

        promptLines = promptLines.join('');

Then only ended up with one extra line being marked as undefined (or : >), so I updated the for loop to compare i against promptLines.length-1.

        for (var i = 0; i < promptLines.length-1; i++) {

Modified hack (working)...

Fiddle

image

    if (promptText !== '') {
        if (promptText.includes('|')) {
            // promptText format : 1|myPromptText;2-3|myOtherPrompt;4,8|myThirdPrompt
            // promptChunks: an array of
            var promptChunks = promptText.split(';');
            // prompts: an array of line number => prompt text
            var prompts = [];
            for (var i = 0; i < promptChunks.length; i++) {
                // promptSections: 0 - line range; 1 - prompt value
                var promptSections = promptChunks[i].split('|');
                var promptValue = promptSections[1];
                var promptRanges = promptSections[0].split(',');
                for (var p = 0; p < promptRanges.length; p++) {
                    var promptRange = promptRanges[p].split('-');
                    var promptStart = parseInt(promptRange[0]);
                    var promptEnd = promptStart;
                    if (promptRange.length === 2) {
                        promptEnd = parseInt(promptRange[1]);
                    }
                    if (!isNaN(promptStart) && !isNaN(promptEnd)) {
                        for (var j = promptStart; j <= promptEnd; j++) {
                            var index = j-1;
                            prompts[index] = promptValue;
                        }
                    }
                }
            }
            for (var i = 0; i < promptLines.length-1; i++) {
                var promptText = typeof prompts[i] === "undefined" ? ": >" : prompts[i];
                promptLines[i] = '<span data-prompt="' + promptText + '"></span>';
            }
            promptLines = promptLines.join('');
        } else {
            promptLines = promptLines.join('<span data-prompt="' + promptText + '"></span>');
        }
    } else {
        var user = getAttribute('data-user', 'user');
        var host = getAttribute('data-host', 'localhost');
        promptLines = promptLines.join('<span data-user="' + user + '" data-host="' + host + '"></span>');
    }
Aaron-Gonz commented 4 years ago

This would be a great enhancement as some routers / switches have several different command modes with their corresponding prompts.

Cisco IOS Example: Router> | - User EXEC mode Router# | - Privileged EXEC mode Router(config)# | - Configuration mode (notice the # sign indicates this is accessible only at privileged EXEC mode) Router(config-if)# | - Interface level within configuration mode Router(config-router)# | - Routing engine level within configuration mode Router(config-line)# | - Line level (vty, tty, async) within configuration mode

derek-shnosh commented 4 years ago

@VoIP-Dude - the code snippet I posted above works if you're comfortable modifying your local version yourself.

I have an example of what you're talking about on my site.

Given, it is a but cumbersome to manage with the data-prompt attribute; here's the source for the changing prompt table.

<pre class="command-line language-cisco-nxos" data-prompt="1|NX-OSv(config)#;2|NX-OSv#">
<code>end
copy run start</code></pre>
Aaron-Gonz commented 4 years ago

@derek-shnosh I tried modifying my local copy of prism.js (v1.21.0) with the snippet you posted on Mar 28, 2019 but couldn't get it to work. Are you changing the command-line plugin section in prism.js or adding new lines of code? Have you tested with PrismJS version 1.21.0?

I'm not sure if the plugins and languages I'm using makes a difference either but here's a link to the custom version I'm using in case you wanted to have a crack at it and share as a fiddle ;) .

Thanks!

derek-shnosh commented 4 years ago

@VoIP-Dude I'm still using whatever version that was current-ish when I fumbled through the code to make the "tweak" work. The Fiddle from my original response has the entire .js, looks like it was version 1.15.

I just took @oletizi's hack and tacked it on to the end of the script, then modified a couple lines to get it working; couldn't tell you which anymore to be honest. Could probably diff his hack and my tweak to find out what changed.