国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Javascript codemirror 高級應用

DesGemini / 1243人閱讀

摘要:可能是在環境或者直接在瀏覽器的控制臺中進行調試。阮老師的代碼傳送門在此這個代碼的演示程序,如下圖所示本系統的特點系統采用進行開發的。

搭建javascript在線IDE 項目地址

github:https://github.com/sixtrees/j...

這兩天在看阮一峰的《ES6標準入門》,對其中涉及到的代碼示例部分,感覺到很不方便,不知道阮老師是如何進行代碼調試的。可能是在nodejs環境或者直接在瀏覽器的控制臺中進行調試。我每次都是在nodejs命令行中進行代碼編寫,由于命令行本身的特點,有一句代碼編寫錯誤,都可能導致需要重寫所有的代碼。

像下圖中所示的情況一樣,當我們由java或者其他語言的編寫習慣造成的語法錯誤for (var item of set ),導致測試代碼沒能得到正確的輸出,這時候我們就需要重頭來過,這體驗當然是不好的,在瀏覽器的控制臺中這種情況,會好一點。但是,一旦我們不小心觸碰到了ENTER按鍵,那就悲劇了。

我也曾異想天開的認為既然nodejs可以使用node app.js來啟動nodejs程序,那為什么不試試用node test.js來進行代碼測試呢。經過測試,發現是可以的,但是這樣,我每一次都要在命令行和文本編輯器之間進行切換。

由于,我想簡單點,開發一個基于web的IDE來運行我們輸入的javascript或者es2015也就是es6代碼。經過一個晚上加一個上午的構思和代碼編寫,已經完成了基礎代碼的編寫。下圖就是這個項目的一個運行示例。利用CodeMirror插件來作為代碼編輯插件,并且根據需要,改寫了CodeMirror官方的javascript-hint.js文件,使得代碼提示的效果更豐富,同時也發現了網上大多數坑人的帖子帶來的問題,后面都要有詳細的說明。先來簡單的看一下我們的系統長什么樣吧,至于界面的設計,大家就將就的看一下,畢竟功能才是我們所需要的。

如何安裝

目前,我已經將代碼托管至github(點我)。下面,我來演示如何安裝本平臺,請大家放心,不會涉及太多復雜的東西,因為這個系統只是一個很簡單的IDE環境。

先在webstorm下看一下項目結構:

下面開始進入安裝階段。
項目采用的是express進行開發的,因此,主要的npm依賴見下面的代碼區。

  "dependencies": {
    "body-parser": "~1.17.1",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.3",
    "express": "~4.15.2",
    "hbs": "~4.0.1",
    "morgan": "~1.8.1",
    "serve-favicon": "~2.4.2"
  }

好了,我們開始連接服務器或者在自己的電腦上打開命令行(我用的msysgit,大家也可以用cmder)
進入到我們的工作文件夾,我這里用的是自己的D盤下面的nodejs文件夾,可以使用如下命令進行快速進入

Administrator@neil-PC MINGW64 /d/nodejs
$ cd
$ cd d:/nodejs
$ pwd
/d/nodejs
$ git clone https://github.com/sixtrees/js-online-running.git

克隆完成后,進入js-online-running文件夾。

執行npm安裝項目的依賴,關于npm install 如何安裝package.json文件夾下的依賴,請大家自行了解其中緣由。

$ npm install
js-online-running@0.0.0 D:
odejsjs-online-running
+-- body-parser@1.17.2
+-- cookie-parser@1.4.3
+-- debug@2.6.8
+-- express@4.15.3
+-- hbs@4.0.1
+-- morgan@1.8.1
`-- serve-favicon@2.4.3

安裝好npm的依賴之后,我們就可以使用 node bin/www來運行項目了。bin/www文件時系統啟動文件,請不要用node app.js來試圖運行本系統。
還有就是不要在bin之前加/,這是畫蛇添足。執行node bin/www后,node就會啟動localhost:3000作為項目的部署地址了,端口號可以在bin/www文件中進行修改。此時,是沒有任何輸出的,如果你是用webstorm打開的,推薦大家使用nodemon等熱部署解決方法。具體的方法,請自己自行上網查找解決方案,反正就是很簡答的那種。像用IDEA來開發java, 我會推薦大家使用JRebel來進行熱部署。這樣的東西是可以提供編程的效率的。

此時,打開瀏覽器,輸入localhost:3000,就可以看到我們的頁面了。

此時,nodejs控制臺也會輸入所有的資源請求情況。

到這里,系統的部署就完成了。就可以用這個平臺來進行js代碼的運行測試了。
總結一下,啟動項目,使用node bin/www,如果想隨電腦啟動,請自行查找如何在windows或者linux平臺下,讓nodejs項目對計算機啟動而啟動。

使用

下面,我使用阮一峰的《es6標準入門》的一個案例代碼來演示如何使用本平臺,其實這個平臺的初衷就是學了配合阮老師的書來學習的。
阮老師的代碼傳送門:在此

var a = [1,2,3,4];
var set = neww Set(a);
for(var item of a) {
  console.log(item);
}

這個代碼的演示程序,如下圖所示

本系統的特點

系統采用nodejs+express進行開發的。但是主要的實現都是靠html+javascript來實現的,我當時是想用戶傳遞自己輸入的javascript語句到后臺進行執行,但是根據常識,瀏覽器是可以直接運行javascript代碼的,因此,就想到了eval這個讓大家又愛又怕的函數來執行我們輸入的javascript語句,并且捕獲異常,將捕獲的異常信息做為bootstrap-treeview插件的數據來顯示具有層次結果的錯誤信息。(這里我可能描述的不夠準備,捕獲的是Error.

總結幾個特點:

使用最新的的CodeMirrror,包含了所有的樣式和addon。用戶可以根據自己喜歡來設置自己喜歡的代碼編輯區的配色方案。

利用CodeMirrorcursorActivity事件來完成代碼提示的觸發。網上一群坑爹的貨,居然說用onChange事件,老子的瀏覽器選項卡直接卡死,在仔細看了官方的文檔后,發現cursorActivity事件才是解決代碼提示的正確道路。

利用split函數將用戶輸入的所有的代碼按照空格進行分割,獲取所有的英文單詞,將這些單詞傳遞給一個自定義的全局變量CodeMirror.ukeys,結合javascript的關鍵字來實現代碼提示,所以,本系統能夠實現實時的代碼提示,而且可以提示用戶出入的變量名,不僅僅是javascript關鍵詞,從而給人更真實的IDE感

由于時間較多,沒有做很多的后臺的程序的編寫, 大家有興趣的,可以mysql或者mongodb來實現類似于HUE的在線IDE。

關于CodeMirror如何實現實時提示

這個問題在原生的CodeMirror有兩個問題,

問題1

一個問題就是代碼提示的時候,在沒有任何輸入的時候就會彈出所有的提示關鍵詞,這一點讓人很討厭,那么該如何改進呢。由于我們這里使用的javascript-hint.js來進行javascript代碼的提示,那我們可以修改的文件就應該是public/codemirror/addon/hint/javascript-hint.js文件,如果大家仔細的閱讀了CodeMirror的代碼,就會發現在javascript-hint.js文件中有一個函數getCompletions,該函數有一個參數叫token,這個token其實是編譯原理中所說的token,也就是一個語法分割單位,這個token是我們代碼提示的關鍵,所有的關鍵字就要跟token進行比對,如果發現token是某些關鍵字的前綴,那么這些單詞都要作為當前的關鍵字提示給用戶。
例如,下圖中,我們正在輸入的語法單詞是se,那么此時觸發的cursorActivity事件調用showHint方法,經過一系列的函數判斷,最重獲取到當前的tokense,則我們需要將所有以se為首的單詞進行彈出提示。那么,針對我們正在說的這個事情:CodeMirror在我們沒有任何輸入的時候,也會進行代碼提示,那根據分析沒有任何輸入時,觸發cursorActivity事件時,得到的token的值是"",我們只需要在getCompletions函數(這個函數就是獲取和當前用戶正在輸入的語法單詞匹配的所有關鍵詞的函數)的開始判斷token=="",如果是true,則直接返回一個空的list{}。


改寫的代碼如下:

    function getCompletions(token, context, keywords,options) {

        //這里是處理沒有任何字母輸入時也會有代碼提示的原因。
        if (token.string == "") {
            return {list:{}};;
        }
        ...
}
問題2

另外一個問題就是CodeMirror能提供的auto-complete(代碼自動完成)是需要進行按鍵綁定的,用戶通過某個按鍵組合才能觸發autocomplete事件,這對于我們寫代碼的速度肯定影響是很大。因此,我們希望在我們輸入字符的同時,界面可以給出我們實時的代碼提示,而不需要進行按鍵組合來觸發。一般網上的示例都是比較坑爹的,代碼示例如下:

editor.on("change", function () {
     editor.showHint();
});

如果你是這么用CodeMirror的,或者你正在發愁的時候,我希望我的這的總結能夠給你提供比較的幫助。繼續說,上面的代碼示例千萬不要用,因為這樣做了,瀏覽器會卡死的,而造成這種現象 的原因可能是CodeMirror內部處理的問題,我沒有仔細研究,但是經過我的仔細閱讀官方文檔和不斷摸索,我給出一個比較正確的方案來實現代碼的實時提示。

//不要用change
editor.on("cursorActivity", function () {
            //調用顯示提示
            editor.showHint();
});

如果,你是這么做的或者你剛好這么改正了,那么恭喜你,你應該得到了你要的效果。

好了,這兩個問題,就簡單論述到這里,下面還有更重要的東西需要我來論述的。

如何增加CodeMirror代碼提示的關鍵字

不失一般性,我這里就描述一下這個項目中,我是如何獲取更多的關鍵字(這里的關鍵字是指匹配用戶輸入的提示單詞)并且將這樣單詞進行匹配并跟隨原有的關鍵字進行實時提示的。

還記得剛才看過的那個代碼片段吧,上面的代碼是我為了給大家描述如何來觸發代碼實時提示的解決方案的。下面才是本項目中實際用到的代碼。下面的代碼注釋已經寫的很清楚的,首先就是利用CodeMirrorAPI來獲取用戶輸入代碼(注意是純代碼),然后利用正則來提取出所有的單詞,用match匹配后得到的是一個數組,然后將該數組傳遞給我們拓展在CodeMirror全局變量的上一個屬性ukeys。然后再調用editor.showHint()來處理實際的代碼提示。

 /**
 * 用來實時對用戶的輸入進行提示
 */
editor.on("cursorActivity", function () {
    //獲取用戶當前的編輯器中的編寫的代碼
    var words = editor.getValue() + "";
    //利用正則取出用戶輸入的所有的英文的字母
    words = words.replace(/[a-z]+[-|"]+[a-z]+/ig, "").match(/([a-z]+)/ig);
    //將獲取到的用戶的單詞傳入CodeMirror,并在javascript-hint中做匹配
    CodeMirror.ukeys = words;
    //調用顯示提示
    editor.showHint();
});

上面的描述希望沒有給您帶來閱讀上的不順暢,下面,我將描述一下如何在javascript-hint.js文件中如何接受我們傳入的ukeys以及如何利用內置的函數快速完成關鍵字的匹配并將匹配的結果疊加進行關鍵字的提示。

首先是javascript-hint.js中javascript代碼提示的主調函數

如果你對下面的文字描述不感興趣,請移步github(點我),直接看源碼(有注釋).

    /**
     * 主調函數,加入了我自己定義的一個CodeMirror.ukeys變量,用來向CodeMirror傳遞用戶
     * 輸入的所有的單詞
     * @param editor
     * @param options
     * @returns {{list, from, to}|*}
     */
    function javascriptHint(editor, options) {

        var ukeys =  CodeMirror.ukeys;//獲取用戶的所有的輸入的單詞
        return scriptHint(editor, javascriptKeywords,ukeys,
            function (e, cur) {
                return e.getTokenAt(cur);
            },
            options);
    };

如上面的代碼所示,在javascriptHint函數中,我們獲取到CodeMirror.ukeys,并將ukeys傳遞給scriptHint函數。scriptHint函數的主要代碼如下:

    //這是處理關鍵字匹配的關鍵函數實現
    function scriptHint(editor, keywords, ukeys,getToken, options) {
        // Find the token at the cursor
        var cur = editor.getCursor(), token = getToken(editor, cur);
        if (/(?:string|comment)/.test(token.type)) return;
        token.state = CodeMirror.innerMode(editor.getMode(), token.state).state;

        // If it"s not a "word-style" token, ignore the token.
        if (!/^[w$_]*$/.test(token.string)) {
            token = {
                start: cur.ch, end: cur.ch, string: "", state: token.state,
                type: token.string == "." ? "property" : null
            };
        } else if (token.end > cur.ch) {
            token.end = cur.ch;
            token.string = token.string.slice(0, cur.ch - token.start);
        }

        var tprop = token;
        // If it is a property, find out what it is a property of.
        while (tprop.type == "property") {
            tprop = getToken(editor, Pos(cur.line, tprop.start));
            if (tprop.string != ".") return;
            tprop = getToken(editor, Pos(cur.line, tprop.start));
            if (!context) var context = [];
            context.push(tprop);
        }
        return {
            list: getCompletions(token, context, keywords,ukeys, options),
            from: Pos(cur.line, token.start),
            to: Pos(cur.line, token.end)
        };
    }

從上面的代碼中,可以看到scriptHint函數主要是獲取list(匹配的關鍵字)。這也印證了上面我在處理沒有任何輸入時,判斷token==""返回的是{list:{}}是正確的寫法。這個函數的改動很小,主要還是將ukeys繼續向下傳遞 list: getCompletions(token, context, keywords,ukeys, options)。所以的單詞匹配都是在getCompletions函數中實現的,在這個函數中,提供了很多內置函數,我們只需要添加幾行代碼就可以完成附加關鍵詞的功能了。該函數的改動后的代碼如下所示:

 /**
     *
     * @param token 當前光標下用戶正在輸入的單詞
     * @param context
     * @param keywords 關鍵字列表,本文件內定義
     * @param ukeys 用戶添加的關鍵字
     * @param options
     * @returns {*}
     */
    function getCompletions(token, context, keywords, ukeys,options) {

        //這里是處理沒有任何字母輸入時也會有代碼提示的原因。
        if (token.string == "") {
            return {list:{}};
        }
        var found = [], start = token.string, global = options && options.globalScope || window;

        function maybeAdd(str) {
            if (str.lastIndexOf(start, 0) == 0 && !arrayContains(found, str)) found.push(str);
        }

        function gatherCompletions(obj) {
            if (typeof obj == "string") forEach(stringProps, maybeAdd);
            else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
            else if (obj instanceof Function) forEach(funcProps, maybeAdd);
            forEach(ukeys,maybeAdd);//匹配我們傳進來的用戶輸入的代碼中的所有的單詞
            forAllProps(obj, maybeAdd)
        }

        if (context && context.length) {
            // If this is a property, see if it belongs to some object we can
            // find in the current environment.
            var obj = context.pop(), base;
            if (obj.type && obj.type.indexOf("variable") === 0) {
                if (options && options.additionalContext)
                    base = options.additionalContext[obj.string];
                if (!options || options.useGlobalScope !== false)
                    base = base || global[obj.string];
            } else if (obj.type == "string") {
                base = "";
            } else if (obj.type == "atom") {
                base = 1;
            } else if (obj.type == "function") {
                if (global.jQuery != null && (obj.string == "$" || obj.string == "jQuery") &&
                    (typeof global.jQuery == "function"))
                    base = global.jQuery();
                else if (global._ != null && (obj.string == "_") && (typeof global._ == "function"))
                    base = global._();
            }
            while (base != null && context.length)
                base = base[context.pop().string];
            if (base != null) gatherCompletions(base);
        } else {
            // If not, just look in the global object and any local scope
            // (reading into JS mode internals to get at the local and global variables)
            for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
            for (var v = token.state.globalVars; v; v = v.next) maybeAdd(v.name);
            if (!options || options.useGlobalScope !== false)
                gatherCompletions(global);
            forEach(keywords, maybeAdd);
        }
        //console.log(found);
        return found;
    }

我們只在gatherCompletions函數中添加了一條語句
好了,如果你這么做了,就可以完成我們輸入的變量也會出現在CodeMirror中了。

附贈的福利

CodeMirror還提供了sql的代碼提示的附加功能。主要針對的有MSSQLmysqlmariadb以及PLSQL。本文以一個實際的項目中的實際使用來演示如何按照上文的描述來修改對應的sql-hint.js中的內容來完成:

取消沒有輸入任何有效字符時的代碼提示問題

cursorActivity設置代碼實時提示

增加表的字段到代碼提示中去。

問題1

sql對應的關鍵字信息在CodeMirror/mode/sql/sql.js中,我在項目中用的是類似于oracle的數據庫,因此我們在sql.js增加了PLSQL的部分關鍵字,如下圖所示(更詳細的信息,請參考我的github)

然后修改CodeMirror/addon/hint/sql-hint.js中的 CodeMirror.registerHelper("hint", "sql", function (editor, options) {函數中添加如下圖所示的代碼,同樣是判斷token是否=="".

問題2及問題3

由于問題2和問題三都是在cursorActivity中編寫。直接上代碼來描述吧。
獲取所有的表字段
我的項目中,在編寫sql的頁面有所有的字段信息,所以我就用jquery直接獲取了,如果大家的字段不在頁面中,那就用ajax請求在頁面一次加載的時候就保存在頁面的一個全局變量中吧。一定不要讓瀏覽器都去發ajax請求去獲取字段列表,那樣不卡死才怪。

 $(function(){
        console.log("get field");
        $(".field .easytree-title").each(function (){
            var tmp =$(this).html();
            tmp = tmp.substring(0,tmp.indexOf("["));
            window.fields.push(tmp);
        })
    });

上面的代碼獲取了我的項目中的所有的字段,并作為一個數組存儲在全局變量window.fields上。然后再在cursorActivity中傳遞到sql-hint.js中。
字段傳遞及關鍵字的匹配

 editor.on("cursorActivity",function(){
        CodeMirror.ukeys =  window.fields;
        editor.showHint();
    });

sql-hint.js文件的改寫2
CodeMirror.registerHelper("hint", "sql", function (editor, options) {中添加如下圖所示的代碼,就完成了單詞的匹配及后續的匹配到的單詞的顯示。

上圖的代碼也就是利用封裝好的函數讀取CodeMirror.ukeys并進行關鍵字匹配,如果匹配成功則加入到result中,最后返回的list就是result.

最后上一個效果圖。所有改動后的文件都在本次示例的項目中。github地址(點我)

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97017.html

相關文章

  • 如何制作一款在線編譯器

    摘要:在文章開始之前先展示一下我自己做的在線編譯器點此預覽大概三四個月之前我開始有了制作在線編譯器的想法,在此之前我接觸過很多的在線編譯器,如等,這些都非常優秀且有著龐大的用戶群體的編譯器。是一個用于瀏覽器的實現的多功能文本編輯器。 在文章開始之前先展示一下我自己做的在線編譯器 JS-Encoder: 點此預覽 showImg(https://i.loli.net/2019/07/21/5d...

    Alan 評論0 收藏0
  • 手把手教你搭建網頁代碼編輯器

    摘要:如下,我們創建一個編輯代碼的編輯器上邊的代碼復制到文件即可運行。完整的拓展列表在這里如下示例展示了開啟語法糾錯直接將代碼復制到文件即可運行當然,的功能十分豐富,比如按鍵映射主題定制模式等,更深入的使用可以查閱官網。 CodeMirror CodeMirror 是一個可以鑲嵌到 Web 頁面中代碼編輯器組件。它的核心代碼庫僅僅提供了編輯器功能,沒有提供像是 自動補全, 語法糾錯 等IDE...

    ranwu 評論0 收藏0
  • 手把手教你搭建網頁代碼編輯器

    摘要:如下,我們創建一個編輯代碼的編輯器上邊的代碼復制到文件即可運行。完整的拓展列表在這里如下示例展示了開啟語法糾錯直接將代碼復制到文件即可運行當然,的功能十分豐富,比如按鍵映射主題定制模式等,更深入的使用可以查閱官網。 CodeMirror CodeMirror 是一個可以鑲嵌到 Web 頁面中代碼編輯器組件。它的核心代碼庫僅僅提供了編輯器功能,沒有提供像是 自動補全, 語法糾錯 等IDE...

    Julylovin 評論0 收藏0
  • Vue-Codemirror-Lite: 在線代碼編輯器 Codemirror 的輕量級 Vue.j

    摘要:項目地址為了減少打包后的體積,所有的語言模式和插件在默認的情況下沒有加載要使用它們見本地運行實例編輯器的值傳遞給實例的配置選項前往查看更多可用選項中包含了許多的語言模式默認情況下所有 Vue-Codemirror-Lite 項目地址:https://github.com/cnu4/vue-codemirror-lite CodeMirror Component For Vue.js (...

    sushi 評論0 收藏0
  • 在線代碼編輯器利器-codeMirror

    摘要:說明是一款十分強大的代碼編輯插件,提供了十分豐富的,最近在項目中用到了這款插件,做一個記錄。 說明 codeMirror是一款十分強大的代碼編輯插件,提供了十分豐富的API,最近在項目中用到了這款插件,做一個記錄。 官網 github地址 安裝 下載安裝包 在github上直接download 或者 clone npm 安裝 npm install --save code...

    Doyle 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<