zoukankan      html  css  js  c++  java
  • sublime

    这几天为sublime-syntax的语法简直伤透了脑筋,网上能找到的教程都非常浅显,而官方英文文档的一时半会看不懂,中文文档翻译又实在糟心,纠结到最后还是下决心将英文文档整个看了一遍,并翻译成了我能看懂的文字。就以此作为我的第一篇正式博客吧!

    使用步骤

    1.安装PackageDev插件

    2.新建语法文件

    Tools | Packages | Package Development | New Syntax Definition

    3.定义语法高亮规则

    见后文。

    4.保存文件

    保存完点击 Tools | Build System | Convert to 编译。
    (感觉好像可以不用这一步,直接保存在user文件夹下就行,因为新版本已支持.sublime-syntax后缀文件。当然我也没试过,只是猜想。)

    5.修改语法文件

    修改并保存可直接产生效果,不用等状态栏100%。但最终要等100%才能退出sublime,以后会自动加载。

    语法规则

    name                ->  语法名称。可选,如果不写,将从文件名派生
    file_extensions     ->  此语法应使用的文件扩展名
    first_line_match    ->  没有可识别的扩展名时,将对文件第一行进行匹配识别
    scope               ->  分配给文件中所有文本的默认scope
    hidden              ->  隐藏的语法定义,不会显示在菜单中,但仍可以通过插件分配
    

    Contexts

    Contexts中通常有多种匹配文本

    ctrl+alt+shift+p -> 查看当前文本所使用的scope

    当内容能匹配多个context时,使用最左边的一个;当多种context在同一位置生效时,使用先定义的一个。

    push        ->  使用push入栈,将文本匹配切换到另一种context中,
                =>  剩下的将不再使用当前context,直到使用pop从栈中弹出
    meta_scope  ->  为当前栈context的所有文本分配scope
    pop         ->  从栈中弹出,继续使用之前的scope
    main        ->  每个语法必须定义一个main context, 它应用于文本最开始的位置.
    

    Meta

    meta_scope              ->  为当前栈context的所有文本分配scope, 包括触发push和pop的文本
    meta_content_scope      ->  同上,但是不应用于触发push和pop的文本
    meta_include_prototype  ->  false, 阻止当前文本自动应用prototype匹配.
    clear_scopes            ->  移除当前栈中应用的scope,可以是整数或true. 
                            =>  应用于meta_scope和meta_content_scope之前. 
                            =>  通常仅在将一种语法嵌入另一种语法时使用。
    

    meta 必须列在任何match或include之前。

    Match

    match               ->  用正则表达式来匹配文本。一次只针对一行文本匹配
                        =>  可以不使用'',但当正则中有# : - { [ 或 > 时必须用引号
    scope               ->  分配给匹配文本的着色类型
    captures            ->  group数字对scope的映射,将匹配的内容按gruop分别着色
    push                ->  推入堆栈的context,可以是context名及其列表,或者内联的匿名context
    pop                 ->  弹出堆栈中的当前context。此键唯一可接受的值是true
    set                 ->  类似push,但先退出当前context,然后将给定的context推送到栈中
    embed               ->  此键接受context名,类似push,但当escape时弹出所有嵌套的context。
                        =>  是将一种语法嵌入另一种语法的理想工具
        escape              ->  与embed配套使用,用于退出嵌入的context
                            =>  此内的所有反向引用与match中的group关联
        embed_scope         ->  为escape前match的所有文本分配scope
        escape_capture      ->  escape中group数字对scope的映射,0表示所有匹配文本
    

    push, pop, set 和 embed互斥。

    Include

    用于将一个context的内容包含在另一个context中。

    例如注释,可以使用include将其包含在内,而不用将它的内容复制到每个context中。

    include的内容会被插入到当前位置,仍然可以通过调整插入位置来指定先后顺序。

    include的内容中定义的meta语句会被忽略。

    prototype

    对于诸如注释之类的元素,经常会用include来使它们在每个context中自动插入,但每次都写include太过繁琐。

    可以使用prototype来完成此操作,它自动将内容插入到每个context的顶部,除非在context顶部用meta_include_prototype: false用标明。

    Including Other Files

    Sublime Syntax 支持一个语法嵌套另一个语法。
    例如HTML嵌套Javascript。

    main:
      - match: <script>
        push: Packages/JavaScript/JavaScript.sublime-syntax
        with_prototype:
          - match: (?=</script>)
            pop: true
    
    with_prototype      ->   类似prototype, 将匹配应用于上面引入的所有context中。 
                        =>   但是它会忽略meta_include_prototype设置。
    

    此处(?=</script>),当匹配到上面的内容后跟</script>时将JS从栈中弹出,并按原HTML规则匹配

    虽然.sublime-syntax 和.tmLanguage语法都支持,但是在此不能混用。

    例2:HTML模板语言的实现

    scope: text.jinja
    contexts:
      main:
        - match: ""
          push: "Packages/HTML/HTML.sublime-syntax"
          with_prototype:
            - match: "{{"
              push: expr
    
      expr:
        - match: "}}"
          pop: true
        - match: (if|else)
          scope: keyword.control
    

    与HTML中嵌入JavaScript不同的是,模板语言倾向于从内到外操作:默认使用HTML,只有某些特殊语句转义为模板语言

    match: "" 默认匹配所有的文本,通过with_prototype语句,当遇到 {{ ... }} 时使用新的匹配.

    Variables

    几个正则表达式中有部分完全相同的情况并不少见,为避免重复,可以使用变量代替。

    variables:
      ident: '[A-Za-z_][A-Za-z_0-9]*'
    contexts:
      main:
        - match: '{{ident}}'
          scope: keyword.control
    

    变量必须在.sublime-syntax文件顶层定义,并通过{{varname}}在正则表达式中引用。

    Variables may themselves include other variables. Note that any text that doesn't match {{[A-Za-z0-9_]+}} won't be considered as a variable, so regexes can still include literal {{ characers, for example.

    实例

    嵌套循环匹配

    例:括号自动匹配, 高亮显示单独的闭括号)

    contexts:
      main:
        - match: (
          push: brackets
        - match: )
          scope: invalid.illegal.stray-bracket-end
    
      brackets:
        - match: )
          pop: true
        - include: main
    

    高级栈的使用

    例:匹配typedef的两种定义

    typedef int coordinate_t;
    
    typedef struct
    {
        int x;
        int y;
    } point_t;
    

    匹配代码:

    main:
      - match: typedef
        scope: keyword.control.c
        set: [typedef_after_typename, typename]
    
    typename:
      - match: struct
        set:
          - match: "{"
            set:
              - match: "}"
                pop: true
      - match: [A-Za-z_][A-Za-z_0-9]*
        pop: true
    
    typedef_after_typename:
      - match: [A-Za-z_][A-Za-z_0-9]*
        scope: entity.name.type
        pop: true
    

    main中使用匹配将两个context推入堆栈,最右边的处于栈的最顶层,先匹配,当最右边弹出后,才开始匹配左边的。

    为了简洁起见,typename中使用了context的匿名写法。

    对正则表达式中group的引用

    例:PHP与 Heredocs语法

    contexts:
      main:
        - match: <<<([A-Za-z][A-Za-z0-9_]*)
          push: heredoc
    
      heredoc:
        - meta_scope: string.unquoted.heredoc
        - match: ^1;
            pop: true
    

    此处使用了 1 符号代指之前匹配的group

    语法测试

    可以定义一个语法测试文本来自动检测,而不需要手动通过show_scope_name命令检测
    具体见官方文档。

    关于scope的语法容日后再行研究

    引用:

    非官方文档(推荐)
    官方文档
    官方文档中文版

  • 相关阅读:
    按指定上下限区间进行数据统计的示例.sql
    树形数据层次显示处理示例.sql
    Flexi传授如何说服自己的老板采用Node.js
    sed的用法[转]
    [bash] string operators
    [shell script]脚本实现目录和文件名显示
    Bash快捷键
    [bash] Condition Tests
    整理一下博客
    老爸的工具箱之:根据日期批量重命名照片
  • 原文地址:https://www.cnblogs.com/JeromeLong/p/9880000.html
Copyright © 2011-2022 走看看