代码编辑器开发心得

46 阅读2分钟

代码编辑器

前段时间开发了基于monaco-editor/react的SQL代码编辑器,还有一个python编辑器,踩了几个坑 主要的功能包括自定义文字,自定义SQL语句规则,代码补全等 整个组件的形式主要就是

 <div
      className={cn('  border-input overflow-hidden pt-[8px]', ariaInvalid && 'border-destructive', className)}
      style={{
        background,
      } as React.CSSProperties}
    >
      <Editor
        height={height}
        width={width}
        defaultLanguage="sql"
        theme={theme === 'dark' ? 'vs-dark' : 'vs-light'}
        value={sqlValue || value}
        onChange={onSqlValueChange || onChange}
        // beforeMount={beforeMount}
        onMount={onMount}
        loading={<div className="flex items-center justify-center h-full">加载中...</div>}

        options={{
          minimap: { enabled: minimap },
          scrollBeyondLastLine: false,
          fontSize: 14,
          lineNumbers,
          lineNumbersMinChars: 3,
          readOnly,
          wordWrap: 'on',
          automaticLayout: true,
          suggestOnTriggerCharacters: true,
          quickSuggestions: true,
          snippetSuggestions: 'inline',
          glyphMargin: false, // 关闭断点等图标区域
          folding: false,
          fixedOverflowWidgets: true,
        }}
        {...rest}
      />
    </div>

1.SqlCoder实现了一套完整的变量系统,使用{{variable}}语法进行标识:


// 变量识别规则
variables: [
  [/{{/, 'variable', '@variableContent'],
],
variableContent: [
  [/[^}]+/, 'variable'],
  [/}}/, 'variable', '@pop'],
]

其中还有一些小功能

1.监听编辑器失去焦点事件,立即添加自定义变量
2.监听variables变化,更新SQL编辑器中的变量引用

2 代码补全SQL编辑器的核心功能,SqlCoder实现了多层次的补全策略:

const dispose = monaco.languages.registerCompletionItemProvider('sql', {
  triggerCharacters: ['{', ' ', '.', ',', '(', '='],
  provideCompletionItems: (model, position) => {
    // 智能判断上下文,提供相关建议
  }
});

这个补全代码 之前发现会多次触发 刷新就好了 但是重新进入不同页面 的相同编辑器 发现会触发多次补全 提示多个重复的 后来才发现要通过 return () => { dispose?.dispose() } 卸载才行

其他

稳健的加载策略

SqlCoder实现了完善的错误处理和重试机制:


const [hasError, setHasError] = useState(false);
const [retryCount, setRetryCount] = useState(0);

if (hasError && retryCount < 3) {
  return (
    // 重试界面
  );
}

防抖优化

在变量自动提取功能中,组件使用了防抖技术避免频繁操作:


const handleBlur = () => {
  if (debounceTimer) {
    clearTimeout(debounceTimer);
  }
  debounceTimer = setTimeout(() => {
    // 处理变量提取
  }, 500);
};

语法高亮实现

SqlCoder通过Monaco的Monarch库定义了SQL的语法标记规则,这是实现语法高亮的底层技术:


monaco.languages.setMonarchTokensProvider('sql', {
  defaultToken: '',
  tokenPostfix: '.sql',
  keywords: SQL_KEYWORDS,
  functions: SQL_FUNCTIONS,
  // ...完整的tokenizer配置
});

这一实现涵盖了SQL语言的多个关键要素:

  1. 关键字识别​(SELECT、FROM、WHERE等)
  2. 函数支持​(COUNT、SUM、AVG等)
  3. 数据类型处理​(字符串、数字、注释等)
  4. 特殊符号处理​(括号、运算符等)

主题系统集成

组件通过useTheme钩子实现了主题切换功能,这是现代编辑器的重要特性:


const { theme } = useTheme();
// ...
theme={theme === 'dark' ? 'vs-dark' : 'vs-light'}

这种设计使用户可以在亮色和暗色主题间无缝切换,提升了用户体验。值得注意的是,微软在Access的Monaco SQL编辑器中也特别强调了浅色和深色主题的支持