ملاحظة المحرر
في
المقالة الأخيرة ، تحدثنا عن إصدار لوحة تحكم Voximplant ، دون أن ننسى ذكر IDE المحدث. اليوم نكرس سلسلة
طويلة منفصلة لهذه الأداة - وصف زميلنا
Geloosa بعناية كل من عملية اختيار التكنولوجيا والتنفيذ مع علامات التبويب ، الإكمال التلقائي وأنماط مخصصة. اجلس أكثر ملاءمة ، وخصص بقية شؤونك وانتقل إلى حل المشكلات ، حيث ينتظر الشجاعة في موناكو فضوليًا - لا تنزلق ، فهناك الكثير منهم :) استمتع بالقراءة.
أي مكتبة تختارها لتحرير الكود؟
ينتج Npm 400+ نتائج لمحرر التعليمات البرمجية. بالنسبة للجزء الأكبر ، فهذه عبارة عن ملفات غلاف UI للعديد من libs الأكثر شيوعًا والتي تم إعدادها لإطار عمل أو مشروع معين ، ومكونات إضافية لنفس libs أو شوكاتهم مع تعديلات لأنفسهم ، وكذلك ليس لتحرير الكود في المستعرض ، فهم ببساطة دخلوا في الإخراج بالكلمات الرئيسية. لذلك ، لحسن الحظ ، فإن الخيار أضيق بكثير. عدد قليل من libs - la
CodeFlask ، وخفيفة الوزن ، ولكن ليست وظيفية للغاية ، مصممة
للقصاصات الصغيرة والأمثلة التفاعلية ، ولكن ليس ل IDE على شبكة الإنترنت كاملة مع الوظائف التي اعتدنا عليها في محرري سطح المكتب.
في النهاية ، لدينا 3 مكتبات للاختيار من بينها:
Ace و
CodeMirror و
Monaco Editor . وأول هذه ، CodeMirror ، كانت مبادرة خاصة من قبل Berliner
Marijn Haverbeke ، الذي كان بحاجة إلى محرر كود التمرين في برنامجه التعليمي عبر الإنترنت ،
Eloquent JavaScript . تم إصدار النسخة الأولى من المحرر في عام 2007. في عام 2010 ، تم تقديم الإصدار الأول من Ace في JSConf.eu في نفس برلين ، التي طورتها Ajax.org بعد ذلك لسحابة IDE Cloud9 الخاصة بها (في الواقع ، يرمز Ace إلى Ajax.org Cloud9 Editor). في عام 2016 ، تم شراء Cloud9 بواسطة Amazon وهو الآن جزء من AWS. الأحدث ، Monaco Editor ، هو أحد مكونات VS Code وتم نشره بواسطة Microsoft في نهاية عام 2015.
كل محرر له نقاط القوة والضعف الخاصة به ؛ يتم استخدام كل محرر في أكثر من مشروع كبير. على سبيل المثال ، يتم استخدام CodeMirror في أدوات مطوري Chrome و Firefox ، و IDE في Bitbucket ، و RunKit في npm ؛ Ace - في Codecademy ، أكاديمية خان ، MODX ؛ موناكو - في GitLab IDE و CodeSandbox. فيما يلي مخطط مقارنة قد يساعدك في اختيار المكتبة الأنسب لمشروعك.
| المكتبات |
| الآس | CodeMirror | موناكو |
المطور | Cloud9 IDE (Ajax.org) ، الآن جزء من AmazonMozilla | مارين هافربيكي | مايكروسوفت |
دعم المتصفح | Firefox ^ 3.5 الكروم Safari ^ 4.0 IE ^ 8.0 أوبرا ^ 11.5 | Firefox ^ 3.0 الكروم Safari ^ 5.2 IE ^ 8.0 أوبرا ^ 9.2 | Firefox ^ 4.0 الكروم Safari (v -؟) IE ^ 11.0 أوبرا ^ 15.0 |
دعم اللغة (تسليط الضوء على بناء الجملة) | > 120 | > 100 | > 20 |
عدد الشخصيات في أحدث الإصدارات على cndjs.com | 366 608 (الإصدار 1.4.3) | 394269 (الإصدار 5.4.0) | 2،064،949 (v0.16.2) |
وزن أحدث الإصدارات ، غزيب | 2.147 كيلو بايت | 1.411 كيلو بايت | 10.898 كيلوبايت |
أداء | DOM | DOM | DOM و <canvas> جزئيًا (للتمرير والتصغير) |
الوثائق | 7 من 10: لا بحث ، ليس واضحًا دائمًا أن أساليب العودة ، وهناك شكوك في اكتمال وأهمية (ليست كل الروابط تعمل في قفص الاتهام) | 6 من 10: تم دمجها مع دليل المستخدم ، البحث عن طريق Ctrl + F ، هناك شكوك حول الاكتمال | 9 من 10: جميل ، مع البحث و إشارة الصليب -1 نقطة لعدم وجود تفسير لبعض الأعلام التي طلبها ليس واضحا تماما من الاسم |
بدء تشغيل العروض التوضيحية | المستندات النصية مع أمثلة التعليمات البرمجية ، بشكل منفصل هناك عروض تجريبية مع أمثلة التعليمات البرمجية (صحيح ، فهي منتشرة على صفحات مختلفة ، لا يعمل الجميع ويتم تفتيشهم بسهولة أكبر عبر Google) ، هناك عرض توضيحي حيث يمكنك لمس ميزات مختلفة ، لكن يُقترح إدارتها من خلال عناصر تحكم واجهة المستخدم ، وهذا هو ، ثم لا يزال يتعين علينا البحث بشكل منفصل عن الأساليب لربطها | كيف لفقراء حقا أساسا كل شيء متناثرة على جيثب و stackoverflow ، ولكن هناك عروض تجريبية من الميزات مع أمثلة رمز لتنفيذه | مجتمعة في شكل ملعب: رمز مع التعليقات وعدد من العروض ، يمكنك حاول على الفور وتقييم احتمالات كثيرة |
نشاط مجتمعي | مركزي | ارتفاع | مركزي |
نشاط المطور | مركزي | مركزي | ارتفاع |
ليس من المنطقي مقارنة المكتبات حسب الحجم ، لأن كل هذا يتوقف على ما وكيفية الاتصال بمشروع معين: قم بتحميل الملف النهائي بأحد البنيات (التي تختلف أيضًا) أو قم بتشغيل حزمة npm من خلال نوع من المجمّع. والأهم هو مقدار استخدام المحرر: ما إذا كان يتم تحميل جميع الأنماط والسمات ، وعدد الإضافات والوظائف الإضافية المستخدمة. على سبيل المثال ، في CodeMirror ، تتوفر معظم الوظائف التي تعمل في Monaco و Ace خارج الصندوق فقط مع الوظائف الإضافية. يعرض الجدول عدد الأحرف في الإصدارات الحديثة على CDN ووزن الملفات المضغوطة الخاصة بهم للحصول على فكرة عامة عن الطلبات المشاركة.
تحتوي جميع المكتبات على نفس مجموعة الميزات الأساسية تقريبًا: التنسيق التلقائي للكود ، وخطوط قابلة للطي ، وخفض / نسخ / لصق ، ومفاتيح التشغيل السريع ، والقدرة على إضافة صيغ جديدة للتمييز والترتيب ، والتحقق من بناء الجملة (في CodeMirror فقط من خلال الوظائف الإضافية ، في Ace حتى الآن فقط لجافا سكريبت) / CoffeeScript / CSS / XQuery) ، تلميحات الأدوات والإكمال التلقائي (في CodeMirror - من خلال الوظائف الإضافية) ، البحث المتقدم عن طريق الكود (في CodeMirror - من خلال الوظائف الإضافية) ، طرق لتنفيذ علامات التبويب ووضع الانقسام ، وضع الفرق وأداة دمج (في CodeMirror - إما مع إيجابيات وسلبيات في نافذة واحدة ، أو لوحة اثنين من خلال الملحق ، الآس - فصل ليب). نظرًا لعمرها ، تمت كتابة العديد من الإضافات لـ CodeMirror ، لكن عددها سيؤثر على وزن وسرعة المحرر. يمكن لموناكو القيام بالكثير من الأشياء خارج الصندوق ، وفي رأيي ، أفضل وفي حجم أكبر من Ace و CodeMirror.
بقينا في موناكو لعدة أسباب:
- الأدوات الأكثر تطوراً التي اعتبرناها مهمة لمشروعنا:
- التحسس الذكي - النصائح والإكمال التلقائي ؛
- الملاحة رمز الذكية في قائمة السياق ومن خلال minimap.
- وضع فرق اثنين من لوحة خارج منطقة الجزاء.
- مكتوب في TypeScript. لوحة التحكم الخاصة بنا مكتوبة بلغة Vue + Typescript ، لذلك كان دعم TS مهمًا. بالمناسبة ، تدعم Ace مؤخرًا أيضًا TS ، ولكن تمت كتابته في الأصل في JS. ل CodeMirror ، هناك أنواع في definitelyTyped.
- يتم تطويره بشكل أكثر فاعلية (ربما لأنه تم إصداره منذ وقت ليس ببعيد) ، ويتم تصحيح الأخطاء بشكل أسرع ويتم مواجهة طلبات التجميع. للمقارنة ، مع CodeMirror كان لدينا تجربة حزينة ، عندما لم يتم تصحيح الأخطاء لسنوات ووضعنا عكاز على عكاز وقادنا عكاز.
- وثائق مريحة تم إنشاؤها تلقائيًا (والتي تعطي الأمل في اكتمالها) مع مراجع تبادلية بين الواجهات والأساليب.
- حسب ذوقنا ، أجمل واجهة المستخدم (ربما تتعلق أيضًا بوقت الإنشاء) وواجهة برمجة تطبيقات موجزة.
- بعد سؤال أصدقاء المطورين عن المحررين الذين تسببوا في معظم الصداع ، كان Ace و CodeMirror هم القادة.
بشكل منفصل ، ينبغي أن يقال عن سرعة العمل. تحليل مكلفة يحدث في مؤشر ترابط العامل المتوازي. بالإضافة إلى ذلك ، يتم تقييد جميع العمليات الحسابية من خلال حجم منفذ العرض (يتم احتساب جميع الأنواع والألوان والتجسيد فقط لتلك الخطوط المرئية). يبدأ في الفرامل فقط إذا كان الكود يحتوي على 100،000 سطر - يمكن حساب المطالبات لعدة ثوان. اتضح أن Ace ، التي تستخدم أيضًا العاملين في مجال الحوسبة الثقيلة ، أسرع: في التعليمات البرمجية من نفس الطول ، تظهر المطالبات على الفور تقريبًا ، وتتكيف بسرعة مع 200000 سطر (على الموقع الرسمي ، يُذكر أنه حتى 4 ملايين خط يجب ألا تكون مشكلة ، على الرغم من تم تسريع المسامير ، وبدأ الإدخال في التباطؤ واختفت المطالبات بعد المليون. يتعذر على CodeMirror ، حيث لا توجد حسابات متوازية ، سحب مثل هذه المجلدات: يمكن أن تومض كل من النص وتمييز بناء الجملة. نظرًا لأن 100،000 سطر في ملف نادر في العالم الواقعي ، فقد تغاضينا عن هذا. حتى مع 40-50 ألف خط موناكو يقوم بعمل ممتاز.
توصيل Monaco واستخدام الميزات الأساسية (على سبيل المثال ، التكامل مع Vue)
صلة
هنا سأقدم أمثلة على الكود من مكونات الصوت وأستخدم المصطلحات المناسبة. ولكن كل هذا يتم نقله بسهولة إلى أي إطار آخر أو JS خالص.
يمكن تنزيل شفرة مصدر موناكو على الموقع الرسمي ووضعها في مشروعك ، ويمكنك استلامه من CDN ، ويمكنك الاتصال بالمشروع عبر npm. سأتحدث عن الخيار الثالث وبناء باستخدام webpack.
نضع محرر موناكو ومكون إضافي للتجميع:
npm i -S monaco-editor npm i -D monaco-editor-webpack-plugin
في تهيئة webpack ، أضف:
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); module.exports = {
إذا كنت تستخدم Vue و vue-cli-service في الإنشاء ، فأضف إلى vue.config.js:
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); module.exports = {
إذا كنت لا تحتاج إلى جميع لغات وميزات Monaco ، لتقليل حجم الحزمة ، يمكنك نقل كائن من الإعدادات إلى
MonacoWebpackPlugin
:
new MonacoWebpackPlugin({ output: '',
قائمة كاملة من الميزات واللغات للمكون الإضافي
هنا .
إنشاء وتخصيص محرر
نقوم باستيراد
editor
editor.create(el: HTMLElement, config?: IEditorConstructionOptions)
، بتمرير عنصر DOM الذي نريد إنشاء المحرر فيه كوسيطة أولى.
في مكون المحرر:
<template> <div ref='editor' class='editor'></div> </template> <script> import {editor} from 'monaco-editor'; import {Component, Prop, Vue} from 'vue-property-decorator'; @Component() export default class Monaco extends Vue { private editor = null; mounted() { this.editor = editor.create(this.$refs.editor); } } </script> <style> .editor { margin: auto; width: 60vw; height: 200px; } </style>
يجب أن تقوم الحاوية الخاصة بالمحرر بالضرورة بتعيين الارتفاع بحيث لا يتحول إلى صفر. إذا قمت بإنشاء المحرر في div فارغ (مع ارتفاع صفر - K.O.) ، ستكتب Monaco نفس الارتفاع بأسلوب مضمّن في نافذة المحرر.
الوسيطة الاختيارية الثانية إلى
editor.create
هي تهيئة المحرر. يوجد أكثر من مائة خيار فيه ، يوجد وصف كامل لواجهة
IEditorConstructionOptions في الوثائق.
على سبيل المثال ، سنقوم بتعيين اللغة والسمة والنص الأولي وتمكين التفاف السطر (بشكل افتراضي ، لا يتم لفهم):
const config = { value: `function hello() { alert('Hello world!'); }`, language: 'javascript', theme: 'vs-dark', wordWrap: 'on' }; this.editor = editor.create(this.$refs.editor, config);
ترجع الدالة
editor.create كائنًا بواجهة
IStandaloneCodeEditor . من خلاله ، يمكنك الآن التحكم في كل ما يحدث في المحرر ، بما في ذلك تغيير الإعدادات الأولية:
الآن من أجل الألم: يقبل
updateOptions
كائنًا بواجهة
IEditorOptions ، وليس IEditorConstructionOptions. تختلف قليلاً: IEditorConstructionOptions أوسع ، ويشمل خصائص مثيل المحرر هذا وبعض الخصائص العامة. يتم تغيير خصائص
updateOptions
من خلال
updateOptions
، وعالمية - من خلال أساليب
editor
العالمي. وبالتالي ، فإن تلك التي تتغير على مستوى العالم تتغير لجميع الحالات. من بين هذه الخيارات هو
theme
. إنشاء مثيلات 2 مع سمات مختلفة. ذ كلاهما سيكون واحد في الماضي (الظلام هنا). ستقوم طريقة
editor.setTheme('vs')
أيضًا بتغيير الموضوع لكليهما. سيؤثر هذا حتى على تلك النوافذ الموجودة في صفحة أخرى من SPA الخاص بك. هناك عدد قليل من هذه الأماكن ، ولكن عليك متابعتها.
<template> <div ref='editor1' class='editor'></div> <div ref='editor2' class='editor'></div> </template> <script> </script>
حذف المحرر
عندما تقوم بتدمير نافذة Monaco ، يجب عليك استدعاء طريقة
dispose
، وإلا فلن يتم مسح جميع المستمعين ولن تعمل النوافذ التي تم إنشاؤها بعد ذلك بشكل صحيح ، وتتفاعل مع بعض الأحداث عدة مرات:
beforeDestroy() { this.editor && this.editor.dispose(); }
علامات التبويب
تستخدم علامات التبويب المفتوحة في محرر الملف نفس نافذة موناكو. للتبديل بينهما ، يتم استخدام أساليب IStandaloneCodeEditor:
getModel
و
setModel
لتحديث نموذج المحرر. يقوم النموذج بتخزين النص وموضع المؤشر وتاريخ الإجراء للتراجع عن الإعادة. لإنشاء نموذج لملف جديد ، يتم استخدام الطريقة العالمية
editor.createModel(text: string, language: string)
. إذا كان الملف فارغًا ، فلا يمكنك إنشاء نموذج وتمرير
setModel
إلى
setModel
:
عرض الكود <template> <div class='tabs'> <div class='tab' v-for="tab in tabs" :key'tab.id' @click='() => switchTab(tab.id)'> {{tab.name}} </div> </div> <div ref='editor' class='editor'></div> </template> <script> import {editor} from 'monaco-editor'; import {Component, Prop, Vue} from 'vue-property-decorator'; @Component() export default class Monaco extends Vue { private editor = null; private tabs: [ {id: 1, name: 'tab 1', text: 'const tab = 1;', model: null, active: true}, {id: 2, name: 'tab 2', text: 'const tab = 2;', model: null, active: false} ]; mounted() { this.editor = editor.create(this.$refs.editor); } private switchTab(id) { const activeTab = this.tabs.find(tab => tab.id === id); if (!activeTab.active) { </script>
وضع الفرق
لوضع الفرق ، تحتاج إلى استخدام طريقة
editor
أخرى عند إنشاء نافذة المحرر -
createDiffEditor
:
<template> <div ref='diffEditor' class='editor'></div> </template> // ... mounted() { this.diffEditor = editor.createDiffEditor(this.$refs.diffEditor, config); } // ...
يستغرق نفس المعلمات مثل
editor.create
، لكن يجب أن يحتوي التكوين على واجهة
IDiffEditorConstructionOptions ، والتي تختلف قليلاً عن تهيئة المحرر العادي ، على وجه الخصوص ، ليس لها
value
. يتم تعيين النصوص للمقارنة بعد إنشاء
IStandaloneDiffEditor التي تم إرجاعها عبر
setModel :
this.diffEditor.setModel({ original: editor.createModel('const a = 1;', 'javascript'), modified: editor.createModel('const a = 2;', 'javascript') });
قائمة السياق ، لوحة القيادة والمفاتيح الساخنة
تستخدم Monaco قائمة السياق الخاصة بها ، غير المستعرضية ، حيث يوجد تنقل ذكي ، ومؤشر متعدد لتغيير كل الأحداث ، ولوحة أمر كما هو الحال في VS Code (لوحة الأوامر) مع مجموعة من الأوامر والاختصارات المفيدة التي تسرع كتابة التعليمات البرمجية:
قائمة السياق موناكو
لوحة قيادة موناكو
يتم توسيع قائمة السياق من خلال طريقة
addAction
(وهي متوفرة في كل من
IStandaloneCodeEditor
و
IStandaloneDiffEditor
) ، والتي تقبل كائن
IActionDescriptor :
من أجل ربط اختصار بإجراء ما فقط دون إظهاره في قائمة السياق ، يتم استخدام نفس الطريقة ، لم يتم تحديد
contextMenuGroupId
العمل فقط:
ستتضمن لوحة الأوامر جميع الإجراءات المضافة.
نصائح والإكمال التلقائي
لهذه الأغراض ، تستخدم Monaco
التحسس الذكي ، وهو أمر رائع. يمكنك أن تقرأ على لقطات الشاشة الرابط مقدار المعلومات المفيدة التي يمكنه عرضها. إذا لم يكن لغتك بعد الإكمال التلقائي ، يمكنك إضافتها من خلال
registerCompletionItemProvider . وبالنسبة إلى JS و TS ، يوجد بالفعل أسلوب
addExtraLib
الذي يسمح لك بتحميل تعريفات TypeScript لأدوات تلميحات وإكمال تلقائي:
في المعلمة الأولى ، يمرر السطر التعريف ، في الثاني ، اختياري ، اسم lib.
لغات مخصصة والسمات
لدى Monaco وحدة نمطية
Monarch لتحديد بناء جملة لغاتها. يتم وصف بناء الجملة بشكل قياسي تمامًا: يتم تعيين المراسلات بين النظامي والرموز المميزة لهذه اللغة.
يمكنك أيضًا إنشاء سمة
لرموزك - كائن بواجهة
IStandaloneThemeData - وتثبيته في
editor
:
الآن سيبدو النص باللغة الموضحة كما يلي:
يمكنك تطبيق هذه الميزة ، طالما أن لديك ما يكفي من الخيال. على سبيل المثال ، قمنا بإنشاء عارض سجل المكالمات في لوحة المطورين الخاصة بنا. غالبًا ما تكون السجلات طويلة وغير مفهومة ، ولكن عندما يتم عرضها بتمييز بناء الجملة ، والبحث الذكي ، وخطوط قابلة للطي / التمديد ، والأوامر الضرورية (على سبيل المثال ، Prettify params) ، وتسليط الضوء على جميع خطوط الاتصال بمعرفها أو ترجمة الوقت في السجل إلى منطقة زمنية مختلفة ، ثم الحفر يصبح الأمر أكثر سهولة فيها (لقطة الشاشة قابلة للنقر):
استنتاج
باختصار ، سأقول إن موناكو هي النار. بعد أشهر من العمل معه ، لدي ذكريات ممتعة للغاية. إذا اخترت محررًا للرمز ، فتأكد من الانتقال إلى
Playground الخاص به والتشغيل مع الكود ، ومعرفة ما يمكن القيام به. ربما هذا هو بالضبط ما تبحث عنه.