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

RStudio code mode for Ace #14356

Open
seanbirchall opened this issue Mar 1, 2024 · 3 comments
Open

RStudio code mode for Ace #14356

seanbirchall opened this issue Mar 1, 2024 · 3 comments
Labels
enhancement layout Issues relating to layout, appearance, pane organization, etc.

Comments

@seanbirchall
Copy link

Any idea how / if it'd be possible to create a custom code mode for Ace called rstudio? Opened this with Ace too ajaxorg/ace#5493.

It looks like I could probably just start from here and pull in all the other necessary requirements. The code here looks very similar to how standard boilerplate code modes for Ace looks so maybe this won't be too hard.

RStudio isn't spinning up some web server or service worker that I'm not aware of in the background for completions, linting... etc with Ace right? So I could probably do something like below and get RStudio like code completions in the browser, so long as I get everything together and working? If so then I imagine I can just compile all this to a single code mode file.

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>R Ace Editor</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ext-language_tools.js"></script>
</head>
<body>

<div id="editor" style="height: 75vh; width: 100%;"></div>

<script>
    // Create Ace editor instance
    var editor = ace.edit("editor");
    editor.session.setMode("ace/mode/r");
    editor.setOptions({
        enableBasicAutocompletion: true,
        enableSnippets: true,
        enableLiveAutocompletion: true
    });

    // Add custom R language mode
    ace.define("ace/mode/r_studio", ["require", "exports", "module"], function (require, exports, module) {
        
        var Editor = require("ace/editor").Editor;
        var EditSession = require("ace/edit_session").EditSession;
        var Range = require("ace/range").Range;
        var oop = require("ace/lib/oop");
        var TextMode = require("ace/mode/text").Mode;
        var Tokenizer = require("ace/tokenizer").Tokenizer;
        var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules;
        var RHighlightRules = require("mode/r_highlight_rules").RHighlightRules;
        var RCodeModel = require("mode/r_code_model").RCodeModel;
        var RMatchingBraceOutdent = require("mode/r_matching_brace_outdent").RMatchingBraceOutdent;
        var AutoBraceInsert = require("mode/auto_brace_insert").AutoBraceInsert;
        var unicode = require("ace/unicode");

        var Mode = function(suppressHighlighting, session)
        {
            if (suppressHighlighting)
                this.$tokenizer = new Tokenizer(new TextHighlightRules().getRules());
            else
                this.$tokenizer = new Tokenizer(new RHighlightRules().getRules());

            this.codeModel = new RCodeModel(session, this.$tokenizer);
            this.foldingRules = this.codeModel;
            this.$outdent = new RMatchingBraceOutdent(this.codeModel);
        };
        oop.inherits(Mode, TextMode);

        (function()
        {
            this.getLanguageMode = function(position) {
                return "R";
            };

            this.checkOutdent = function(state, line, input) {
                return this.$outdent.checkOutdent(state, line, input);
            };

            this.autoOutdent = function(state, session, row) {
                return this.$outdent.autoOutdent(state, session, row);
            };

            this.tokenRe = new RegExp("^[" + unicode.wordChars + "._]+", "g");
            this.nonTokenRe = new RegExp("^(?:[^" + unicode.wordChars + "._]|\\s)+", "g");

            // NOTE: these override fields used for 'auto_brace_insert'
            this.$complements = {
                    "(": ")",
                    "[": "]",
                    '"': '"',
                    "'": "'",
                    "{": "}",
                    "`": "`"
                    };
            this.$reOpen  = /^[{(\["'`]$/;
            this.$reClose = /^[})\]"'`]$/;

            this.getNextLineIndent = function(state, line, tab, row)
            {
                return this.codeModel.getNextLineIndent(state, line, tab, row);
            };

            this.allowAutoInsert = this.smartAllowAutoInsert;

            this.getIndentForOpenBrace = function(openBracePos)
            {
                return this.codeModel.getIndentForOpenBrace(openBracePos);
            };

            this.$getIndent = function(line) {
                var match = line.match(/^(\s+)/);
                if (match) {
                    return match[1];
                }

                return "";
            };

            this.$id = "mode/r";
        }).call(Mode.prototype);
        exports.Mode = Mode;
    });
</script>

</body>
</html>
@seanbirchall seanbirchall added enhancement new New incoming issues, ready for initial review. labels Mar 1, 2024
@ronblum
Copy link
Contributor

ronblum commented Mar 5, 2024

@seanbirchall Thank you for bringing this up!

@kevinushey Any thoughts? Pinging you because you understand this better than me. 🙂

@ronblum ronblum added layout Issues relating to layout, appearance, pane organization, etc. and removed new New incoming issues, ready for initial review. labels Mar 5, 2024
@kevinushey
Copy link
Contributor

RStudio isn't spinning up some web server or service worker that I'm not aware of in the background for completions, linting... etc with Ace right? So I could probably do something like below and get RStudio like code completions in the browser, so long as I get everything together and working? If so then I imagine I can just compile all this to a single code mode file.

Assuming I'm understanding your question, RStudio uses its own completion system independent of Ace, so you'd have to wire up your own completion solution using the existing Ace tools. (RStudio relies on a lot of the existing R session state for the completions it provides, so it needs more context than is just available in the Ace editor instance.)

@seanbirchall
Copy link
Author

seanbirchall commented Mar 6, 2024

I would say I'm trying to understand what is covered in Ace? For instance the there's a custom R mode being defined which I included above, but also code for, r_highlight_rules, r_code_model, r_matching_brace_outdent which I think could all be useful to me. Right now I'm using an R package called shinyAce for code completions in my Ace Editor. I would like to try and pull all of this back into JavaScript and incorporate some of the great formatting and completion logic from RStudio.

I'm aware that there is probably a lot more happening behind the scenes like capturing packages, functions, and everything else going on in the R Environment. Which currently isn't an issue for me as shinyAce actually already takes care of all that. The formatting and what is probably r_code_model is all off in my current implementation as well as some edge cases like r_matching_brace_outdent.

With shinyAce I can define a custom mode that is packaged with Ace or create my own. So I'm trying to create my own that makes my IDE app feel more like RStudio. It might be easier to just try writing out some code in it here to see what I mean. Would me creating a custom mode using some of the RStudio code above make the code writing experience better (by better I mean more like RStudio)?

Here's some shinyAce code worth looking at if you're trying to understand what I mean by using shinyAce/R for my current code completions. I could also implement some of this there, but I already notice that the code completions in R are slower than RStudio/JS.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement layout Issues relating to layout, appearance, pane organization, etc.
Projects
None yet
Development

No branches or pull requests

3 participants