Giter Club home page Giter Club logo

syntect's Introduction

syntect

Crates.io Documentation Crates.io Build Status codecov

syntect is a syntax highlighting library for Rust that uses Sublime Text syntax definitions. It aims to be a good solution for any Rust project that needs syntax highlighting, including deep integration with text editors written in Rust. It's used in production by at least two companies, and by many open source projects.

If you are writing a text editor (or something else needing highlighting) in Rust and this library doesn't fit your needs, I consider that a bug and you should file an issue or email me. I consider this project mostly complete, I still maintain it and review PRs, but it's not under heavy development.

Important Links

Getting Started

syntect is available on crates.io. You can install it by adding this line to your Cargo.toml:

syntect = "5.0"

After that take a look at the documentation and the examples.

If you've cloned this repository, be sure to run

git submodule update --init

to fetch all the required dependencies for running the tests.

Features/Goals

  • Work with many languages (accomplished through using existing grammar formats)
  • Highlight super quickly, faster than nearly all text editors
  • Include easy to use API for basic cases
  • API allows use in fancy text editors with piece tables and incremental re-highlighting and the like.
  • Expose internals of the parsing process so text editors can do things like cache parse states and use semantic info for code intelligence
  • High quality highlighting, supporting things like heredocs and complex syntaxes (like Rust's).
  • Include a compressed dump of all the default syntax definitions in the library binary so users don't have to manage a folder of syntaxes.
  • Well documented, I've tried to add a useful documentation comment to everything that isn't utterly self explanatory.
  • Built-in output to coloured HTML <pre> tags or 24-bit colour ANSI terminal escape sequences.
  • Nearly complete compatibility with Sublime Text 3, including lots of edge cases. Passes nearly all of Sublime's syntax tests, see issue 59.
  • Load up quickly, currently in around 23ms but could potentially be even faster.

Screenshots

There's currently an example program called syncat that prints one of the source files using hard-coded themes and syntaxes using 24-bit terminal escape sequences supported by many newer terminals. These screenshots don't look as good as they could for two reasons: first the sRGB colours aren't corrected properly, and second the Rust syntax definition uses some fancy labels that these themes don't have highlighting for.

Nested languages Base 16 Ocean Dark Solarized Light InspiredGithub

Example Code

Prints highlighted lines of a string to the terminal. See the easy and html module docs for more basic use case examples.

use syntect::easy::HighlightLines;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::{ThemeSet, Style};
use syntect::util::{as_24_bit_terminal_escaped, LinesWithEndings};

// Load these once at the start of your program
let ps = SyntaxSet::load_defaults_newlines();
let ts = ThemeSet::load_defaults();

let syntax = ps.find_syntax_by_extension("rs").unwrap();
let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
let s = "pub struct Wow { hi: u64 }\nfn blah() -> u64 {}";
for line in LinesWithEndings::from(s) {
    let ranges: Vec<(Style, &str)> = h.highlight_line(line, &ps).unwrap();
    let escaped = as_24_bit_terminal_escaped(&ranges[..], true);
    print!("{}", escaped);
}

Performance

Currently syntect is one of the faster syntax highlighting engines, but not the fastest. The following perf features are done:

  • Pre-link references between languages (e.g <script> tags) so there are no tree traversal string lookups in the hot-path
  • Compact binary representation of scopes to allow quickly passing and copying them around
  • Determine if a scope is a prefix of another scope using bit manipulation in only a few instructions
  • Cache regex matches to reduce number of times oniguruma is asked to search a line
  • Accelerate scope lookups to reduce how much selector matching has to be done to highlight a list of scope operations
  • Lazily compile regexes so startup time isn't taken compiling a thousand regexes for Actionscript that nobody will use
  • Optionally use the fancy-regex crate. Unfortunately this isn't yet faster than oniguruma on our benchmarks but it might be in the future.

The current perf numbers are below. These numbers may get better if more of the things above are implemented, but they're better than many other text editors. All measurements were taken on a mid 2012 15" retina Macbook Pro, my new 2019 Macbook takes about 70% of these times.

  • Highlighting 9200 lines/247kb of jQuery 2.1 takes 600ms. For comparison:
    • Textmate 2, Spacemacs and Visual Studio Code all take around 2ish seconds (measured by hand with a stopwatch, hence approximate).
    • Atom takes 6 seconds
    • Sublime Text 3 dev build takes 98ms (highlighting only, takes ~200ms click to pixels), despite having a super fancy javascript syntax definition.
    • Vim is instantaneous but that isn't a fair comparison since vim's highlighting is far more basic than the other editors. Compare vim's grammar to Sublime's.
    • These comparisons aren't totally fair, except the one to Sublime Text since that is using the same theme and the same complex definition for ES6 syntax.
  • Simple syntaxes are faster, JS is one of the most complex. It only takes 34ms to highlight a 1700 line 62kb XML file or 50,000 lines/sec.
  • ~138ms to load and link all the syntax definitions in the default Sublime package set.
    • but only ~23ms to load and link all the syntax definitions from an internal pre-made binary dump with lazy regex compilation.
  • ~1.9ms to parse and highlight the 30 line 791 character testdata/highlight_test.erb file. This works out to around 16,000 lines/second or 422 kilobytes/second.
  • ~250ms end to end for syncat to start, load the definitions, highlight the test file and shut down. This is mostly spent loading.

Feature Flags

Syntect makes heavy use of cargo features, to support users who require only a subset of functionality. In particular, it is possible to use the highlighting component of syntect without the parser (for instance when hand-rolling a higher performance parser for a particular language), by adding default-features = false to the syntect entry in your Cargo.toml.

For more information on available features, see the features section in Cargo.toml.

Pure Rust fancy-regex mode, without onig

Since 4.0 syntect offers an alternative pure-rust regex engine based on the fancy-regex engine which extends the awesome regex crate with support for fancier regex features that Sublime syntaxes need like lookaheads.

The advantage of fancy-regex is that it does not require the onig crate which requires building and linking the Oniguruma C library. Many users experience difficulty building the onig crate, especially on Windows and Webassembly.

As far as our tests can tell this new engine is just as correct, but it hasn't been tested as extensively in production. It also currently seems to be about half the speed of the default Oniguruma engine, although further testing and optimization (perhaps by you!) may eventually see it surpass Oniguruma's speed and become the default.

To use the fancy-regex engine with syntect, add it to your Cargo.toml like so:

syntect = { version = "4.2", default-features = false, features = ["default-fancy"]}

If you want to run examples with the fancy-regex engine you can use a command line like the following:

cargo run --features default-fancy --no-default-features --release --example syncat testdata/highlight_test.erb

Due to the way Cargo features work, if any crate you depend on depends on syntect without enabling fancy-regex then you'll get the default onig mode.

Note: The fancy-regex engine is absurdly slow in debug mode, because the regex engine (the main hot spot of highlighting) is now in Rust instead of C that's always built with optimizations. Consider using release mode or onig when testing.

Caching

Because syntect's API exposes internal cacheable data structures, there is a caching strategy that text editors can use that allows the text on screen to be re-rendered instantaneously regardless of the file size when a change is made after the initial highlight.

Basically, on the initial parse every 1000 lines or so copy the parse state into a side-buffer for that line. When a change is made to the text, because of the way Sublime Text grammars work (and languages in general), only the highlighting after that change can be affected. Thus when a change is made to the text, search backwards in the parse state cache for the last state before the edit, then kick off a background task to start re-highlighting from there. Once the background task highlights past the end of the current editor viewport, render the new changes and continue re-highlighting the rest of the file in the background.

This way from the time the edit happens to the time the new colouring gets rendered in the worst case only 999+length of viewport lines must be re-highlighted. Given the speed of syntect even with a long file and the most complicated syntax and theme this should take less than 100ms. This is enough to re-highlight on every key-stroke of the world's fastest typist in the worst possible case. And you can reduce this asymptotically to the length of the viewport by caching parse states more often, at the cost of more memory.

Any time the file is changed the latest cached state is found, the cache is cleared after that point, and a background job is started. Any already running jobs are stopped because they would be working on old state. This way you can just have one thread dedicated to highlighting that is always doing the most up-to-date work, or sleeping.

Parallelizing

Since 3.0, syntect can be used to do parsing/highlighting in parallel. SyntaxSet is both Send and Sync and so can easily be used from multiple threads. It is also Clone, which means you can construct a syntax set and then clone it to use for other threads if you prefer.

Compared to older versions, there's nothing preventing the serialization of a SyntaxSet either. So you can directly deserialize a fully linked SyntaxSet and start using it for parsing/highlighting. Before, it was always necessary to do linking first.

It is worth mentioning that regex compilation is done lazily only when the regexes are actually needed. Once a regex has been compiled, the compiled version is used for all threads after that. Note that this is done using interior mutability, so if multiple threads happen to encounter the same uncompiled regex at the same time, compiling might happen multiple times. After that, one of the compiled regexes will be used. When a SyntaxSet is cloned, the regexes in the cloned set will need to be recompiled currently.

For adding parallelism to a previously single-threaded program, the recommended thread pooling is rayon. However, if you're working in an already-threaded context where there might be more threads than you want (such as writing a handler for an Iron request), the recommendation is to force all highlighting to be done within a fixed-size thread pool using rust-scoped-pool. An example of the former is in examples/parsyncat.rs.

Examples Available

There's a number of examples of programs that use syntect in the examples folder and some code outside the repo:

  • syncat prints a highlighted file to the terminal using 24-bit colour ANSI escape codes. It demonstrates a simple file highlighting workflow.
  • synhtml prints an HTML file that will display the highlighted code. Demonstrates how syntect could be used by web servers and static site generators.
  • synstats collects a bunch of statistics about the code in a folder. Includes basic things like line count but also fancier things like number of functions. Demonstrates how syntect can be used for code analysis as well as highlighting, as well as how to use the APIs to parse out the semantic tokenization.
  • faiyels is a little code minimap visualizer I wrote that uses syntect for highlighting.
  • parsyncat is like syncat, but accepts multiple files and highlights them in parallel. It demonstrates how to use syntect from multiple threads.

Here's that stats that synstats extracts from syntect's codebase (not including examples and test data) as of this commit:

################## Stats ###################
File count:                               19
Total characters:                     155504

Function count:                          165
Type count (structs, enums, classes):     64

Code lines (traditional SLOC):          2960
Total lines (w/ comments & blanks):     4011
Comment lines (comment but no code):     736
Blank lines (lines-blank-comment):       315

Lines with a documentation comment:      646
Total words written in doc comments:    4734
Total words written in all comments:    5145
Characters of comment:                 41099

Projects using Syntect

Below is a list of projects using Syntect, in approximate order by how long they've been using syntect (feel free to send PRs to add to this list):

  • bat, a cat(1) clone, uses syntect for syntax highlighting.
  • Bolt, a desktop application for building and testing APIs, uses syntect for syntax highlighting.
  • catmark, a console markdown printer, uses syntect for code blocks.
  • Cobalt, a static site generator that uses syntect for highlighting code snippets.
  • crowbook, a Markdown book generator, uses syntect for code blocks.
  • delta, a syntax-highlighting pager for Git.
  • Docket, a documentation site generator that uses syntect for highlighting.
  • hors, instant coding answers via command line, uses syntect for highlighting code blocks.
  • mdcat, a console markdown printer, uses syntect for code blocks.
  • Scribe, a Rust text editor framework which uses syntect for highlighting.
  • syntect_server, an HTTP server for syntax highlighting.
  • tokio-cassandra, CQL shell in Rust, uses syntect for shell colouring.
  • xi-editor, a text editor in Rust which uses syntect for highlighting.
  • Zola, a static site generator that uses syntect for highlighting code snippets.
  • The Way, a code snippets manager for your terminal that uses syntectfor highlighting.
  • Broot, a terminal file manager, uses syntect for file previews.
  • Rusty Slider, a markdown slideshow presentation application, uses syntect for code blocks.
  • bingus-blog, a blog software written in Rust, uses syntect for fenced code blocks.
  • BugStalker, modern debugger for Linux x86-64. Written in Rust for Rust programs.
  • Yazi, blazing fast terminal file manager based on async I/O, uses syntect for text file previews.

License and Acknowledgements

Thanks to Robin Stocker, Keith Hall and Martin Nordholts for making awesome substantial contributions of the most important impressive improvements syntect has had post-v1.0! They deserve lots of credit for where syntect is today. For example @robinst implemented fancy-regex support and a massive refactor to enable parallel highlighting using an arena. @keith-hall found and fixed many bugs and implemented Sublime syntax test support.

Thanks to Textmate 2 and @defuz's sublimate for the existing open source code I used as inspiration and in the case of sublimate's tmTheme loader, copy-pasted. All code (including defuz's sublimate code) is released under the MIT license.

syntect's People

Contributors

byron avatar canop avatar cgmossa avatar cmyr avatar enselic avatar est31 avatar eyelash avatar gjtorikian avatar icsaszar avatar ignatenkobrain avatar jplatte avatar jrappen avatar kanishkarj avatar keats avatar keith-hall avatar kornelski avatar kyoheiu avatar lucretiel avatar quasicomputational avatar rdnetto avatar rhysd avatar robinst avatar sharkdp avatar syphar avatar timhillgit avatar trishume avatar tyoverby avatar uwearzt avatar williamyaoh avatar zzau13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

syntect's Issues

Stack overflow on equality testing for ParseState

I'm trying to test whether two ParseState instances are equal so I can do incremental syntax highlighting.

This is almost certainly because of cyclic references of Rc<RefCell<Context>>. The fix, as trishume pointed out on IRC, is a custom PartialEq implementation on either ContextPtr or on StateLevel.

"clear_scopes" restore too early on "pop"

Imagine the following clear_scopes_test.sublime-syntax file:

%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
name: Simple Clear Scopes Test
scope: source.example
contexts:
  main:
    - match: \'
      scope: punctuation.definition.string.begin.example
      push: single_quoted_string
  single_quoted_string:
    - meta_scope: string.quoted.single.example
    - match: 'test'
      scope: example.pushes-clear-scopes.example
      push:
        - clear_scopes: 1
        - meta_scope: example.meta-scope.after-clear-scopes.example
        - match: 'foo'
          scope: foo
          push:
            - clear_scopes: 1
            - meta_scope: example.meta-scope.cleared-previous-meta-scope.example
            - match: 'bar'
              scope: bar
              pop: true
        - match: 'test'
          scope: example.pops-clear-scopes.example
          pop: true
    - match: '\\.'
      scope: constant.character.escape.example
    - match: \'
      scope: punctuation.definition.string.end.example
      pop: true

and the following syntax_test_clear_scopes.txt file:

# SYNTAX TEST "clear_scopes_test.sublime-syntax"
'hellotest
# ^^^^ string.quoted.single.example - example
#     ^^^^ source.example example.meta-scope.after-clear-scopes.example example.pushes-clear-scopes.example - string
#         ^ example.meta-scope.after-clear-scopes.example - example.pushes-clear-scopes.example - string
world foo bar
# ^^^^ source.example example.meta-scope.after-clear-scopes.example - example.pushes-clear-scopes - example.meta-scope.cleared-previous-meta-scope.example - string
#     ^^^^^^^ source.example example.meta-scope.cleared-previous-meta-scope.example - example.meta-scope.after-clear-scopes.example - example.pushes-clear-scopes - string
testing123'
# ^^ example.meta-scope.after-clear-scopes.example example.pops-clear-scopes.example - example.meta-scope.cleared-previous-meta-scope.example - string
#   ^^^^^^ string.quoted.single.example - example
#         ^ string.quoted.single.example punctuation.definition.string.end.example - example


In Sublime Text, the tests all pass. In syntect 1.2.0, there are some failures - it seems like nested "clear_scopes" are currently unsupported:

loading syntax definitions from testdata/Packages/cst/
Testing file testdata/Packages/cst/syntax_test_clear_scopes.txt
The test file references syntax definition file: clear_scopes_test.sublime-syntax
  Assertion selector "source.example example.meta-scope.cleared-previous-meta-scope.example - example.meta-scope.after-clear-scopes.example - example.pushes-clear-scopes - string" from line 8 failed against line 6, column range 10-13 (with text "bar") has scope [<source.example>, <example.meta-scope.cleared-previous-meta-scope.example>, <example.meta-scope.after-clear-scopes.example>, <bar>]
  Assertion selector "example.meta-scope.after-clear-scopes.example example.pops-clear-scopes.example - example.meta-scope.cleared-previous-meta-scope.example - string" from line 10 failed against line 9, column range 2-4 (with text "st") has scope [<source.example>, <example.meta-scope.cleared-previous-meta-scope.example>, <string.quoted.single.example>, <example.pops-clear-scopes.example>]
  Assertion selector "string.quoted.single.example - example" from line 11 failed against line 9, column range 4-10 (with text "ing123") has scope [<source.example>, <example.meta-scope.cleared-previous-meta-scope.example>]
  Assertion selector "string.quoted.single.example punctuation.definition.string.end.example - example" from line 12 failed against line 9, column range 10-11 (with text "\'") has scope [<source.example>, <example.meta-scope.cleared-previous-meta-scope.example>, <punctuation.definition.string.end.example>]
Ok(FailedAssertions(12, 29))
exiting with code 1

For a more real-world example, this affects the ASP syntax.

Build not working

clone repo
git submodule update --init
cargo build

make[2]: *** [CMakeFiles/onig.dir/src/regext.c.o] Error 1
In file included from /home/yash/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-64.0.0/oniguruma/src/regparse.h:32:0,
from /home/yash/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-64.0.0/oniguruma/src/regcomp.c:30:
/home/yash/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-64.0.0/oniguruma/src/regint.h:667:9: error: unknown type name โ€˜intptr_tโ€™

Please let me know how I can fix this or is it bug?

Thank you for your work on this great library :)

onig crate doesn't link properly for examples on Windows

How to build the examples?

I am on the examples folder doing rustc syncat.rs --extern syntect=.\..\target\debug\libsyntect.rlib and it is resulting:

error[E0463]: can't find crate for `yaml_rust` which `syntect` depends on
 --> syncat.rs:1:1
  |
1 | extern crate syntect;
  | ^^^^^^^^^^^^^^^^^^^^^ can't find crate

error: aborting due to previous error

It is seems to be asking for all the crates syntect depends on. Thought it looks like a lot of crates, how would you build an example more simply?

The "name" key should be optional in "sublime-syntax" files

In syntect, trying to parse a sublime-syntax file without a name top level key causes a panic:

thread 'main' panicked at 'called Result::unwrap() on an Err value: ParseSyntax(MissingMandatoryKey("name"))'

But in Sublime Text, this key is optional (indeed, the "new syntax" template in ST doesn't contain a placeholder for it), so currently syntect cannot parse some valid syntaxes. If it is not provided, ST derives the name of the syntax from the filename - i.e. "Hello World.sublime-syntax" would have a name of "Hello World".

Difference in highlighting some TypeScript React files (Sublime vs. Syntect)

Syntect fails to properly syntax highlight some TypeScript React (tsx) files in contrast to Sublime Text 3 which highlights them fine.

To reproduce this:

  1. You'll need to first download Microsoft's official TypeScriptReact.tmLanguage file and save it somewhere.
  2. Convert that .tmLanguage file to a .sublime-syntax file, using Sublime Text 3's builtin Plugin Development: Convert Syntax to .sublime-syntax command (important: only shows up when viewing .tmLanguage files)
  3. Save the new .sublime-syntax file into e.g. testdata/Packages/TypeScript/TypeScriptReact.sublime-syntax
  4. Run make assets.

Alternatively, my fork's branch here has the above steps done so you don't have to perform them. The .sublime-syntax file is also in the root of the repo.

Once you've done the above or cloned my fork,

  1. Save this BasePicker.tsx test file anywhere.
  2. Save TypeScriptReact.sublime-syntax into e.g. ~/Library/Application\ Support/Sublime\ Text\ 3/Packages/User/ on Mac (and uninstall the TypeScript Sublime plugin, to prevent any concern over the tmLanguage -> sublime-syntax conversion potentially being the issue).

When the file is viewed in Sublime, it looks like this:

image

In contrast, the HTML rendered by cargo run --example synhtml ./BasePicker.tsx > out.html ends up looking like this:

image

Of course, the above two look different due to the theme in use, but notice that even just in the syntect result alone there are two different colors in use for the attributes:

image

I found that changing this line of code to remove the addition operator:

                suggestedDisplayValue={ suggestedDisplayValue }
-               aria-activedescendant={ 'sug-' + this.suggestionStore.currentIndex }
+               aria-activedescendant={ this.suggestionStore.currentIndex }
                aria-owns='suggestion-list'

Fixes the highlighting in Syntect:

image

If it wasn't for Sublime rendering this file with the same sublime-syntax, I would assume the syntax file was broken somehow -- but given the difference between Sublime and Syntect's rendering, I assume this must be a bug in Syntect (but I do not understand Syntect well enough to even begin tracking it down :) )

Incorrect push/pop order when combining meta scopes, content scopes and pushing multiple things

This is the bug that is causing at least some, probably most to all of the ASP tests to fail (cc @keith-hall).

The model of the parser outputting only the pushes and pops doesn't hold up to well in some cases. @keith-hall fixed the case of the weird behaviour of set, but I found another.

Consider the following section of the ASP syntax:

  class_definitions:
    - match: '\b(?i:Class)\s'
      scope: storage.type.asp
      push: [inside_class, class_name]

  class_name:
    - meta_scope: meta.class.asp meta.class.identifier.asp
    # ...
    - match: '{{identifier}}'
      scope: entity.name.class.asp
      pop: true
    # ...

  inside_class:
    - meta_content_scope: meta.class.asp meta.class.body.asp

Sublime Text passes the following test:

' SYNTAX TEST "Packages/ASP/ASP.sublime-syntax"
 Class TestClass2 Public Sub TestSub () Response.Write("wow") End Sub End Class
'^^^^^ meta.class.asp meta.class.identifier.asp storage.type.asp
'      ^ meta.class.asp meta.class.body.asp meta.class.asp meta.class.identifier.asp
'                ^ meta.class.asp meta.class.body.asp

Notice how when the meta_content_scope of inside_class is introduced after Class, it is introduced under meta.class.asp meta.class.identifier.asp.

syntect does not do this. It pushes the inside_class meta_content_scope on top, but then after TestClass2 when it pops the class_name context it pops 2 scopes, thinking it is popping the meta_scope of class_name, but actually the inside_class scopes are on top of the stack.

I see two ways of approaching this:

  • Make pushes like set is in Keith's set branch where they pop the early meta scopes and then re-apply them in the right order.
  • Make a breaking change to the API and scrap the idea of the parser outputting operations. Have stacks be linked lists instead of vectors, and have the parser output regions of text with a scope stack, where the scope stacks share tails. Unfortunately this would require a bunch of reference counting. It may be faster, it may be slower, I'm not sure. It would also be a bunch of work.

I'm inclined to take the first route. My worry is that if done simply it will lead to a bunch of redundant popping and pushing the same thing again in the case when only one item is pushed. It's probably a good idea to have a fast path for that case, although it would probably require a bunch more code.

[linux] error while loading shared libraries: libonig.so

Running "cargo run" on a basic project with syntect yields the following error:

target/debug/eta: error while loading shared libraries: libonig.so: cannot open shared object file: No such file or directory

I tried running

$ export LD_LIBRARY_PATH="./target/debug/build/onig_sys-*/out/lib/"

as it is suggested in the readme, but that doesn't help either.

Infinite Loop on C files

There's an infinite loop bug on some C files due to a broken pattern in the default Sublime C syntax that can cause an infinite loop. Despite the pattern being borked syntect should handle this gracefully like Sublime Text obviously does.

Example

text: struct{estruct

First it matches

- match: '(?={{before_tag}})'
   push: data-structures

at position 8 and then matches

- match: '(?=\S)'
      pop: true

at the same position, and then repeats.

Possible solution

No single pattern should be able to trigger more than once at the same location. Maybe keep track of which patterns have triggered and ignore any further matches, resetting the store upon advancing. The trick is maintaining performance.

Naming confusion in ThemeSettings

Comparing the documentation of ThemeSettings in theme.rs, and comparing that with the sublimetext documentation here, I'm confused in a few places.

  1. the ST docs describe selection and selectionForeground properties. The syntect docs describe selection and selectionBackground. In the actual InspiredGitHub theme, as loaded by syntect, selection has a value but selectionBackground is missing. This is surprising to me: I would expect that the background is more likely to be present than the foreground?

  2. Less significantly there are a few fields missing. None of these are critical (to me), but among the missing are inactiveSelectionForeground.

  3. There are some items for which the syntect docs are either unclear (foreground, selection) or have errors (find_highlight_foreground).

@trishume if you have anything to add here let me know, especially around item 1; then I'll PR as appropriate.

Incorrect behaviour when popping/setting main context

The current behaviour of treating the top level scope as a meta_content_scope on main doesn't match Sublime. From @keith-hall:

From my testing, I think the top level scope behaviour is:

  • for the top level syntax, the scope is never popped off the stack unless clear_scopes is used
  • pushing (or setting to) another syntax's main context will cause that syntax's top level scope to be pushed onto the stack, until the main context is no longer on the stack - i.e. like a meta content scope - so what you have now is correct from that regard
  • including (as opposed to pushing or setting) another syntax's main context will never cause that syntax's top level scope to be pushed onto the stack
  • pushing, setting or including a syntax's non-main context will never cause that syntax's top level scope to be pushed onto the stack

I think I can fix this by rewriting the syntax definitions on load. I'll add the following two contexts to every syntax:

__start:
  - meta_content_scope: some.file.scope
  - match: ''
     push: __main
# The difference below is that including it doesn't include the meta_content_scope
__main:
  - include: main

This actually fixes another problem as well which is that the Scala syntax actually can pop the main scope, which causes a panic since there is no context to take patterns from. With this it will just immediately re-push the main context, which I think is what Sublime does.

syntect handles push & immediately pop non-consuming patterns differently to ST

In ST, the following syntax:

%YAML 1.2
---
# See http://www.sublimetext.com/docs/3/syntax.html
name: push_pop_test
scope: source.push_pop_test
contexts:
  main:
    - match: (?=hello)
      push: test
  test:
    - match: (?!world)
      pop: true
    - match: \w+
      scope: comment.matched

accompanied by the following test passes:

# SYNTAX TEST "push_pop_test.sublime-syntax"
hello
# ^^^ comment.matched

in syntect, it doesn't:

loading syntax definitions from testdata/push_pop_test.sublime-syntax
Testing file testdata/syntax_test_push_pop_test.txt
The test file references syntax definition file: push_pop_test.sublime-syntax
-- debugging line 1 -- scope stack: ScopeStack { clear_stack: [], scopes: [] }
# SYNTAX TEST "push_pop_test.sublime-syntax"
^ +source.push_pop_test
-- debugging line 2 -- scope stack: ScopeStack { clear_stack: [], scopes: [<source.push_pop_test>] }
no operations for this line...
  Assertion selector "comment.matched" from line 3 failed against line 2, column range 2-5 (with text "llo") has scope [<source.push_pop_test>]
Ok(FailedAssertions(3, 3))
exiting with code 1

I believe this is due to how ST handles a match that:

  • consumes no characters and
  • pushes one context
  • where that context has a match which immediately pops without consuming any characters

In ST, it ignores the pop until at least one character has been consumed. Currently, syntect seems to push, then pop, then ignore the push again until at least one char has been consumed.

Related reading: sublimehq/sublime_text#1906 (comment)

This is the cause for most of the C# syntax test failures in syntect alluded to in #124 (comment) since sublimehq/Packages@e29d674#diff-9b5e53d4e14d87efc8f78017464d6b94.

New syntax embedding feature in sublime-syntax files

Sublime Text 3153 was just released with

a change to how syntax embedding works, which makes languages embedding lots of others more practical, and can also significantly reduce memory usage.

the changelog shows:

Syntax Highlighting: Add embed action to .sublime-syntax files, which can significantly reduce memory usage

No details or documentation updates yet, but wanted to log it here because I imagine we will want to add support for it to syntect.

Panic when given tex files

Syntect seems to panic when it is given (la)tex files.

Example

Using cargo run --example syncat test.tex with test.tex being:

\title{}

This gives the error:

thread 'main' panicked at 'Can only iterate patterns after linking: Named("$top_level_main")', src/parsing/syntax_definition.rs:136

(Removing the curly braces, i.e. if the file only contains \title, removes this error).

Markdown syntax test failure investigation

Although the Markdown syntax tests pass on Sublime Text build 3126, it is currently failing in syntect because syntect doesn't suffer from this bug: sublimehq/sublime_text#1190

Therefore, in syntect, https://github.com/trishume/Packages/blob/537d1bfa5bc205aa461b12eb3c996935e017e575/Markdown/Markdown.sublime-syntax#L758 is popping immediately after the push. As it is not a bug in syntect, and the aforementioned bug will be fixed in the next ST build, it can definitely be considered a bug in the syntax definition, which will need a tweak to continue working as expected.

The test line in question is:

- `code` - <a name="demo"></a>
|          ^^^^^^^^^^^^^^^^^^^ meta.tag.inline.a.html

Switch docs to use docs.rs

Before I raise any PRs, I was wondering if you're ok with switching the docs to use docs.rs instead of hosting them yourself. That has a couple of advantages:

  • It makes the build simpler (we can just remove that step)
  • It means the docs are available for older versions as well
  • We can add a badge for it

There's disadvantages as well:

  • It's run by someone other than you :). But given that so many crates use it (including crates by the rust-lang team), the Rust community has a pretty big interest in keeping the site up.

You can check out the docs here: https://docs.rs/syntect/

Only annotate with class name

Would it be possible to have a mode where it only sets some classes like Pygment does?
That makes it trivial for a end user (for example someone using a static site engine) to use whatever theme they want just by changing some CSS.

Looking at http://docs.sublimetext.info/en/latest/reference/color_schemes.html I couldn't find any info whether it's possible possible to have a custom theme that will just add a class rather than add a style?

Not a big deal if it's out of scope for the project

Several `panick`s when trying to run tests

I'm on macOS 10.12.1, rustc 1.13.0, and a fresh cargo test reports the following failures.

    Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs
     Running target/debug/deps/syntect-a38ef98faf98fd4c

running 20 tests
test highlighting::selector::tests::matching_works ... ok
test highlighting::selector::tests::selectors_work ... ok
test dumps::tests::can_dump_and_load ... FAILED
test highlighting::highlighter::tests::can_parse ... FAILED
test html::tests::tricky_test_syntax ... FAILED
test parsing::scope::tests::global_repo_works ... ok
test parsing::scope::tests::matching_works ... ok
test parsing::scope::tests::misc ... ok
test parsing::parser::tests::can_parse ... FAILED
test parsing::scope::tests::prefixes_work ... ok
test parsing::scope::tests::repo_works ... ok
test parsing::syntax_definition::tests::can_compile_refs ... ok
test parsing::yaml_load::tests::can_parse ... ok
test parsing::syntax_set::tests::can_load ... FAILED
test highlighting::theme_set::tests::can_parse_common_themes ... ok
test easy::tests::can_find_regions ... ok
test easy::tests::can_highlight_file ... ok
test easy::tests::can_highlight_lines ... ok
test html::tests::tokens ... ok
test html::tests::strings ... ok

failures:

---- dumps::tests::can_dump_and_load stdout ----
	thread 'dumps::tests::can_dump_and_load' panicked at 'called `Result::unwrap()` on an `Err` value: ParseSyntax(MissingMandatoryKey("match"))', ../src/libcore/result.rs:799
note: Run with `RUST_BACKTRACE=1` for a backtrace.

---- highlighting::highlighter::tests::can_parse stdout ----
	thread 'highlighting::highlighter::tests::can_parse' panicked at 'called `Result::unwrap()` on an `Err` value: ParseSyntax(MissingMandatoryKey("match"))', ../src/libcore/result.rs:799

---- html::tests::tricky_test_syntax stdout ----
	thread 'html::tests::tricky_test_syntax' panicked at 'called `Result::unwrap()` on an `Err` value: ParseSyntax(MissingMandatoryKey("match"))', ../src/libcore/result.rs:799

---- parsing::parser::tests::can_parse stdout ----
	thread 'parsing::parser::tests::can_parse' panicked at 'called `Result::unwrap()` on an `Err` value: ParseSyntax(MissingMandatoryKey("match"))', ../src/libcore/result.rs:799

---- parsing::syntax_set::tests::can_load stdout ----
	thread 'parsing::syntax_set::tests::can_load' panicked at 'called `Result::unwrap()` on an `Err` value: ParseSyntax(MissingMandatoryKey("match"))', ../src/libcore/result.rs:799


failures:
    dumps::tests::can_dump_and_load
    highlighting::highlighter::tests::can_parse
    html::tests::tricky_test_syntax
    parsing::parser::tests::can_parse
    parsing::syntax_set::tests::can_load

test result: FAILED. 15 passed; 5 failed; 0 ignored; 0 measured

error: test failed

Any thoughts? Can I provide more information or help out in some way?

Parsing simple Groovy file takes 10 s

The UnmanagedNodeBackedModelMapTest.groovy file from the gradle sources takes 10 seconds to parse, on current master (f03fa0f):

$ curl -LO "https://github.com/gradle/gradle/raw/aa8c200808824c61f2c46ed1eb948c759c9483c2/subprojects/model-core/src/test/groovy/org/gradle/model/UnmanagedNodeBackedModelMapTest.groovy"
$ cargo build --release --example syncat
$ time ./target/release/examples/syncat UnmanagedNodeBackedModelMapTest.groovy
...
    9.72s user 0.04s system 99% cpu 9.811 total

Don't use inline CSS for HTML output

Inline CSS can be used inside XSS attacks. That's why it is generally a good thing to disable inline CSS via the CSP header.

However, this library outputs HTML that uses inline CSS. Instead I'd love to see a mode (maybe even change of the default?) where the HTML output uses class="..." instead of style="...", with a separate function that returns appropriate CSS code for a given Theme instance. You could then still have inline CSS via <style></style> tags, but you'd have a choice. Also, it might not be relevant as those strings would show up in huffman trees pretty quickly (so any gzip like transfer compression would make the effects irrelevant), but style="color:#96b5b4;" takes up more space than class="highlight". Bonus points that switching themes would now only mean switching of css files!

Java syntax definition gets confused by Foo.class

With the following Java source:

public class Test {

    void test1() {
        Foo.class;
    }

    void test2() {
    }
}

Syntect (8ea3944) gets confused by the Foo.class line. All the source code after that line is incorrectly/not highlighted. Removing the line fixes it. It also happens when the Foo.class is part of an expression (e.g. used as an argument).

This may be related to #51, but I wasn't sure. (And it doesn't hurt to have another issue.)

included contexts should still be able to pop using backrefs

Now that #101 is fixed, I was able to get the ASP syntax tests to pass by changing the syntax definition to not include a with_prototype conflict - namely by changing [1] and [2] from scope:text.html.asp#html to scope:text.html.basic:

loading syntax definitions from testdata/Packages/
Testing file testdata/Packages/ASP/syntax_test_asp.asp
The test file references syntax definition file: Packages/ASP/HTML-ASP.sublime-syntax
Ok(Success(4071))
Testing file testdata/Packages/ASP/syntax_test_asp2.asp2
The test file references syntax definition file: Packages/ASP/HTML-ASP2.sublime-syntax
Ok(Success(16))
exiting with code 0

Emboldened by that, I decided to try some more syntaxes out (SublimeText/PackageDev#98), but found a bug. In ST, it is always possible for a match pattern that will pop to use back references captured from the original push pattern, regardless of whether that pattern is a direct child of the context that was pushed, or was included from it at any nesting. In syntect, it only seems to allow back references that refer to the original push pattern if the pop pattern is a direct child of the context that was pushed onto the stack.

In syntect, an included context trying to access the back references currently causes a panic (please expand the arrow to the left of this paragraph for the backtrace).
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/option.rs:323
stack backtrace:
   1:       0x2d4be997fa - std::sys::imp::backtrace::tracing::imp::write::h3188f035833a2635
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:       0x2d4be9c4df - std::panicking::default_hook::{{closure}}::h6385b6959a2dd25b
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:349
   3:       0x2d4be9c0de - std::panicking::default_hook::he4f3b61755d7fa95
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:365
   4:       0x2d4be9c927 - std::panicking::rust_panic_with_hook::hf00b8130f73095ec
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:553
   5:       0x2d4be9c764 - std::panicking::begin_panic::h6227f62cb2cdaeb4
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:515
   6:       0x2d4be9c6d9 - std::panicking::begin_panic_fmt::h173eadd80ae64bec
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:499
   7:       0x2d4be9c667 - rust_begin_unwind
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:475
   8:       0x2d4bec898d - core::panicking::panic_fmt::h3b2d1e30090844ff
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/panicking.rs:69
   9:       0x2d4bec88c4 - core::panicking::panic::h2596388ccef1871c
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/panicking.rs:49
  10:       0x2d4bc27856 - <core::option::Option<T>>::unwrap::hcbcf6267c1bc19a7
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libcore/macros.rs:21
  11:       0x2d4bca0728 - syntect::parsing::parser::ParseState::parse_next_token::h0647d274e681b640
                        at /home/keith/Documents/syntect-master/src/parsing/parser.rs:201
  12:       0x2d4bc9f74a - syntect::parsing::parser::ParseState::parse_line::h89d6548f1cea9c1e
                        at /home/keith/Documents/syntect-master/src/parsing/parser.rs:103
  13:       0x2d4bbff152 - syntest::test_file::hf2ec9e02ad06e0c2
                        at /home/keith/Documents/syntect-master/examples/syntest.rs:191
  14:       0x2d4bc00314 - syntest::recursive_walk::he846690fb982efe6
                        at /home/keith/Documents/syntect-master/examples/syntest.rs:270
  15:       0x2d4bbffde8 - syntest::main::h78e5d2a4f07ea011
                        at /home/keith/Documents/syntect-master/examples/syntest.rs:256
  16:       0x2d4bea37ba - __rust_maybe_catch_panic
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libpanic_unwind/lib.rs:98
  17:       0x2d4be9d066 - std::rt::lang_start::h65647f6e36cffdae
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panicking.rs:434
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/panic.rs:351
                        at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/src/libstd/rt.rs:57
  18:       0x2d4bc00bf2 - main
  19:     0x7fd5e385782f - __libc_start_main
  20:       0x2d4bbd8ad8 - _start
  21:                0x0 - <unknown>

I've managed to put a small example syntax together that exhibits this behavior:

%YAML 1.2
---
name: Include Backref Pop Test
scope: text.includebackrefpop.syntect
contexts:
  main:
    - match: '(<)(string)\s*(>)'
      scope: meta.tag.xml
      captures:
        1: punctuation.definition.tag.begin.xml
        2: entity.name.tag.localname.xml
        3: punctuation.definition.tag.end.xml
      set:
        - meta_content_scope: meta.inside-value.string.plist
        - include: pop-tag-no-children

  pop-tag-no-children:
    - match: '(</)(\2)\s*(>)'
      scope: meta.tag.xml
      captures:
        1: punctuation.definition.tag.begin.xml
        2: entity.name.tag.localname.xml
        3: punctuation.definition.tag.end.xml
      pop: true
    # - match: '<(?!!)'
    #   scope: punctuation.definition.tag.begin.xml
    #   push: unknown-tag
    #- include: scope:text.xml

  # unknown-tag:
  #   - meta_scope: meta.tag.xml
  #   - meta_content_scope: invalid.illegal.unknown-or-unexpected-tag.plist
  #   - match: '>'
  #     scope: punctuation.definition.tag.end.xml
  #     pop: true

which can be used with the following syntax test:

# SYNTAX TEST "include_backref_pop.sublime-syntax"
<string>
</string>
# ^^^^^^ entity.name.tag.localname.xml

Getting output for terminal

I've been browsing through the examples & docs and I'm very glad to see this library exists!

I'm making a markdown previewer for the terminal. During codeblocks I have information (usually) about the language and a string reference for the code that I need to highlight, I need to output it colored for your average 24-bit terminal. I got this so far:

    fn highlight_lines(&self, s: &str, buf: &mut String) {
        let ts = ThemeSet::load_defaults();
        let ps = SyntaxSet::load_defaults_nonewlines();

        let syntax = if let Some(ref lang) = self.lang {
            ps.find_syntax_by_name(lang)
        } else {
            ps.find_syntax_by_first_line(s)
        }.unwrap_or_else(|| ps.find_syntax_plain_text());

        let mut h = HighlightLines::new(syntax, &ts.themes["base16-ocean.dark"]);
        for line in s.lines() {
            let ranges: Vec<(Style, &str)> = h.highlight(line);
            let escaped = as_24_bit_terminal_escaped(&ranges[..], false);
            buf.push_str(&escaped);
        }
    }

This function takes close to 10 seconds to run (it gets executed twice on short strings) and doesn't colour the output at all. I was hoping you could point me in the direction of what I'm doing incorrectly.

So long as I select one of the 'default' themes, I don't need to actually have a theme file locally right?

600 line Rust source file takes more than 2 minutes

How to reproduce (link to view file):

curl -LO 'https://github.com/rust-lang/rust/raw/a6fe6c9be10c79d64c988d490519f5cc07e9060d/src/librustc_borrowck/borrowck/mir/dataflow/impls.rs'
time target/release/examples/synstats impls.rs

Running with syntect from master (currently 431174d), this is the output of time:

target/release/examples/synstats impls.rs  141.49s user 0.54s system 99% cpu 2:22.71 total

Sublime text build 3125 seems to have no problem with the file and loads instantly.

good place to mention HTTP server?

Feel free to close this issue if this is the wrong place to ask/mention this!

I had the requirement of using Syntect from another language (Go) so I chose to communicate with Syntect via an HTTP server (rocket.rs). While doing this, I ran into various issues as a Rust beginner and came across threads like #20 and it seems like others have had the same idea (exposing Syntect via HTTP) but I didn't successfully find any open source version of this. I ended up creating:

https://github.com/sourcegraph/syntect_server

I figured the least I could do is post on this issue tracker for future people like myself in the future to hopefully run across this, as it may help them.

I also wanted to ask if you would accept a PR to add a "Projects using Syntect" section to the README (or somewhere else if you prefer) since I think that would be useful for folks looking for an HTTP-server variant, and also for beginners like myself to understand usage of Syntect? I can send this if you agree :)

Syntect fails to build when combined with serde

I ran into this problem with cobalt. I hacked around it by disabling the default features I didn't need.

Example error

error[E0308]: mismatched types
  --> /home/epage/.cargo/registry/src/github.com-1ecc6299db9ec823/syntect-1.7.0/src/parsing/yaml_load.rs:90:34
   |
90 |         if let Ok(map) = get_key(h, "variables", |x| x.as_hash()) {
   |                                  ^ expected struct `std::collections::BTreeMap`, found struct `linked_hash_map::LinkedHashMap`
   |
   = note: expected type `&std::collections::BTreeMap<yaml_rust::Yaml, yaml_rust::Yaml>`
              found type `&linked_hash_map::LinkedHashMap<yaml_rust::Yaml, yaml_rust::Yaml>`
   = help: here are some functions which might fulfill your needs:
           - .hasher()

In case there is something weird we are doing with syntect

Split syntect into multiple crates

As we've been discussing here, It would be helpful for Xi if the parsing and the theme application components of syntect were available as separate crates.

Q: Might it make sense to also separate the syntax_definition module into a crate? It could be nice to take advantage of the syntax detection features it offers, instead of rolling our own.

I'm happy to take a stab at this work at some point, but would appreciate any preliminary guidance. Is this mostly a matter of turning the highlighting module into a crate? Any additional foreseeable challenges?

Panic: Can only iterate patterns after linking: Named("types") with C# file

Reproduce on master with 1748efe:

$ cat bug.cs
public class Foo
{
    private static void Bar()
    {
        baz.Sort((a, b) => b.depth.CompareTo(a.depth));
    }
}
$ cargo build --example synstats && RUST_BACKTRACE=1 ./target/debug/examples/synstats bug.cs

Output:

################## Files ###################
bug.cs
thread 'main' panicked at 'Can only iterate patterns after linking: Named("types")', src/parsing/syntax_definition.rs:137
stack backtrace:
   1:        0x105c130ea - std::sys::imp::backtrace::tracing::imp::write::hd3b65cdfe843284c
   2:        0x105c14e8f - std::panicking::default_hook::{{closure}}::hf2b7428652613d83
   3:        0x105c14b37 - std::panicking::default_hook::h5da8f27db5582938
   4:        0x105c152f6 - std::panicking::rust_panic_with_hook::hcef1e67c646c6802
   5:        0x105c15194 - std::panicking::begin_panic::hc2e8ca89533cd10d
   6:        0x105c150b2 - std::panicking::begin_panic_fmt::h60990696c3c3a88d
   7:        0x105bd40e8 - <syntect::parsing::syntax_definition::MatchIter as core::iter::iterator::Iterator>::next::h0fc92fde02d6dd7f
   8:        0x105bdc6ea - syntect::parsing::parser::ParseState::parse_next_token::h7b5d8225fe16d480
   9:        0x105bdbf28 - syntect::parsing::parser::ParseState::parse_line::hde79bb6ed3c527e5
  10:        0x105b66cbd - synstats::count::h5c86d3300a80813b
  11:        0x105b6739e - synstats::main::h761e13430343e881
  12:        0x105c160ea - __rust_maybe_catch_panic
  13:        0x105c15696 - std::rt::lang_start::h87cb84a8b6cb187e
  14:        0x105b67839 - main

The Sort line is the problematic one. The original file had a lot more code in it, but removing that line makes it work.

Can't build on Windows because onig_sys doesn't build on Windows

error: failed to run custom build command for onig_sys v61.1.0

I am compiling the rust program https://github.com/trishume/syntect by running make packs. However it throws the error:

$ make packs
cargo run --example gendata -- synpack testdata/Packages assets/default_newlines.packdump assets/default_nonewlines.packdump
   Compiling onig_sys v61.1.0
error: failed to run custom build command for `onig_sys v61.1.0`
process didn't exit successfully: `D:\syntect\target\debug\build\onig_sys-523c993a9ee13532\build-script-build` (exit code: 101)

...

--- stderr
DIST_NAME: onig
DIST_VERSION: 6.1.1
DIST_LICENSE: BSD
DIST_AUTHOR: K.Kosako
DIST_MAINTAINER: K.Kosako
DIST_URL: https://github.com/kkos/oniguruma
DIST_DESC: Oniguruma is a regular expressions library.
DIST_DEPENDS:
thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\cmake-0.1.21\src\lib.rs:605
note: Run with `RUST_BACKTRACE=1` for a backtrace.

make: *** [packs] Error 101

Why the https://github.com/kkos/oniguruma is not compiling?

I ran cargo build -vv and got this most all the log:

D:\syntect>cargo build -vv
       Fresh num-traits v0.1.37
       Fresh winapi-build v0.1.1
       Fresh pkg-config v0.3.9
       Fresh gcc v0.3.45
       Fresh regex-syntax v0.4.0
       Fresh num-integer v0.1.33
       Fresh cmake v0.1.21
       Fresh num-iter v0.1.33
       Fresh lazy_static v0.2.4
       Fresh winapi v0.2.8
       Fresh yaml-rust v0.3.5
       Fresh serde v0.8.23
       Fresh bitflags v0.7.0
       Fresh num v0.1.37
       Fresh xml-rs v0.3.6
       Fresh rustc-serialize v0.3.23
       Fresh bitflags v0.8.0
       Fresh fnv v1.0.5
       Fresh serde v0.9.11
       Fresh kernel32-sys v0.2.2
       Fresh byteorder v1.0.0
       Fresh bincode v0.6.1
   Compiling onig_sys v61.1.0
       Fresh same-file v0.1.3
       Fresh libc v0.2.21
     Running `D:\syntect\target\debug\build\onig_sys-523c993a9ee13532\build-scrip
t-build`
       Fresh byteorder v0.5.3
       Fresh walkdir v1.0.7
       Fresh miniz-sys v0.1.9
       Fresh time v0.1.36
       Fresh flate2 v0.2.17
       Fresh chrono v0.2.25
       Fresh plist v0.1.2
running: "cmake" "C:\\Users\\Professional\\.cargo\\registry\\src\\github.com-1ecc6299db9ec823\\onig_sys-61.1.0\\oniguruma" "-G" "Visual Studio 14 2015 Win64" "-DBUILD_SHARED_LIBS=OFF" "-
DCMAKE_INSTALL_PREFIX=D:\\syntect\\target\\debug\\build\\onig_sys-d633e
4c1e0d45051\\out" "-DCMAKE_C_FLAGS= /nologo /MD" "-DCMAKE_C_FLAGS_RELEASE= /nologo /MD" "-DCMAKE_CXX_FLAGS= /nologo /MD" "-DCMAKE_CXX_FLAGS_RELEASE= /nologo /MD" "-DCMAKE_BUILD_TYPE=Rele
ase"
DIST_NAME: onig
DIST_VERSION: 6.1.1
DIST_LICENSE: BSD
DIST_AUTHOR: K.Kosako
DIST_MAINTAINER: K.Kosako
DIST_URL: https://github.com/kkos/oniguruma
DIST_DESC: Oniguruma is a regular expressions library.
DIST_DEPENDS:
-- Configuring done
-- Generating done
-- Build files have been written to: D:/syntect/target/debug/build/onig_sys-d633e
4c1e0d45051/out/build
running: "cmake" "--build" "." "--target" "install" "--config" "Release" "--"
Microsoft (R) Build Engine version 14.0.24723.2
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 17/03/2017 15:41:57.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" on node 1 (default targets).
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" (1) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d450
51\out\build\ZERO_CHECK.vcxproj" (2) on node 1 (default targets).
InitializeBuildStatus:
  Creating "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
  All outputs are up-to-date.
  Checking Build System
  CMake does not need to re-run because D:/syntect/target/debug/build/onig_sys-d6
33e4c1e0d45051/out/build/CMakeFiles/generate.stamp is up-to-date.
FinalizeBuildStatus:
  Deleting file "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild".
  Touching "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\ZERO_CHECK.lastbuildstate".
Done Building Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\ou
t\build\ZERO_CHECK.vcxproj" (default targets).
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" (1) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d450
51\out\build\ALL_BUILD.vcxproj" (3) on node 1 (default targets).
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\ALL_BU
ILD.vcxproj" (3) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d4
5051\out\build\onig.vcxproj" (4) on node 1 (default targets).
InitializeBuildStatus:
  Touching "onig.dir\Release\onig.tlog\unsuccessfulbuild".
CustomBuild:
  All outputs are up-to-date.
  Building Custom Rule C:/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-61.1.0/oniguruma/CMakeLists.txt
  CMake does not need to re-run because D:/syntect/target/debug/build/onig_sys-d6
33e4c1e0d45051/out/build/CMakeFiles/generate.stamp is up-to-date.
ClCompile:
  F:\VisualStudio2015\VC\bin\x86_amd64\CL.exe /c /I"D:\syntect\target\debug\build
\onig_sys-d633e4c1e0d45051\out\build" /I"C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma" /nologo /W1 /WX- /O2 /D _CRT_SECURE_NO_WARNINGS
/D "CMAKE_INTDIR=\"Release\"" /D _MBCS /Gm- /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"onig.dir\Release\\" /Fd"onig.dir\Release\onig.pdb" /Gd /TC /errorReport:queue "C:\
Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c"
  regenc.c
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): warning C4273: 'OnigEncDefaultCharEncoding': inconsistent dll linkage [D
:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(227): note: see previous definition of 'OnigEncDefaultCharEncoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): error C2099: initializer is not a constant [D:\User\\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(36): warning C4273: 'onigenc_init': inconsistent dll linkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(343): note: see previous definition of 'onigenc_init'
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(345): note: see previous definition of 'onig_initialize_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(53): warning C4273: 'onigenc_get_default_encoding': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(349): note: see previous definition of 'onigenc_get_default_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(59): warning C4273: 'onigenc_set_default_encoding': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(347): note: see previous definition of 'onigenc_set_default_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(66): warning C4273: 'onigenc_get_right_adjust_char_head': inconsistent dll li
nkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcx
proj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(359): note: see previous definition of 'onigenc_get_right_adjust_char_he
ad'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(77): warning C4273: 'onigenc_get_right_adjust_char_head_with_prev': inconsist
ent dll linkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\buil
d\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(353): note: see previous definition of 'onigenc_get_right_adjust_char_he
ad_with_prev'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(92): warning C4273: 'onigenc_get_prev_char_head': inconsistent dll linkage [D
:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(355): note: see previous definition of 'onigenc_get_prev_char_head'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(101): warning C4273: 'onigenc_step_back': inconsistent dll linkage [D:\User\D
ropbox\Applications\SoftwareVersioning\SublimeText\Data\Packages\ObjectBeautifier\source\libraries\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(338): note: see previous definition of 'onigenc_step_back'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(127): warning C4273: 'onigenc_step': inconsistent dll linkage [D:\User\Dropbo
x\Applications\SoftwareVersioning\SublimeText\Data\Packages\ObjectBeautifier\source\libraries\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(222): note: see previous definition of 'onigenc_step'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(137): warning C4273: 'onigenc_strlen': inconsistent dll linkage [D:\User\Drop
box\Applications\SoftwareVersioning\SublimeText\Data\Packages\ObjectBeautifier\source\libraries\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(361): note: see previous definition of 'onigenc_strlen'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(150): warning C4273: 'onigenc_strlen_null': inconsistent dll linkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(363): note: see previous definition of 'onigenc_strlen_null'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(175): warning C4273: 'onigenc_str_bytelen_null': inconsistent dll linkage [D:
\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(365): note: see previous definition of 'onigenc_str_bytelen_null'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(197): warning C4273: 'OnigEncAsciiToLowerCaseTable': inconsistent dll linkage
 [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]

  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(228): note: see previous definition of 'OnigEncAsciiToLowerCaseTable'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(269): warning C4273: 'OnigEncAsciiCtypeTable': inconsistent dll linkage [D:\U
ser\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(230): note: see previous definition of 'OnigEncAsciiCtypeTable'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(304): warning C4273: 'OnigEncISO_8859_1_ToLowerCaseTable': inconsistent dll l
inkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vc
xproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(216): note: see previous definition of 'OnigEncISO_8859_1_ToLowerCaseTable'


"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\install.vcxpro
j" (default target) (1) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\ALL_BUILD.vcxp
roj" (default target) (3) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj"
(default target) (4) ->
(ClCompile target) ->
  C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): error C2099: initializer is not a constant [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]

    45 Warning(s)
    1 Error(s)

Time Elapsed 00:00:03.85
thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\cmake-0.1.21\src\lib.rs:605
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: failed to run custom build command for `onig_sys v61.1.0`
process didn't exit successfully: `D:\syntect\target\debug\build\onig_sys-523c993
a9ee13532\build-script-build` (exit code: 101)
--- stdout
running: "cmake" "C:\\Users\\Professional\\.cargo\\registry\\src\\github.com-1ecc6299db9ec823\\onig_sys-61.1.0\\oniguruma" "-G" "Visual Studio 14 2015 Win64" "-DBUILD_SHARED_LIBS=OFF" "-
DCMAKE_INSTALL_PREFIX=D:\\User\\syntect\\target\\debug\\build\\onig_sys-d633e
4c1e0d45051\\out" "-DCMAKE_C_FLAGS= /nologo /MD" "-DCMAKE_C_FLAGS_RELEASE= /nologo /MD" "-DCMAKE_CXX_FLAGS= /nologo /MD" "-DCMAKE_CXX_FLAGS_RELEASE= /nologo /MD" "-DCMAKE_BUILD_TYPE=Rele
ase"
-- Configuring done
-- Generating done
-- Build files have been written to: D:/syntect/target/debug/build/onig_sys-d633e
4c1e0d45051/out/build
running: "cmake" "--build" "." "--target" "install" "--config" "Release" "--"
Microsoft (R) Build Engine version 14.0.24723.2
Copyright (C) Microsoft Corporation. All rights reserved.

Build started 17/03/2017 15:41:57.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" on node 1 (default targets).
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" (1) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d450
51\out\build\ZERO_CHECK.vcxproj" (2) on node 1 (default targets).
InitializeBuildStatus:
  Creating "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.
CustomBuild:
  All outputs are up-to-date.
  Checking Build System
  CMake does not need to re-run because D:/syntect/target/debug/build/onig_sys-d6
33e4c1e0d45051/out/build/CMakeFiles/generate.stamp is up-to-date.
FinalizeBuildStatus:
  Deleting file "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\unsuccessfulbuild".
  Touching "x64\Release\ZERO_CHECK\ZERO_CHECK.tlog\ZERO_CHECK.lastbuildstate".
Done Building Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\ou
t\build\ZERO_CHECK.vcxproj" (default targets).
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
The target "BeforeGenerateProjectPriFile" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\Microsoft\NuGet\Microsoft.NuGet.targets (186,61)" does not exist in the p
roject, and will be ignored.
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\instal
l.vcxproj" (1) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d450
51\out\build\ALL_BUILD.vcxproj" (3) on node 1 (default targets).
Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\ALL_BU
ILD.vcxproj" (3) is building "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d4
5051\out\build\onig.vcxproj" (4) on node 1 (default targets).
InitializeBuildStatus:
  Touching "onig.dir\Release\onig.tlog\unsuccessfulbuild".
CustomBuild:
  All outputs are up-to-date.
  Building Custom Rule C:/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/onig_sys-61.1.0/oniguruma/CMakeLists.txt
  CMake does not need to re-run because D:/syntect/target/debug/build/onig_sys-d6
33e4c1e0d45051/out/build/CMakeFiles/generate.stamp is up-to-date.
ClCompile:
  F:\VisualStudio2015\VC\bin\x86_amd64\CL.exe /c /I"D:\syntect\target\debug\build
\onig_sys-d633e4c1e0d45051\out\build" /I"C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma" /nologo /W1 /WX- /O2 /D _CRT_SECURE_NO_WARNINGS
/D "CMAKE_INTDIR=\"Release\"" /D _MBCS /Gm- /MD /GS /fp:precise /Zc:wchar_t /Zc:forScope /Zc:inline /Fo"onig.dir\Release\\" /Fd"onig.dir\Release\onig.pdb" /Gd /TC /errorReport:queue "C:\
Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c"
  regenc.c
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): warning C4273: 'OnigEncDefaultCharEncoding': inconsistent dll linkage [D
:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(227): note: see previous definition of 'OnigEncDefaultCharEncoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): error C2099: initializer is not a constant [D:\User\\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(36): warning C4273: 'onigenc_init': inconsistent dll linkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(343): note: see previous definition of 'onigenc_init'
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(345): note: see previous definition of 'onig_initialize_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(53): warning C4273: 'onigenc_get_default_encoding': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(349): note: see previous definition of 'onigenc_get_default_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(59): warning C4273: 'onigenc_set_default_encoding': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(347): note: see previous definition of 'onigenc_set_default_encoding'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(66): warning C4273: 'onigenc_get_right_adjust_char_head': inconsistent dll li
nkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcx
proj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(359): note: see previous definition of 'onigenc_get_right_adjust_char_he
ad'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(77): warning C4273: 'onigenc_get_right_adjust_char_head_with_prev': inconsist
ent dll linkage [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\buil
d\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\oniguruma.h(353): note: see previous definition of 'onigenc_get_right_adjust_char_he
ad_with_prev'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(861): warning C4273: 'onigenc_mb4_is_code_ctype': inconsistent dll linkage [D
:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(149): note: see previous definition of 'onigenc_mb4_is_code_ctype'
C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(876): warning C4273: 'onigenc_with_ascii_strncmp': inconsistent dll linkage [
D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  c:\users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.h(220): note: see previous definition of 'onigenc_with_ascii_strncmp'
Done Building Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\ou
t\build\onig.vcxproj" (default targets) -- FAILED.
Done Building Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\ou
t\build\ALL_BUILD.vcxproj" (default targets) -- FAILED.
Done Building Project "D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\ou
t\build\install.vcxproj" (default targets) -- FAILED.

Build FAILED.

"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\install.vcxpro
j" (default target) (1) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\ALL_BUILD.vcxp
roj" (default target) (3) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj"
(default target) (4) ->
(ClCompile target) ->
  C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): warning C4273: 'OnigEncDefaultCharEncoding': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(861): warning C4273: 'onigenc_mb4_is_code_ctype': inconsistent dll linkage
[D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]
  C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(876): warning C4273: 'onigenc_with_ascii_strncmp': inconsistent dll linkage
 [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]



"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\install.vcxpro
j" (default target) (1) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\ALL_BUILD.vcxp
roj" (default target) (3) ->
"D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj"
(default target) (4) ->
(ClCompile target) ->
  C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\onig_sys-61.1.0\oniguruma\src\regenc.c(32): error C2099: initializer is not a constant [D:\syntect\target\debug\build\onig_sys-d633e4c1e0d45051\out\build\onig.vcxproj]

    45 Warning(s)
    1 Error(s)

Time Elapsed 00:00:03.85

--- stderr
DIST_NAME: onig
DIST_VERSION: 6.1.1
DIST_LICENSE: BSD
DIST_AUTHOR: K.Kosako
DIST_MAINTAINER: K.Kosako
DIST_URL: https://github.com/kkos/oniguruma
DIST_DESC: Oniguruma is a regular expressions library.
DIST_DEPENDS:
thread 'main' panicked at '
command did not execute successfully, got: exit code: 1

build script failed, must exit now', C:\Users\User\.cargo\registry\src\github.com-1ecc6299db9ec823\cmake-0.1.21\src\lib.rs:605
note: Run with `RUST_BACKTRACE=1` for a backtrace.


D:\syntect>

with_prototype syntax test failures

I've finally had chance to investigate #59 a little bit, and found something interesting.

Let's say we have a file testdata/Packages/ASP/HTML-ASP2.sublime-syntax with the following contents (it's basically a cut down version of the full HTML-ASP syntax, that doesn't reference ASP itself and can serve as a(n almost minimal) complete verifiable example):

%YAML 1.2
---
# http://www.sublimetext.com/docs/3/syntax.html
name: HTML (ASP)2
file_extensions:
  - asp2
scope: text.html.asp2
contexts:
  main:
    - include: html

  asp_punctuation_begin:
    - match: '<%'
      scope: punctuation.section.embedded.begin.asp
      push:
        - match: '(?=\S)'
          set: [close_embedded_asp, begin_embedded_asp]

  html:
    - match: ''
      set:
        - include: scope:text.html.basic
      with_prototype:
        - include: asp_punctuation_begin

  begin_embedded_asp:
    - meta_content_scope: source.asp.embedded.html
    - match: '(?=%>)'
      pop: true

  close_embedded_asp:
    - match: '%>'
      scope: punctuation.section.embedded.end.asp
      pop: true

and the following corresponding syntax test (testdata/Packages/ASP/syntax_test_asp2.asp2):

' SYNTAX TEST "Packages/User/HTML-ASP2.sublime-syntax"
<html><% example <%
' ^^^ meta.tag.structure.any.html entity.name.tag.structure.any.html
'     ^^ punctuation.section.embedded.begin.asp
'        ^^^^^^^^^^^ source.asp.embedded.html - punctuation

and execute syntest with RUST_BACKTRACE=1 cargo run --example syntest testdata/Packages/ASP/syntax_test_asp2.asp2 testdata/Packages/

The output is:

loading syntax definitions from testdata/Packages/
Testing file testdata/Packages/ASP/syntax_test_asp2.asp2
The test file references syntax definition file: Packages/ASP/HTML-ASP2.sublime-syntax
  Assertion selector "source.asp.embedded.html - punctuation" from line 5 failed against line 2, column range 17-19 (with text "<%") has scope [<text.html.asp2>, <source.asp.embedded.html>, <punctuation.section.embedded.begin.asp>]
Ok(FailedAssertions(2, 16))
exiting with code 1

but in ST, if we look at the scopes, we see the <% which had a failure in syntect has no special scopes applied to it.
image

so we can conclude that the with_prototype is being applied in syntect to the begin_embedded_asp context, but isn't in ST. I suspect there is a general rule that the with_prototype shouldn't apply to nested contexts pushed by matches made in itself, if that makes sense.

i.e. estimated rough sequence of events:

  • the anonymous context inside the html context is pushed onto the stack, with the asp_punctuation_begin context in the with_prototype
  • eventually the <% match pattern from that context is hit, and it pushes a new anonymous context - this context should no longer have the asp_punctuation_begin with_prototype applied to it
  • the begin_embedded_asp context replaces the anonymous context at the top of the stack
  • because syntect is still applying the with_prototype, the <% after example gets matched unexpectedly/incorrectly and scoped.

Rust syntax highlighting not correct in "use" section

I don't have Sublime Text so can't verify whether the issue is present there as well. When highlighting a Rust file, it seems choose arbitrary lines to highlight in the "use" section:

This text:

#[macro_use] extern crate iron;
extern crate router;
extern crate params;
extern crate bodyparser;

extern crate crypto;
extern crate rand;
extern crate syntect;

use std::fs;
use std::fs::File;
use std::path::Path;
use std::io::Write;
use std::io::Read;
use std::io::BufRead;

use iron::headers::ContentType;
use iron::modifiers::Header;
use iron::prelude::*;
use iron::status;

use params::{Params, Value};
use router::Router;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::sha2::Sha256;

use rand::Rng;

use syntect::parsing::SyntaxSet;
use syntect::highlighting::{ThemeSet, Style};
use syntect::util::as_24_bit_terminal_escaped;
use syntect::easy::HighlightLines;

highlights with the Rust highlighter (as determined by the "rs" extension) are as follows:

screenshot

Note that the keyword "use" is sometimes colored, sometimes not.

Fix nonewlines mode

As noted in #34 (comment), nonewlines mode uses \z in character classes, but that just acts as z and not end of string. This presents a few problems:

  • Patch it so nonewlines doesn't mess up in the presence of z.
  • Act properly in terms matching the end of the string, this may require more advanced regex syntax rewriting rather than just running regex replacements on regexes.

Specifically, this line needs to be fixed to do a proper replacement strategy that doesn't replace \n with \z when the \n is in a character class, and maybe replaces the character class with (?:[...]|\z) where ... is everything that was in the character class except the \n. This probably would also need a different rewrite for inverted character classes.

cc @robinst

Enable multi-threaded use

Background: I'm trying to write a service that receives source code via HTTP, parses it using syntect and then returns some information about it. I'm using Iron for it, but this issue would also occur with other uses. In Iron, the Handler trait which handles requests is required to be Send and Sync, meaning it can be reused between threads.

So, the simplest implementation is to just call SyntaxSet::load_defaults_nonewlines() on every request, then figure out which SyntaxDefinition to use, and then parse the text. Unfortunately, this means that the syntax definitions have to be loaded for each request, which is quite a bit of work that could be avoided.

You can see where this is going. I'd like to have a way to only load SyntaxSet once at startup and then share it between all the request handlers. Or if that's not possible, at least share the SyntaxDefinition between threads (and have a mutex protecting SyntaxSet).

If we try to write that with the current syntect, it would look something like this:

#[test]
fn threading_with_shared_syntax_set() {
    let syntax_set = SyntaxSet::load_defaults_nonewlines();
    let syntax = syntax_set.find_syntax_by_name("rust").unwrap();

    thread::spawn(|| {
        let parse_state = ParseState::new(&syntax);
        let mut f = File::open("testdata/parser.rs").unwrap();
        let mut reader = BufReader::new(f);

        for line in reader.lines() {
            let line = line.unwrap();
            parse_state.parse_line(&line);
        }
    });
}

And it currently fails to compile like this:

[101] % cargo test threading
   Compiling syntect v1.0.0 (file:///Users/rstocker/Projects/rust/syntect)
error[E0277]: the trait bound `std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>: std::marker::Sync` is not satisfied
  --> tests/threading.rs:14:5
   |
14 |     thread::spawn(|| {
   |     ^^^^^^^^^^^^^
   |
   = note: `std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>` cannot be shared between threads safely
   = note: required because it appears within the type `std::option::Option<std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>>`
   = note: required because it appears within the type `syntect::parsing::SyntaxDefinition`
   = note: required because it appears within the type `&syntect::parsing::SyntaxDefinition`
   = note: required because of the requirements on the impl of `std::marker::Send` for `&&syntect::parsing::SyntaxDefinition`
   = note: required because it appears within the type `[closure@tests/threading.rs:14:19: 23:6 syntax:&&syntect::parsing::SyntaxDefinition]`
   = note: required by `std::thread::spawn`

I tried to work around this with some unsafe code, but it panics (as expected) when multiple threads use the same SyntaxDefinition.

As I understand the code currently, it is structured the way it is to avoid having to compile all the regexes eagerly. I wonder if there's a simple way to preserve that while still keeping that nice property. Alternatively, it would be cool if there was a way to precompile a SyntaxDefinition and get a new type that is immutable and thus Send and Sync. By the way, apart from this the library works beautifully :).

Fix the last few syntax tests

After #55 fixed most syntax test exposed bugs, there's a few left. Now the syntax tests for almost all languages pass perfectly. The following languages still fail:

  • ASP: not sure why, think it is some weird thing with with_prototype. Speculation in #51
  • LaTeX: mostly works, but one pattern matches the empty string, should be fixed in Sublime Packages. Notes in #51 by @keith-hall
  • Markdown: one test fails on <a name=\"demo\"></a>. Not sure why. Might be that sublimehq/Packages#877 doesn't actually work correctly. Not sure if @keith-hall ever ran the syntax tests on it. These tests no longer fail because the syntax in the repo was updated, but there's still probably an underlying difference from Sublime here.
  • PHP: a number of failures, not sure why. Might be the same thing as ASP. Fixed in #103

If you plan on attempting to diagnose or fix one of these bugs, create an issue for it and reference it here. I will do the same.

I don't foresee myself personally doing much work on this for the next little while, but I will review code and discuss and may get around to it eventually.

Confusing build failure

More confusing because I think I've encountered this problem before, and figured it out, but I can't now. ๐Ÿ˜•โ“

Example of this failure here:

https://travis-ci.org/google/xi-editor/jobs/286745290#L594

in my cargo.toml:

[dependencies.syntect]
version = "1.7"
default-features = false
features = ["assets","dump-load-rs"]

And it looks like IoError is not a member of bincode's error enum (it's just ErrorKind::Io): https://github.com/TyOverby/bincode/blob/master/src/internal.rs#L30

So it doesn't seem like this should ever compile?

I strongly believe I'm just missing something, but really no clue what, any help appreciated @trishume.

Replace calls to panic! with Result types

After doing a quick search, there are 8 occurrences of panic! in syntect. It'd be great to have these errors bubbled up using Result types with custom errors, instead. With the existing implementation, it's awkward to handle these, and because these methods don't signal the possibility of these errors, you won't realize there's an issue until you hit a runtime panic and have to work backwards to find the source.

Refactor to use an arena

This would be a large project, and may never happen, but the architecture would work much better with an arena of Contexts instead of using Rc<RefCell<>> everywhere. Not only would the code be cleaner, but the lifetimes of SyntaxDefinition and SyntaxSet would be more correct, avoiding the footgun of dropping a SyntaxSet and keeping a cloned SyntaxDefinition that no longer has references to nested languages.

This would look something like using a Vec<Context> and indices everywhere.

It may also be easier to parallelize and make thread-safe, but that still requires extra work because of lazy regex compilation. See extensive discussion in #20.

Use in threaded context seems to require unsafe wrapper struct

Documentation states that the SyntaxSet and ThemeSet should be loaded once at program startup (and indeed reloading them whenever highlighting is needed hurts performance). However, SyntaxSet does not appear to be threadsafe, possibly due to the internal use of RefCell in SyntaxDefinition.

As a result, the simplest way of getting it to work in Iron that I have found requires the following (unsafe) dance:

struct HighlighterSyntaxSet {
    ss: SyntaxSet,
}
unsafe impl Sync for HighlighterSyntaxSet {}

lazy_static! {
    static ref HL_SYNTAX_SET: HighlighterSyntaxSet = {
        let ss = SyntaxSet::load_defaults_newlines();
        HighlighterSyntaxSet {ss: ss}
    };
}

Using it directly without the unsafe wrapper results in the following error:

the trait `std::marker::Sync` is not implemented for `std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>`
    = note: `std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>` cannot be shared between threads safely
    = note: required because it appears within the type `std::option::Option<std::rc::Rc<std::cell::RefCell<syntect::parsing::syntax_definition::Context>>>`
    = note: required because it appears within the type `syntect::parsing::SyntaxDefinition`
    = note: required because of the requirements on the impl of `std::marker::Sync` for `std::ptr::Unique<syntect::parsing::SyntaxDefinition>`
    = note: required because it appears within the type `alloc::raw_vec::RawVec<syntect::parsing::SyntaxDefinition>`
    = note: required because it appears within the type `std::vec::Vec<syntect::parsing::SyntaxDefinition>`
    = note: required because it appears within the type `syntect::parsing::SyntaxSet`

The use of lazy_static here is simply to avoid the more complex code necessary for using the persistent crate, or Arcs directly. I don't believe it affects the issue at hand.

All that said, it is of course entirely possible I'm using this incorrectly -- I'm somewhat new to Rust.

Support advanced scope selectors

  • multiple exclusions
  • empty scope selectors always match
  • pipes are aliases for commas
  • parenthesized sub-matches
  • ampersand operator (and operator precedence)

Currently, syntect doesn't support grouping parens or & operators in scope selectors, which means it doesn't color scopes correctly when the .tmTheme file being used contains these more advanced constructs.

See the update under "One last twist" at http://blog.macromates.com/2005/introduction-to-scopes/ for a brief example

it's also possible to AND, OR, and subtract scope selectors, e.g.: (a | b) & c - d would select the scope which is not matched by d, and matched by both c, and a or b.

I've never really found any good documentation on scope selectors, so I tried to write a bit more about them on SO, which I'll link to here in case it's useful: http://stackoverflow.com/a/37407588/4473405

EDIT: I also found http://textmate.1073791.n5.nabble.com/formal-definition-of-scope-selector-syntax-td12109.html just now, which seems to indicate that | and , don't have equal precedence.

As a simple example, if we imagine the following Python code:

def test:
    global abc

then the selector (storage | entity.name) & meta.function should match def and test.

Please would you consider adding support for this to your awesome syntect library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.