73 Commits
0.1 ... master

Author SHA1 Message Date
Benjamin Sago
a1f5dad700 Readme updates
- Link to the new Wiki pages
- Rewrite compilation notes
- Offer to download the zip instead of going through the whole git process
2015-12-08 19:34:24 +00:00
Ben S
43eee05c44 Add very basic rustfmt Text Filter 2015-12-08 07:29:33 +00:00
Ben S
86c005e015 Add some Terminal+Cargo AppleScripts 2015-12-08 07:29:07 +00:00
Ben S
2defa5f908 Move Generate Implementation script into a folder 2015-12-08 07:28:44 +00:00
Ben S
75ef4092ec Add doc-splitter to the helper toolbox
This helper tool uses BBEdit's Preview Windows to preview Markdown syntax in your rustdocs. It has the following components:

- A binary Preview Filter
- The source for the filter, written in Rust, as a binary in the toolbox
- The Preview CSS that uses the classes outputted by the filter
2015-12-08 07:11:29 +00:00
Ben S
9e44cd4eb8 Rename impl-generator-bin to impl-generator
This will start transitioning the impl generator to be a more generic helper tool, with the impl generator as one of its component.

Also, drop the "-bin" from the name, because what else is it going to be?
2015-12-07 23:52:14 +00:00
Ben S
cf99295fa1 Cargo.toml clippings 2015-12-07 22:14:51 +00:00
Ben S
8b4069c4a6 TOML improvements
- Now it properly handles strings and numbers (without underscores) and dates and comments
- Sections are now in the function dropdown thing in the navigation bar
- Whitespace!
2015-12-07 22:14:30 +00:00
Ben S
eb478ce254 Clean up the plist, and add search URL template
- Add whitespace to make it readable
- Add BBLMIsSourceKind and BBLMIsHeaderKind to the BBLMSuffixMap, which I don't think actually do anything but they're there now
- Add BBLMReferenceSearchURLTemplate to search the libstd docs
2015-12-07 16:26:37 +00:00
Ben S
3fe8f93cec Update the screenshots (about time!) 2015-11-23 19:02:37 +00:00
Ben S
8ee5fa4793 Add a bunch more Clippings 2015-11-23 18:24:46 +00:00
Ben S
dea280c188 Update the binary and Xcode stuffs 2015-11-23 18:23:05 +00:00
Ben S
85a4eb2830 Be a bit more pragmatic with language guessing 2015-11-23 13:32:57 +00:00
Ben S
487b87d13a Avoid highlighting tuple indexes as numbers 2015-11-23 13:30:03 +00:00
Ben S
012448ebe8 Fix bug in attribute value highlighting
Any newlines within strings are now properly catered for.

Fixes #3.
2015-11-23 12:56:37 +00:00
Ben S
2c27300233 Clippings for regexen 2015-10-01 00:48:08 +01:00
Ben S
7fe432c069 Cargo.lock is TOML, too 2015-09-23 21:07:35 +01:00
Ben S
4e6a94bcef Add Toml CLM! 2015-09-09 15:10:12 +01:00
Ben S
4ee8768ce3 Add macro_rules! clipping 2015-08-01 22:17:15 +01:00
Ben S
77b2980f41 'us' and 'is' -> 'usize' and 'isize' 2015-08-01 22:17:07 +01:00
Ben S
11aa41ff48 Fix all the std::fmt function signatures 2015-07-24 18:20:42 +01:00
Ben S
53cf427f4f Macro variables shouldn't use spaces like this 2015-07-22 21:23:19 +01:00
Benjamin Sago
0ec4a6ccd1 Add std::iter traits 2015-07-19 19:50:42 +01:00
Benjamin Sago
19aecb6e55 impl-generator documentation. 2015-07-19 18:58:36 +01:00
Benjamin Sago
f53dfbc9fc Fix regex and add tests
The previous regex failed against Test 5 (generic_generics).
2015-07-19 17:23:38 +01:00
Ben S
55bb739dbe Add impl-generator script! 2015-07-15 16:56:41 +01:00
Ben S
eb06c53efc Add a bunch of clippings! 2015-07-15 15:14:26 +01:00
Ben S
d8fd3d0bd1 Update installation instructions 2015-07-15 14:23:02 +01:00
Ben S
2e92e9cd82 Start including a compiled version in the repo
This makes it possible for users to upgrade with a simple `git pull`,
rather than having to re-download the latest release from GitHub each
time - after checking that there is one, first!

It also converts it from just a `.bblm` file to an entire `.bbprojectd`
file, allowing me to add things like Clippings and Text Filters in the
future. (Planned!)
2015-07-15 14:14:53 +01:00
Ben S
6bc2dac873 Another version bump! 2015-05-03 12:25:52 +01:00
Ben S
07b020f253 Detab the plist 2015-05-03 12:24:31 +01:00
Ben S
ec10c4bf7f Add loads more built-in types 2015-05-03 12:24:22 +01:00
Ben S
e28267063f Update README 2015-03-16 22:02:24 +00:00
Ben S
adbf51d973 Add code folding!
Also, fix weird-looking function definitions.
2015-03-16 21:49:15 +00:00
Ben S
439556cbe4 Check end of word after scanning functions
'enumerate' is not 'enum' with some bits after it!
2015-03-16 18:35:00 +00:00
Ben S
0fe7412e14 Parse definitions with lifetimes correctly
This is actually achieved by making the parsing *more lenient* instead of more strict. The view looks more cluttered as a result, but at least it's *correct*. Nothing I can do about the clutter, as far as I know - BBEdit only allows us to use substrings of the document in the menu, so I can't strip out the lifetimes.
2015-03-16 18:19:56 +00:00
Ben S
565243f64b Update screenshot 2015-02-21 13:44:55 +00:00
Ben S
46fe844c16 Version bump 2015-02-21 13:29:11 +00:00
Ben S
bfdc57e356 Fix infinite loop when writing code at end of file
This resulted in my BBEdit hanging.
2015-02-21 13:27:29 +00:00
Ben S
1154b0df63 Highlight module names in 'use...as' statements 2015-02-21 13:27:05 +00:00
Ben S
2c05ab8682 Download link bump 2015-02-15 14:06:55 +00:00
Ben S
822eb95303 But there's only one type of string 2015-02-15 13:48:41 +00:00
Ben S
da342c1b7d Simplify macro-highlighting code 2015-02-15 13:43:15 +00:00
Ben S
81197c7d45 Detect r##"raw strings"## 2015-02-15 13:23:32 +00:00
Ben S
e6c0074733 Smarten up attribute highlighting 2015-02-15 13:07:24 +00:00
Ben S
5452afbb9c Replace identifier colour with preprocessor colour 2015-02-15 13:07:10 +00:00
Ben S
2c06798f84 Allow 'us' and 'is' machine-dependent suffixes 2015-02-15 12:54:55 +00:00
Ben S
d2549503b5 Add smoke test thing to save me from testing 2015-02-15 12:49:34 +00:00
Ben S
3b9fc0817c Add all the other keywords I missed 2015-02-15 12:27:35 +00:00
Ben S
82931045a2 Highlight macro_rules! definitions + arguments 2015-02-15 02:44:29 +00:00
Ben S
51e8755030 where wasn't a keyword already? 2015-02-15 02:24:35 +00:00
Benjamin Sago
9932fb4761 Replace int/uint with isize/usize 2015-01-11 12:43:57 +01:00
Ben S
79a65307f0 Changes to the way numbers are highlighted
They were being highlighted after underscores in variable names, and underscores weren't being catered for in non-base-ten numeric literals. Now, fixed!
2014-12-24 14:11:32 +00:00
Ben S
c98ec54134 Skip over modules called 'test' 2014-12-05 21:47:52 +00:00
Ben S
98a15cf36a Skip over empty function/module definitions 2014-12-05 20:51:08 +00:00
Ben S
34bbe47973 Turns out numbers are valid identifier components 2014-12-05 20:08:26 +00:00
Ben S
69e12ea420 Subtly change the way 'use' lines are highlighted 2014-12-05 20:07:08 +00:00
Ben S
92862fc0a3 Merge pull request #1 from crdx/trailing-spaces
remove trailing spaces
2014-11-29 16:45:23 +00:00
Sean S
dbb13d4816 remove trailing spaces 2014-11-29 16:43:56 +00:00
Ben S
38deac77fe oops 2014-11-28 23:38:42 +00:00
Ben S
affebcf878 Bump release link 2014-11-28 23:38:30 +00:00
Ben S
55bbe945ae And add the screenshot to the readme! 2014-11-28 23:18:16 +00:00
Ben S
3b76b3429f Add a screenshot 2014-11-28 23:16:22 +00:00
Ben S
af4c34887f Highlight numbers in 'use' statements
Thanks, std::f64::consts...
2014-11-27 05:19:10 +00:00
Ben S
c8ebb59385 Sort out keywords 2014-11-26 00:09:04 +00:00
Ben S
6668052266 Highlight binary and octal literals 2014-11-25 20:02:24 +00:00
Ben S
91d69de57f Highlight hex literals 2014-11-25 19:44:29 +00:00
Ben S
01998a20bc Require whitespace after mod, fn, and use 2014-11-25 18:36:07 +00:00
Ben S
4743bab662 Highlight module names and numeric prefixes 2014-11-14 18:47:59 +00:00
Ben S
41fcd43e6d Syntax highlight file includes 2014-11-09 21:06:15 +00:00
Ben S
50498ece46 Merge branch 'master' of github.com:ogham/Rust.bblm 2014-11-09 20:20:06 +00:00
Ben S
b68e3e3b77 Allow decimal points in numbers 2014-11-09 20:19:55 +00:00
Ben S
2a73fb8f72 Link to the download 2014-11-07 15:45:37 +00:00
53 changed files with 2254 additions and 306 deletions

4
.gitignore vendored
View File

@@ -3,6 +3,10 @@ build/*
*.pbxuser
xcuserdata
*.mode1v3
xcshareddata
# cargo noise
target
# osx noise
.DS_Store

View File

@@ -0,0 +1,2 @@
[dependencies.#PLACEHOLDERSTART#...#PLACEHOLDEREND#]
version = "#PLACEHOLDERSTART#...#PLACEHOLDEREND#"

View File

@@ -0,0 +1,2 @@
[dependencies.#PLACEHOLDERSTART#...#PLACEHOLDEREND#]
git = "#PLACEHOLDERSTART#...#PLACEHOLDEREND#"

View File

@@ -0,0 +1,2 @@
[dependencies.#PLACEHOLDERSTART#...#PLACEHOLDEREND#]
path = "#PLACEHOLDERSTART#...#PLACEHOLDEREND#"

View File

@@ -0,0 +1,7 @@
[profile.bench]
opt-level = 3
debug = false
rpath = false
lto = false
debug-assertions = false
codegen-units = 1

View File

@@ -0,0 +1,7 @@
[profile.dev]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1

View File

@@ -0,0 +1,7 @@
[profile.doc]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1

View File

@@ -0,0 +1,7 @@
[profile.release]
opt-level = 3
debug = false
rpath = false
lto = false
debug-assertions = false
codegen-units = 1

View File

@@ -0,0 +1,7 @@
[profile.test]
opt-level = 0
debug = true
rpath = false
lto = false
debug-assertions = true
codegen-units = 1

View File

@@ -0,0 +1,3 @@
#INDENT#static ref #PLACEHOLDERSTART#...#PLACEHOLDEREND#: Regex = Regex::new(r##"(?x)
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
"##).unwrap();

View File

@@ -0,0 +1,3 @@
#INDENT#static ref #PLACEHOLDERSTART#...#PLACEHOLDEREND#: Regex = Regex::new(r##"(?x) ^
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
$ "##).unwrap();

View File

@@ -0,0 +1 @@
#[derive(#placeholderstart#...#placeholderend#)]

View File

@@ -0,0 +1,3 @@
#indent#fn main() {
#placeholderstart#...#placeholderend#
}

View File

@@ -0,0 +1 @@
static #PLACEHOLDERSTART#NAME#PLACEHOLDEREND#: &'static str = "#PLACEHOLDERSTART#...#PLACEHOLDEREND#";

View File

@@ -0,0 +1,3 @@
#INDENT#static #PLACEHOLDERSTART#NAME#PLACEHOLDEREND#: &'static [&'static str] = &[
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
];

View File

@@ -0,0 +1,4 @@
\#[test]
#indent#fn #placeholderstart#test#placeholderend#() {
#placeholderstart#...#placeholderend#
}

View File

@@ -0,0 +1,8 @@
#indent#macro_rules! #placeholderstart#name#placeholderend# {
($name:ident: $input:expr => $result:expr) => {
\#[test]
fn $name() {
assert_eq!($input, $result);
}
};
}

View File

@@ -0,0 +1,9 @@
#indent#\#[cfg(test)]
mod test {
use super::*;
\#[test]
fn #placeholderstart#test#placeholderend#() {
#placeholderstart#...#placeholderend#
}
}

View File

@@ -0,0 +1,3 @@
//! ```
//! #placeholderstart##placeholderend#
//! ```

View File

@@ -0,0 +1,5 @@
#INDENT#/// ### Examples
///
/// ```
/// #PLACEHOLDERSTART#...#PLACEHOLDEREND#
/// ```

View File

@@ -0,0 +1,3 @@
#INDENT#/// ### Panics
///
/// #PLACEHOLDERSTART#...#PLACEHOLDEREND#

View File

@@ -0,0 +1,3 @@
#indent#if let Some(#placeholderstart#variable#placeholderend#) = #placeholderstart#...#placeholderend# {
#placeholderstart#...#placeholderend#
}

View File

@@ -0,0 +1,4 @@
#indent#match #placeholderstart#...#placeholderend# {
Some(#placeholderstart#...#placeholderend#) => #placeholderstart#...#placeholderend#,
None => #placeholderstart#...#placeholderend#,
}

View File

@@ -0,0 +1,4 @@
#indent#match #placeholderstart#...#placeholderend# {
Ok(#placeholderstart#...#placeholderend#) => #placeholderstart#...#placeholderend#,
Err(#placeholderstart#...#placeholderend#) => #placeholderstart#...#placeholderend#,
}

View File

@@ -0,0 +1,7 @@
#INDENT#let mut f = try!(File::open("log.txt"));
let mut reader = BufReader::new(f);
for line in reader.lines() {
let line = line.unwrap();
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
}

View File

@@ -0,0 +1,6 @@
#INDENT#let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line.unwrap();
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
}

View File

@@ -0,0 +1,5 @@
#INDENT#macro_rules! #PLACEHOLDERSTART#...#PLACEHOLDEREND# {
(#PLACEHOLDERSTART#...#PLACEHOLDEREND#) => {
#PLACEHOLDERSTART#...#PLACEHOLDEREND#
}
}

View File

@@ -0,0 +1 @@
println!("#PLACEHOLDERSTART#...#PLACEHOLDEREND#");

View File

@@ -0,0 +1 @@
println!("{:?}", #placeholderstart#...#placeholderend#);

View File

@@ -0,0 +1 @@
unimplemented!()

View File

@@ -0,0 +1 @@
unreachable!()

View File

@@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>15B42</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>Rust</string>
<key>CFBundleIdentifier</key>
<string>me.bsago.bblm.rust</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>BBLM</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>8.0</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>7B91b</string>
<key>DTPlatformVersion</key>
<string>GM</string>
<key>DTSDKBuild</key>
<string>15A278</string>
<key>DTSDKName</key>
<string>macosx10.11</string>
<key>DTXcode</key>
<string>0710</string>
<key>DTXcodeBuild</key>
<string>7B91b</string>
<key>com.barebones.bblminfo</key>
<array>
<dict>
<key>BBLMCanGuessLanguage</key>
<true/>
<key>BBLMColorsSyntax</key>
<true/>
<key>BBLMCommentLineDefault</key>
<string>// </string>
<key>BBLMCommentPrefixDefault</key>
<string>/* </string>
<key>BBLMCommentSuffixDefault</key>
<string> */</string>
<key>BBLMDroppedFilePathStyle</key>
<string>POSIX</string>
<key>BBLMEntryPointName</key>
<string>rustMain</string>
<key>BBLMFunctionScannerDoesFoldsToo</key>
<true/>
<key>BBLMIsCaseSensitive</key>
<true/>
<key>BBLMKeywords</key>
<array>
<dict>
<key>Keywords</key>
<array>
<string>abstract</string>
<string>alignof</string>
<string>as</string>
<string>become</string>
<string>box</string>
<string>break</string>
<string>const</string>
<string>continue</string>
<string>crate</string>
<string>do</string>
<string>else</string>
<string>enum</string>
<string>extern</string>
<string>false</string>
<string>final</string>
<string>fn</string>
<string>for</string>
<string>if</string>
<string>impl</string>
<string>in</string>
<string>let</string>
<string>loop</string>
<string>macro</string>
<string>macro_rules</string>
<string>match</string>
<string>mod</string>
<string>move</string>
<string>mut</string>
<string>offsetof</string>
<string>override</string>
<string>priv</string>
<string>proc</string>
<string>pub</string>
<string>pure</string>
<string>ref</string>
<string>return</string>
<string>self</string>
<string>sizeof</string>
<string>static</string>
<string>struct</string>
<string>super</string>
<string>trait</string>
<string>true</string>
<string>type</string>
<string>typeof</string>
<string>unsafe</string>
<string>unsized</string>
<string>use</string>
<string>virtual</string>
<string>where</string>
<string>while</string>
<string>yield</string>
</array>
<key>RunKind</key>
<string>com.barebones.bblm.keyword</string>
</dict>
<dict>
<key>Keywords</key>
<array>
<string>blkcnt_t</string>
<string>blksize_t</string>
<string>bool</string>
<string>c_char</string>
<string>c_double</string>
<string>c_float</string>
<string>c_int</string>
<string>c_long</string>
<string>c_schar</string>
<string>c_short</string>
<string>c_uchar</string>
<string>c_uint</string>
<string>c_ulong</string>
<string>c_ushort</string>
<string>char</string>
<string>clock_t</string>
<string>dev_t</string>
<string>f32</string>
<string>f64</string>
<string>float</string>
<string>gid_t</string>
<string>i16</string>
<string>i32</string>
<string>i64</string>
<string>i8</string>
<string>ino_t</string>
<string>isize</string>
<string>mode_t</string>
<string>nlink_t</string>
<string>off_t</string>
<string>pid_t</string>
<string>ptrdiff_t</string>
<string>size_t</string>
<string>str</string>
<string>suseconds_t</string>
<string>time_t</string>
<string>u16</string>
<string>u32</string>
<string>u64</string>
<string>u8</string>
<string>uid_t</string>
<string>usize</string>
<string>wchar_t</string>
</array>
<key>RunKind</key>
<string>com.barebones.bblm.predefined-symbol</string>
</dict>
</array>
<key>BBLMLanguageCode</key>
<string>Rust</string>
<key>BBLMLanguageDisplayName</key>
<string>Rust</string>
<key>BBLMNonSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.code</string>
<string>com.barebones.bblm.double-string</string>
</array>
<key>BBLMRunColors</key>
<dict>
<key>me.bsago.bblm.rust.function</key>
<string>rgb(219, 135, 2)</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>rgb(61, 153, 112)</string>
<key>me.bsago.bblm.rust.lifetime</key>
<string>rgb(133, 20, 75)</string>
<key>me.bsago.bblm.rust.module</key>
<string>rgb(135, 2, 219)</string>
</dict>
<key>BBLMRunNames</key>
<dict>
<key>me.bsago.bblm.rust.function</key>
<string>fn functionname</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>Identifier</string>
<key>me.bsago.bblm.rust.lifetime</key>
<string>'lifetime</string>
<key>me.bsago.bblm.rust.module</key>
<string>mod modulename</string>
</dict>
<key>BBLMScansFunctions</key>
<true/>
<key>BBLMSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.line-comment</string>
<string>com.barebones.bblm.block-comment</string>
</array>
<key>BBLMReferenceSearchURLTemplate</key>
<string>https://doc.rust-lang.org/std/?search=__SYMBOLNAME__</string>
<key>BBLMSuffixMap</key>
<array>
<dict>
<key>BBLMLanguageSuffix</key>
<string>.rs</string>
<key>BBLMIsSourceKind</key>
<true/>
<key>BBLMIsHeaderKind</key>
<false/>
</dict>
</array>
<key>BBLMUseHTMLFileSearchRules</key>
<false/>
</dict>
</array>
</dict>
</plist>

Binary file not shown.

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BBEditDocumentType</key>
<string>CodelessLanguageModule</string>
<key>BBLMColorsSyntax</key>
<true/>
<key>BBLMIsCaseSensitive</key>
<true/>
<key>BBLMKeywords</key>
<array>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.predefined-symbol</string>
<key>Keywords</key>
<array>
<string>true</string>
<string>false</string>
</array>
</dict>
</array>
<key>BBLMKeywordPatterns</key>
<array>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.sgml-tag</string>
<key>Pattern</key>
<string>^\[.*\]$</string>
</dict>
</array>
<key>BBLMSuffixMap</key>
<array>
<dict>
<key>BBLMLanguageSuffix</key>
<string>.toml</string>
</dict>
<dict>
<key>BBLMLanguageSuffix</key>
<string>.lock</string>
</dict>
</array>
<key>BBLMLanguageCode</key>
<string>TOML</string>
<key>BBLMLanguageDisplayName</key>
<string>TOML</string>
<key>BBLMScansFunctions</key>
<true/>
<key>Language Features</key>
<dict>
<key>Close Strings 1</key>
<string>'</string>
<key>Close Strings 2</key>
<string>"</string>
<key>End-of-line Ends Strings 1</key>
<false/>
<key>End-of-line Ends Strings 2</key>
<false/>
<key>Escape Char in Strings 1</key>
<string>\</string>
<key>Escape Char in Strings 2</key>
<string>\</string>
<key>Identifier and Keyword Characters</key>
<string>0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_.-abcdefghijklmnopqrstuvwxyz[]</string>
<key>Open Line Comments</key>
<string>#</string>
<key>Open Parameter Lists</key>
<string>{</string>
<key>Open Statement Blocks</key>
<string>{</string>
<key>Open Strings 1</key>
<string>'</string>
<key>Open Strings 2</key>
<string>"</string>
<key>Comment Pattern</key>
<string><![CDATA[(?x:
(?> [\#] .* $ )
)]]></string>
<key>Skip Pattern</key>
<string><![CDATA[(?x:
(?>
(?P>comment) |
(?P>string)
)
)]]></string>
<key>String Pattern</key>
<string><![CDATA[(?x:
(?> """ (?s: \\. | [^"] )*? (?: """ ) ) |
(?> ''' (?s: . )*? (?: ''' ) ) |
(?> " (?s: \\. | [^"] )*? (?: " ) ) |
(?> ' (?s: [^'] )*? (?: ' ) ) |
(?>
\d{4} - \d{2} - \d{2}
(?: T
\d{2} : \d{2} : \d{2} (?: \. \d+ )?
(?: Z | ([+-]) \d{2} : \d{2} )?
)?
)
)]]></string>
<key>Function Pattern</key>
<string><![CDATA[(?x:
(?P<function>
\[
(?P<function_name>
(\[* [\w/._-]+ \]*)
)
\]
)
)]]></string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,72 @@
/*
* These styles are a poor imitation of the standard rustdoc styles. They should
* contain just enough to look more-or-less like rustdocs output, but large
* parts of the official stylesheet arent relevant, and Im not even sure if
* Im allowed to distribute its webfonts! So this will have to do.
*/
body {
padding: 0;
margin: 0;
font: 16px/1.4 Georgia; /* Georgia is like Source Serif Pro, right? */
}
.docs pre, .docs code, .docs span {
font-family: Monaco; /* Monaco is like Source Code Pro, right? */
font-size: 12px;
}
.docs {
padding: 20px 20px 10px 20px;
color: #333;
}
.docs.module {
background-color: #F7F3F7;
border-bottom: 1px solid #D8CAD8;
}
/*
* We want to keep the docs above a piece of code close to that code in the
* preview, as docs usually refer to the code below them.
*/
.code {
border-top: 1px solid #BDC3C7;
border-bottom: 1px solid #BDC3C7;
background-color: #ECF0F1;
font-size: 10px;
font-family: Monaco;
color: #666;
padding: 10px 20px;
margin: 0em;
}
p:last-child {
padding: 0;
margin: 0;
}
/*
* The headings have borders below them, just like rustdoc!
*/
h2 {
font-size: 1.4em;
}
h3 {
font-size: 1.3em;
}
h1, h2, h3 {
font-family: "Helvetica Neue"; /* Helvetica is like Fira Sans, right? */
border-bottom: 1px solid #ddd;
color: #000;
font-weight: 500;
margin: 20px 0 15px 0;
padding-bottom: 6px;
}

Binary file not shown.

BIN
Contents/Resources/impl-generator Executable file

Binary file not shown.

View File

@@ -0,0 +1,17 @@
tell application "BBEdit"
tell front text document
if modified = true then
save its document
end if
set the_file to its file
if the_file ­ missing value then
set the_path to POSIX path of ((the_file as text) & "::")
else
error "Document does not point to a file"
end if
end tell
end tell
tell application "Terminal"
do script "cd " & (quoted form of the_path) & "; cargo build"
end tell

View File

@@ -0,0 +1,17 @@
tell application "BBEdit"
tell front text document
if modified = true then
save its document
end if
set the_file to its file
if the_file ­ missing value then
set the_path to POSIX path of ((the_file as text) & "::")
else
error "Document does not point to a file"
end if
end tell
end tell
tell application "Terminal"
do script "cd " & (quoted form of the_path) & "; cargo doc --open"
end tell

View File

@@ -0,0 +1,17 @@
tell application "BBEdit"
tell front text document
if modified = true then
save its document
end if
set the_file to its file
if the_file ­ missing value then
set the_path to POSIX path of ((the_file as text) & "::")
else
error "Document does not point to a file"
end if
end tell
end tell
tell application "Terminal"
do script "cd " & (quoted form of the_path) & "; cargo test"
end tell

Binary file not shown.

2
Contents/Text Filters/rustfmt Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
rustfmt --write-mode=display

7
Makefile Normal file
View File

@@ -0,0 +1,7 @@
all:
xcodebuild -configuration Release
cp -r build/Release/Rust.bblm Contents/"Language Modules"
cd helper-tool; cargo build --release; cp target/release/impl-generator ../Contents/Resources/impl-generator; cp target/release/doc-splitter ../Contents/"Preview Filters"/"Rust Markdown"
clean:
rm -r build; cd helper-tool; cargo clean

View File

@@ -1,27 +1,47 @@
BBEdit language module for Rust
===============================
BBEdit Package for Rust
=======================
This is a BBEdit 11 Language Module for [Rust](http://www.rust-lang.org). It provides the following features:
!["Screenshots of the Rust BBEdit language module"](screenshots.png)
This is a BBEdit 11 Package for [Rust](http://www.rust-lang.org). It provides the following features:
- Complete syntax highlighting
- Special support for lifetimes, attributes, and identifiers
- Customisable colours using the [BBEdit 11 colour thing](http://barebones.com/products/bbedit/bbedit11.html)
- Customisable colours using the [BBEdit 11 colour editor](http://barebones.com/products/bbedit/bbedit11.html)
- Language features
- Go to start of/end of/previous/next function
- Go to named symbol
- Go to symbol
- [Find in Reference support](https://github.com/ogham/Rust-BBEdit/wiki/Find-in-Reference)
- Indexed function menu
- Code folding
- Integration and helpers
- [Rustdoc preview](https://github.com/ogham/Rust-BBEdit/wiki/Rustdoc-Preview) to check your docs Markdown syntax
- Clippings for common code patterns
- [Implementation generator](https://github.com/ogham/Rust-BBEdit/wiki/impl-Generator) for standard library traits
- [TOML support](https://github.com/ogham/Rust-BBEdit/wiki/TOML) for Cargo and suchlike
- [rustfmt support](https://github.com/ogham/Rust-BBEdit/wiki/rustfmt)
- [Cargo build scripts](https://github.com/ogham/Rust-BBEdit/wiki/Cargo)
See the Wiki pages for more information and screenshots.
By default, it highlights anything beginning with a capital letter in a certain colour. To turn this off, just change the Identifier colour to be the same as the default text colour in Preferences.
### Installation
The simplest way is to just download the package and put it in this folder:
To install this package, simply clone the repo into BBEdits Packages folder:
~/Application Support/BBEdit/Language Modules
```bash
$ git clone https://github.com/ogham/Rust-BBEdit.git ~/Library/Application\ Support/BBEdit/Packages/Rust.bbpackage
```
Then restart your BBEdit and it should be picked up. Its necessary for the filename to end in `.bbpackage`.
Alternatively, just [download this .zip of the source](https://github.com/ogham/Rust-BBEdit/archive/master.zip) and extract it to that directory.
Then restart your BBEdit and it should be picked up.
### Compilation
To compile your own version, you'll need Xcode. The default schema outputs a `.bblm`. You'll also need the BBEdit SDK. The project assumes it's mounted under `/Volumes/BBEdit SDK`.
To compile your own version, youll need Xcode, Rust, and Cargo. The default schema outputs a `.bblm`, and comes with a Run build step so you can debug the module while BBEdit is running. Youll also need the [BBEdit SDK](http://www.barebones.com/support/develop/). The project assumes its mounted under `/Volumes/BBEdit SDK`.
Once youve got all that set up, simply run `make` and itll compile the language module and Rust helper tools for you.
Note that compiled versions of these tools already exist in the repository—you wont be generating anything that doesnt already exist!

View File

@@ -49,7 +49,6 @@
name = Rust;
productInstallPath = "$(HOME)/Library/Bundles";
productName = "Hello World";
productReference = B57F6C2519FD60C000FDB959 /* Rust.bblm */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
@@ -97,10 +96,11 @@
INFOPLIST_FILE = Info.plist;
INSTALL_MODE_FLAG = "ug+w,o-w,a+rX";
MACOSX_DEPLOYMENT_TARGET = 10.10;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
PRODUCT_NAME = Rust;
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
SDKROOT = macosx10.10;
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "/Volumes/BBEdit\\ SDK/Interfaces/Language\\ Modules/";
WRAPPER_EXTENSION = bblm;
};
@@ -114,10 +114,11 @@
INFOPLIST_FILE = Info.plist;
INSTALL_MODE_FLAG = "ug+w,o-w,a+rX";
MACOSX_DEPLOYMENT_TARGET = 10.10;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
PRODUCT_NAME = Rust;
SCAN_ALL_SOURCE_FILES_FOR_INCLUDES = YES;
SDKROOT = macosx10.10;
SDKROOT = macosx;
USER_HEADER_SEARCH_PATHS = "/Volumes/BBEdit\\ SDK/Interfaces/Language\\ Modules/";
WRAPPER_EXTENSION = bblm;
};

87
helper-tool/Cargo.lock generated Normal file
View File

@@ -0,0 +1,87 @@
[root]
name = "rust-bbedit-helpers"
version = "0.1.0"
dependencies = [
"hoedown 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "advapi32-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"advapi32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hoedown"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"

18
helper-tool/Cargo.toml Normal file
View File

@@ -0,0 +1,18 @@
[package]
name = "rust-bbedit-helpers"
version = "0.1.0"
authors = ["Ben S <ogham@bsago.me>"]
[[bin]]
name = "doc-splitter"
path = "src/doc-splitter.rs"
test = true
[[bin]]
name = "impl-generator"
path = "src/impl-generator.rs"
test = true
[dependencies]
regex = "0.1"
hoedown = "3.0"

View File

@@ -0,0 +1,87 @@
extern crate hoedown;
use hoedown::{Markdown, Html, Render, Extension};
use hoedown::renderer::html::{self, HARD_WRAP};
use std::io::{self, BufRead};
fn main() {
let extensions: Extension =
hoedown::AUTOLINK |
hoedown::FENCED_CODE |
hoedown::FOOTNOTES |
hoedown::NO_INTRA_EMPHASIS |
hoedown::STRIKETHROUGH |
hoedown::SUPERSCRIPT |
hoedown::TABLES;
let stdin = io::stdin();
let mut buffer = String::new();
let mut was_doc = false;
let mut was_module_comment = false;
let mut flags = html::Flags::all();
flags.remove(HARD_WRAP);
let print_markdown = |buf: &str, mod_comment: bool| {
let doc = Markdown::new(buf.trim_right()).extensions(extensions);
let mut html = Html::new(flags, 0);
let classes = match mod_comment {
true => "docs module",
false => "docs",
};
println!("<div class=\"{}\">{}</div>", classes, html.render(&doc).to_str().unwrap());
};
let print_code = |buf: &str| {
println!("<pre class=\"code\">{}</pre>", buf.trim_right().replace("<", "&lt;").replace(">", "&gt;"));
};
for line in stdin.lock().lines() {
let line = line.unwrap();
let mut slice = &line[..];
let mut is_doc = false;
if let Some(first_char) = line.find(|c: char| !c.is_whitespace()) {
let line = &line[first_char ..];
if line.starts_with("//! ") || line.starts_with("/// ") {
slice = &slice[4 + first_char ..];
is_doc = true;
}
else if line.starts_with("//!") || line.starts_with("///") {
slice = &slice[3 + first_char ..];
is_doc = true;
}
}
if !buffer.trim().is_empty() {
if is_doc && !was_doc {
print_code(&*buffer);
buffer.clear();
}
else if !is_doc && was_doc {
print_markdown(&*buffer, was_module_comment);
buffer.clear();
}
}
buffer.push_str(slice);
buffer.push('\n');
was_doc = is_doc;
was_module_comment = line.starts_with("//!");
}
if !was_doc {
print_code(&*buffer);
buffer.clear();
}
else {
print_markdown(&*buffer, false);
buffer.clear();
}
}

View File

@@ -0,0 +1,515 @@
extern crate regex;
use regex::Regex;
use std::fmt;
use std::io::{self, BufRead};
use std::process;
use std::string::ToString;
/// The string pattern that every incoming string should match against.
pub static REGEX: &'static str = r##"(?x)
# example:
^ impl # impl
(?: < .+ >)? \s+ # <'a>
([ A-Z a-z 0-9 _ : ]+) # ops::Add
(< .+ >)? \s+ # <MyValue<'a>>
for \s+ # for
([ A-Z a-z 0-9 _ : ]+) # MyOtherValue
(< .+ >)? \s* # <'a>
\{? $
"##;
fn main() {
let regex = Regex::new(REGEX).unwrap();
let stdin = io::stdin();
let line = stdin.lock().lines().next().unwrap_or_else(||fail("Failed to read line")).unwrap();
let caps = regex.captures(&*line).unwrap_or_else(||fail("Invalid impl line"));
let trait_name = caps.at(1).unwrap_or("");
let trait_args = caps.at(2).unwrap_or("");
let type_name = caps.at(3).unwrap_or("");
let type_args = caps.at(4).unwrap_or("");
if let Some(components) = get_components(trait_name) {
// Print the first line...
println!("impl{} {}{} for {}{} {{", type_args, trait_name,trait_args, type_name,type_args);
// Then print all the components, with a blank line between each one:
let mut printed_anything = false;
for component in components.iter() {
if printed_anything == false {
printed_anything = true;
}
else {
println!("");
}
let text = component.to_string();
// There are three patterns that get replaced before a template is
// printed out:
//
// - SELF, which gets replaced with the name of the type the trait
// is being implemented for;
// - PARAM, which gets replaced with the *parameter* of the trait;
// - RHS, which gets replaced with the parameter if one exists,
// and the name of the type (like SELF) otherwise.
if text.contains("PARAM") && trait_args.is_empty() {
fail(&*format!("Trait {} needs a generic argument", trait_name));
}
// Remove the < and > from the trait's parameter if one exists.
let rhs = if trait_args.is_empty() { type_name } else { &trait_args[1 .. trait_args.len() - 1] };
let text = text.replace("SELF", &*format!("{}{}", type_name, type_args))
.replace("PARAM", rhs)
.replace("RHS", rhs);
println!("{}", text);
}
// And finally the last line.
println!("}}");
}
else {
fail(&*format!("Unknown trait name: {}", trait_name));
}
}
/// A **component** forms part of the resulting template.
#[derive(Copy, Clone)]
enum Component<'a> {
/// An associated type that has to be specified for this implementation.
AssocType(&'a str),
/// A function definition that must be specified for this trait.
Function {
name: &'a str,
input: &'a str,
output: Option<&'a str>,
params: Option<&'a str>,
},
}
impl<'a> fmt::Display for Component<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
Component::AssocType(name) => {
write!(f, " type {} = <#...#>;", name)
},
Component::Function { name, input, output, params } => {
try!(write!(f, " fn {}", name));
if let Some(params) = params {
try!(write!(f, "<{}>", params));
}
try!(write!(f, "({})", input));
if let Some(output) = output {
try!(write!(f, " -> {}", output));
}
write!(f, " {{\n <#...#>\n }}")
},
}
}
}
/// Return a vector of components for a trait if the trait exists; returns
/// `None` otherwise.
fn get_components(trait_name: &str) -> Option<Vec<Component<'static>>> {
use self::Component::*;
let bits = match trait_name {
// -- std::borrow --
"Borrow" => vec![
Function {
name: "borrow",
input: "&self",
output: Some("&PARAM"),
params: None,
}
],
"BorrowMut" => vec![
Function {
name: "borrow_mut",
input: "&mut self",
output: Some("&mut PARAM"),
params: None,
}
],
"IntoCow" => vec![
Function {
name: "into_cow",
input: "self",
output: Some("Cow<PARAM>"),
params: None,
}
],
"ToOwned" => vec![
AssocType("Owned"),
Function {
name: "to_owned",
input: "&self",
output: Some("Self::Owned"),
params: None,
}
],
// -- std::clone --
"Clone" => vec![
Function {
name: "clone",
input: "&self",
output: Some("SELF"),
params: None,
}
],
// -- std::cmp --
"PartialEq" => vec![
Function {
name: "eq",
input: "&self, other: &RHS",
output: Some("bool"),
params: None,
}
],
"PartialOrd" => vec![
Function {
name: "partial_cmp",
input: "&self, other: &RHS",
output: Some("Option<Ordering>"),
params: None,
}
],
// -- std::convert --
"AsMut" => vec![
Function {
name: "as_mut",
input: "&mut self",
output: Some("&mut PARAM"),
params: None,
}
],
"AsRef" => vec![
Function {
name: "as_ref",
input: "&self",
output: Some("&PARAM"),
params: None,
}
],
"From" => vec![
Function {
name: "from",
input: "PARAM",
output: Some("SELF"),
params: None,
}
],
"Into" => vec![
Function {
name: "into",
input: "self",
output: Some("PARAM"),
params: None,
}
],
// -- std::default --
"Default" => vec![
Function {
name: "default",
input: "",
output: Some("SELF"),
params: None,
}
],
// -- std::error --
"Error" => vec![
Function {
name: "description",
input: "&self",
output: Some("&str"),
params: None,
},
Function {
name: "cause",
input: "&self",
output: Some("Option<&Error>"),
params: None,
}
],
// -- std::fmt --
"Binary" | "Debug" | "Display" | "LowerExp" | "LowerHex" | "Octal" |
"Pointer" | "UpperExp" | "UpperHex"
=> format(),
// -- std::hash --
"Hash" => vec![
Function {
name: "hash",
input: "&self, state: &mut H",
output: None,
params: Some("H: Hasher"),
}
],
// -- std::iter --
"Iterator" => vec![
AssocType("Item"),
Function {
name: "next",
input: "&mut self",
output: Some("Option<Self::Item>"),
params: None,
},
],
"ExactLenIterator" => vec![
Function {
name: "len",
input: "&self",
output: Some("usize"),
params: None,
},
],
"FromIterator" => vec![
Function {
name: "from_iter",
input: "iterator: T",
output: Some("SELF"),
params: Some("T: IntoIterator<Item=PARAM>"),
},
],
"DoubleEndedIterator" => vec![
Function {
name: "next_back",
input: "&mut self",
output: Some("Option<Self::Item>"),
params: None,
},
],
"IntoIterator" => vec![
AssocType("Item"),
AssocType("IntoIter"),
Function {
name: "into_iter",
input: "self",
output: Some("Self::IntoIter"),
params: None,
}
],
"Extend" => vec![
Function {
name: "extend",
input: "&mut self, iterable: T",
output: None,
params: Some("T: IntoIterator<Item=PARAM>"),
}
],
// -- std::ops --
"Add" => maths("add"),
"BitAnd" => maths("bitand"),
"BitOr" => maths("bitor"),
"BitXor" => maths("bitxor"),
"Div" => maths("div"),
"Mul" => maths("mul"),
"Rem" => maths("rem"),
"Shl" => maths("shl"),
"Shr" => maths("shr"),
"Sub" => maths("sub"),
"Not" => vec![
AssocType("Output"),
Function {
name: "not",
input: "self",
output: Some("Self::Output"),
params: None,
},
],
"Neg" => vec![
AssocType("Output"),
Function {
name: "neg",
input: "self",
output: Some("Self::Output"),
params: None,
},
],
"Deref" => vec![
AssocType("Target"),
Function {
name: "deref",
input: "&'a self",
output: Some("&'a Self::Target"),
params: Some("'a"),
},
],
"DerefMut" => vec![
AssocType("Target"),
Function {
name: "deref_mut",
input: "&'a mut self",
output: Some("&'a mut Self::Target"),
params: Some("'a"),
},
],
"Index" => vec![
AssocType("Output"),
Function {
name: "index",
input: "&'a self, index: PARAM",
output: Some("&'a Self::Output"),
params: Some("'a"),
},
],
"IndexMut" => vec![
AssocType("Output"),
Function {
name: "index",
input: "&'a mut self, index: PARAM",
output: Some("&'a mut Self::Output"),
params: Some("'a"),
},
],
// -- std::str --
"FromStr" => vec![
AssocType("Err"),
Function {
name: "from_str",
input: "s: &str",
output: Some("Result<SELF, Self::Err>"),
params: None,
},
],
_ => return None,
};
Some(bits)
}
/// Return the components for a mathematical operator, all of which follow the
/// same pattern.
fn maths(name: &'static str) -> Vec<Component<'static>> {
vec![
Component::AssocType("Output"),
Component::Function {
name: name,
input: "self, rhs: RHS",
output: Some("Self::Output"),
params: None,
},
]
}
/// Return the components for a formatting trait, which all look exactly the
/// same.
fn format() -> Vec<Component<'static>> {
vec![
Component::Function {
name: "fmt",
input: "&self, f: &mut fmt::Formatter",
output: Some("Result<(), fmt::Error>"),
params: None,
}
]
}
/// Print the given message, and exit the program, returning failure.
fn fail(message: &str) -> ! {
println!("{}", message);
process::exit(1);
}
#[cfg(test)]
mod test {
use regex::Regex;
use super::*;
#[test]
fn base() {
let regex = Regex::new(REGEX).unwrap();
assert!(regex.is_match("impl Foo for Bar"));
}
#[test]
fn open_bracket() {
let regex = Regex::new(REGEX).unwrap();
assert!(regex.is_match("impl Foo for Bar {"));
}
#[test]
fn generics() {
let regex = Regex::new(REGEX).unwrap();
assert!(regex.is_match("impl<'a> Foo<'a> for Bar<'a>"));
}
#[test]
fn more_generics() {
let regex = Regex::new(REGEX).unwrap();
assert!(regex.is_match("impl<'a, T> Foo<'a, T> for Bar<'a, T>"));
}
#[test]
fn generic_generics() {
let regex = Regex::new(REGEX).unwrap();
assert!(regex.is_match("impl<T<'a>> Foo<T<'a>> for Bar<T<'a>>"));
}
}

View File

@@ -2,176 +2,205 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>me.bsago.bblm.rust</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>BBLM</string>
<key>CFBundleVersion</key>
<string>8.0</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>com.barebones.bblminfo</key>
<array>
<dict>
<key>BBLMCanGuessLanguage</key>
<true/>
<key>BBLMColorsSyntax</key>
<true/>
<key>BBLMDroppedFilePathStyle</key>
<string>POSIX</string>
<key>BBLMCommentLineDefault</key>
<string>// </string>
<key>BBLMCommentPrefixDefault</key>
<string>/* </string>
<key>BBLMCommentSuffixDefault</key>
<string> */</string>
<key>BBLMIsCaseSensitive</key>
<true/>
<key>BBLMRunNames</key>
<dict>
<key>me.bsago.bblm.rust.lifetime</key>
<string>&apos;lifetime</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>Identifier</string>
<key>me.bsago.bblm.rust.attribute</key>
<string>#[attribute]</string>
<key>me.bsago.bblm.rust.function</key>
<string>fn function</string>
</dict>
<key>BBLMRunColors</key>
<dict>
<key>me.bsago.bblm.rust.lifetime</key>
<string>rgb(133, 20, 75)</string>
<key>me.bsago.bblm.rust.attribute</key>
<string>rgb(177, 13, 201)</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>rgb(61, 153, 112)</string>
<key>me.bsago.bblm.rust.function</key>
<string>rgb(219, 135, 2)</string>
</dict>
<key>BBLMKeywords</key>
<array>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.keyword</string>
<key>Keywords</key>
<array>
<string>as</string>
<string>box</string>
<string>break</string>
<string>continue</string>
<string>crate</string>
<string>else</string>
<string>enum</string>
<string>extern</string>
<string>false</string>
<string>fn</string>
<string>for</string>
<string>if</string>
<string>impl</string>
<string>in</string>
<string>let</string>
<string>loop</string>
<string>macro_rules!</string>
<string>match</string>
<string>mod</string>
<string>mut</string>
<string>priv</string>
<string>proc</string>
<string>pub</string>
<string>ref</string>
<string>return</string>
<string>self</string>
<string>static</string>
<string>struct</string>
<string>super</string>
<string>trait</string>
<string>true</string>
<string>type</string>
<string>unsafe</string>
<string>use</string>
<string>while</string>
</array>
</dict>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.predefined-symbol</string>
<key>Keywords</key>
<array>
<string>assert</string>
<string>bool</string>
<string>char</string>
<string>debug</string>
<string>env</string>
<string>error</string>
<string>externfn</string>
<string>f32</string>
<string>f64</string>
<string>fail</string>
<string>float</string>
<string>fmt</string>
<string>i16</string>
<string>i32</string>
<string>i64</string>
<string>i8</string>
<string>include</string>
<string>include_bin</string>
<string>include_str</string>
<string>info</string>
<string>int</string>
<string>proto</string>
<string>str</string>
<string>stringify</string>
<string>u16</string>
<string>u32</string>
<string>u64</string>
<string>u8</string>
<string>uint</string>
<string>vec</string>
<string>warn</string>
</array>
</dict>
</array>
<key>BBLMLanguageCode</key>
<string>Rust</string>
<key>BBLMLanguageDisplayName</key>
<string>Rust</string>
<key>BBLMEntryPointName</key>
<string>rustMain</string>
<key>BBLMScansFunctions</key>
<true/>
<key>BBLMFunctionScannerDoesFoldsToo</key>
<false/>
<key>BBLMSuffixMap</key>
<array>
<dict>
<key>BBLMLanguageSuffix</key>
<string>.rs</string>
</dict>
</array>
<key>BBLMUseHTMLFileSearchRules</key>
<false/>
<key>BBLMSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.line-comment</string>
<string>com.barebones.bblm.block-comment</string>
</array>
<key>BBLMNonSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.code</string>
<string>com.barebones.bblm.double-string</string>
</array>
</dict>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>me.bsago.bblm.rust</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleSignature</key>
<string>BBLM</string>
<key>CFBundleVersion</key>
<string>8.0</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>com.barebones.bblminfo</key>
<array>
<dict>
<key>BBLMCanGuessLanguage</key>
<true/>
<key>BBLMColorsSyntax</key>
<true/>
<key>BBLMDroppedFilePathStyle</key>
<string>POSIX</string>
<key>BBLMCommentLineDefault</key>
<string>// </string>
<key>BBLMCommentPrefixDefault</key>
<string>/* </string>
<key>BBLMCommentSuffixDefault</key>
<string> */</string>
<key>BBLMIsCaseSensitive</key>
<true/>
<key>BBLMRunNames</key>
<dict>
<key>me.bsago.bblm.rust.lifetime</key>
<string>&apos;lifetime</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>Identifier</string>
<key>me.bsago.bblm.rust.function</key>
<string>fn functionname</string>
<key>me.bsago.bblm.rust.module</key>
<string>mod modulename</string>
</dict>
<key>BBLMRunColors</key>
<dict>
<key>me.bsago.bblm.rust.module</key>
<string>rgb(135, 2, 219)</string>
<key>me.bsago.bblm.rust.lifetime</key>
<string>rgb(133, 20, 75)</string>
<key>me.bsago.bblm.rust.identifier</key>
<string>rgb(61, 153, 112)</string>
<key>me.bsago.bblm.rust.function</key>
<string>rgb(219, 135, 2)</string>
</dict>
<key>BBLMKeywords</key>
<array>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.keyword</string>
<key>Keywords</key>
<array>
<string>abstract</string>
<string>alignof</string>
<string>as</string>
<string>become</string>
<string>box</string>
<string>break</string>
<string>const</string>
<string>continue</string>
<string>crate</string>
<string>do</string>
<string>else</string>
<string>enum</string>
<string>extern</string>
<string>false</string>
<string>final</string>
<string>fn</string>
<string>for</string>
<string>if</string>
<string>impl</string>
<string>in</string>
<string>let</string>
<string>loop</string>
<string>macro</string>
<string>macro_rules</string>
<string>match</string>
<string>mod</string>
<string>move</string>
<string>mut</string>
<string>offsetof</string>
<string>override</string>
<string>priv</string>
<string>proc</string>
<string>pub</string>
<string>pure</string>
<string>ref</string>
<string>return</string>
<string>self</string>
<string>sizeof</string>
<string>static</string>
<string>struct</string>
<string>super</string>
<string>trait</string>
<string>true</string>
<string>type</string>
<string>typeof</string>
<string>unsafe</string>
<string>unsized</string>
<string>use</string>
<string>virtual</string>
<string>where</string>
<string>while</string>
<string>yield</string>
</array>
</dict>
<dict>
<key>RunKind</key>
<string>com.barebones.bblm.predefined-symbol</string>
<key>Keywords</key>
<array>
<string>blkcnt_t</string>
<string>blksize_t</string>
<string>bool</string>
<string>c_char</string>
<string>c_double</string>
<string>c_float</string>
<string>c_int</string>
<string>c_long</string>
<string>c_schar</string>
<string>c_short</string>
<string>c_uchar</string>
<string>c_uint</string>
<string>c_ulong</string>
<string>c_ushort</string>
<string>char</string>
<string>clock_t</string>
<string>dev_t</string>
<string>f32</string>
<string>f64</string>
<string>float</string>
<string>gid_t</string>
<string>i16</string>
<string>i32</string>
<string>i64</string>
<string>i8</string>
<string>ino_t</string>
<string>isize</string>
<string>mode_t</string>
<string>nlink_t</string>
<string>off_t</string>
<string>pid_t</string>
<string>ptrdiff_t</string>
<string>size_t</string>
<string>str</string>
<string>suseconds_t</string>
<string>time_t</string>
<string>u16</string>
<string>u32</string>
<string>u64</string>
<string>u8</string>
<string>uid_t</string>
<string>usize</string>
<string>wchar_t</string>
</array>
</dict>
</array>
<key>BBLMLanguageCode</key>
<string>Rust</string>
<key>BBLMLanguageDisplayName</key>
<string>Rust</string>
<key>BBLMEntryPointName</key>
<string>rustMain</string>
<key>BBLMScansFunctions</key>
<true/>
<key>BBLMFunctionScannerDoesFoldsToo</key>
<true/>
<key>BBLMSuffixMap</key>
<array>
<dict>
<key>BBLMLanguageSuffix</key>
<string>.rs</string>
</dict>
</array>
<key>BBLMUseHTMLFileSearchRules</key>
<false/>
<key>BBLMSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.line-comment</string>
<string>com.barebones.bblm.block-comment</string>
</array>
<key>BBLMNonSpellableRunKinds</key>
<array>
<string>com.barebones.bblm.code</string>
<string>com.barebones.bblm.double-string</string>
</array>
</dict>
</array>
</dict>
</plist>

622
rust.mm
View File

@@ -8,12 +8,12 @@
#include "BBLMInterface.h"
#include "BBLMTextIterator.h"
#define kMaxLineLength 256
#define kMaxLineLength 256
static NSString* const identifierColour = @"me.bsago.bblm.rust.identifier";
static NSString* const attributeColour = @"me.bsago.bblm.rust.attribute";
static NSString* const lifetimeColour = @"me.bsago.bblm.rust.lifetime";
static NSString* const functionColour = @"me.bsago.bblm.rust.function";
static NSString* const moduleColour = @"me.bsago.bblm.rust.module";
static bool addRun(NSString *kind, int start,int len , const BBLMCallbackBlock& bblm_callbacks)
{
@@ -30,24 +30,66 @@ static bool addRun(NSString *kind, int start,int len , const BBLMCallbackBlock&
SInt32 skipString(BBLMTextIterator &iter)
{
SInt32 length = 1;
UniChar terminator = iter.GetNextChar();
UniChar ch;
if (iter.strcmp("\"", 1) == 0)
{
iter += 1;
}
else
{
return 0;
}
while ((ch = iter.GetNextChar()))
{
length++;
if (ch == terminator)
if (ch == '"')
{
break;
}
if (ch == '\\')
{
iter++;
length++;
}
}
return length;
}
SInt32 skipRawString(BBLMTextIterator &iter)
{
SInt32 length = 4;
UniChar ch;
if (iter.strcmp("r##\"", 4) == 0)
{
iter += 4;
}
else
{
return 0;
}
while ((ch = iter.GetNextChar()))
{
length++;
if (iter.strcmp("\"##", 3) == 0)
{
length += 3;
iter += 3;
break;
}
if (ch == '\\')
{
iter++;
length++;
}
}
return length;
}
@@ -55,7 +97,7 @@ SInt32 skipLineComment(BBLMTextIterator &iter)
{
SInt32 length = 2;
UniChar ch;
iter += 2;
while ((ch = iter.GetNextChar()))
{
@@ -69,7 +111,7 @@ SInt32 skipLineComment(BBLMTextIterator &iter)
length++;
}
}
return length;
}
@@ -83,10 +125,10 @@ SInt32 skipBlockComment(BBLMTextIterator &iter)
iter++;
length++;
}
iter += 2;
length += 2;
return length;
}
@@ -94,7 +136,7 @@ SInt32 skipWhitespace(BBLMTextIterator &iter)
{
SInt32 length = 0;
UniChar ch;
while ((ch = iter.GetNextChar()))
{
if (isspace(ch))
@@ -107,7 +149,7 @@ SInt32 skipWhitespace(BBLMTextIterator &iter)
break;
}
}
return length;
}
@@ -115,10 +157,10 @@ SInt32 skipWord(BBLMTextIterator &iter)
{
SInt32 length = 0;
UniChar ch;
while ((ch = iter.GetNextChar()))
{
if (isalpha(ch) || ch == '_')
if (isalpha(ch) || ch == '_' || (length > 0 && isdigit(ch)))
{
length++;
}
@@ -128,19 +170,49 @@ SInt32 skipWord(BBLMTextIterator &iter)
break;
}
}
return length;
}
SInt32 skipAttribute(BBLMTextIterator &iter)
{
SInt32 length = 1;
SInt32 length = 0;
UniChar ch;
iter++;
if (iter.strcmp("#[", 2) == 0)
{
length += 2;
iter += 2;
}
else if (iter.strcmp("#![", 3) == 0)
{
length += 3;
iter += 3;
}
else if (iter.strcmp("#", 1) == 0)
{
iter++;
return 1;
}
else
{
return 0;
}
while ((ch = iter.GetNextChar()))
{
if (ch == '\n' || ch == '\r')
if (ch == ']')
{
length++;
break;
}
else if (ch == '"')
{
// We only want to skip newlines in attributes if they're within a string.
iter--;
length += skipString(iter);
}
else if (ch == '\n' || ch == '\r')
{
break;
}
@@ -149,26 +221,77 @@ SInt32 skipAttribute(BBLMTextIterator &iter)
length++;
}
}
return length;
}
SInt32 skipNumber(BBLMTextIterator &iter)
{
UInt32 length = 0;
UniChar ch;
UniChar ch = iter.GetNextChar();
bool hasSuffix = false;
int base = 10;
if (ch == '0')
{
ch = iter.GetNextChar();
if (ch == 'x')
{
base = 16;
length += 2;
}
else if (ch == 'b')
{
base = 2;
length += 2;
}
else if (ch == 'o')
{
base = 8;
length += 2;
}
else if (ch)
{
length++;
iter--;
}
}
else if (ch)
{
iter--;
}
while ((ch = iter.GetNextChar()))
{
if (isdigit(ch) || (ch == '_' && length > 0))
if ((base == 10) && (isdigit(ch) || ((ch == '_' || ch == '.') && length > 0)))
{
length++;
}
else if ((base == 2) && (ch == '0' || ch == '1' || ((ch == '_' || ch == '.') && length > 0)))
{
length++;
}
else if ((base == 8) && ((ch >= '0' && ch <= '7') || ((ch == '_' || ch == '.') && length > 0)))
{
length++;
}
else if ((base == 16) && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F') || isdigit(ch) || ((ch == '_' || ch == '.') && length > 0)))
{
length++;
}
else if (ch == 'f' || ch == 'u' || ch == 'i')
{
hasSuffix = true;
length++;
if (ch != 'f' && iter.strcmp("size", 4) == 0)
{
// Parse 'usize' or 'isize' machine-dependent suffixes
length += 4;
}
else
{
// Otherwise, allow for numbers at the end
hasSuffix = true;
}
break;
}
else
@@ -177,7 +300,7 @@ SInt32 skipNumber(BBLMTextIterator &iter)
break;
}
}
if (hasSuffix)
{
if (iter.strcmp("8", 1) == 0)
@@ -191,7 +314,7 @@ SInt32 skipNumber(BBLMTextIterator &iter)
length += 2;
}
}
return length;
}
@@ -200,11 +323,11 @@ SInt32 skipToEndOfFunction(BBLMTextIterator &iter)
SInt32 length = 0;
UniChar ch;
int braceLevel = 0, parenLevel = 0, bracketLevel = 0;
while ((ch = iter.GetNextChar()))
{
length++;
switch (ch) {
case '/':
ch = iter.GetNextChar();
@@ -223,34 +346,42 @@ SInt32 skipToEndOfFunction(BBLMTextIterator &iter)
iter--;
}
break;
case '{':
braceLevel++;
break;
case '}':
braceLevel--;
if (braceLevel < 1) return length;
break;
case ';':
// If the definition just ends with a semicolon, then it's
// either a function in a trait definition, or a C function
// definition in an extern, neither of which we want in the
// function list.
if (braceLevel < 1) return 0;
break;
case '(':
parenLevel++;
break;
case ')':
parenLevel--;
break;
case '[':
bracketLevel++;
break;
case ']':
bracketLevel--;
break;
}
}
return length;
}
@@ -261,56 +392,107 @@ SInt32 scanForSymbol(BBLMTextIterator &iter,
BBLMParamBlock &params,
const BBLMCallbackBlock *callbacks)
{
SInt32 whitespaceLen, wordLen;
SInt32 whitespaceLen, wordLen = 0, parametersLen = 0;
UniChar ch;
int keywordLen = strlen(keyword);
if (iter.strcmp(keyword, keywordLen) == 0)
{
iter += keywordLen;
if ((whitespaceLen = skipWhitespace(iter)))
{
if ((wordLen = skipWord(iter)))
{
UInt32 funLen = skipToEndOfFunction(iter);
UInt32 tokenOffset, funIndex;
UInt32 nameLen;
BBLMProcInfo info;
iter -= (wordLen + funLen);
nameLen = keywordLen + whitespaceLen + wordLen;
iter -= (keywordLen + whitespaceLen);
bblmAddTokenToBuffer(callbacks, params.fFcnParams.fTokenBuffer, iter.Address(),
nameLen, &tokenOffset);
iter += (nameLen - wordLen);
iter -= (keywordLen + whitespaceLen);
info.fFirstChar = info.fFunctionStart = iter.Offset();
info.fSelStart = iter.Offset() + keywordLen + whitespaceLen;
info.fSelEnd = info.fSelStart + wordLen;
info.fFunctionEnd = info.fSelEnd + funLen;
info.fIndentLevel = indentLevel;
info.fKind = typeIfSo;
info.fFlags = 0;
info.fNameStart = tokenOffset;
info.fNameLength = nameLen;
bblmAddFunctionToList(callbacks, params.fFcnParams.fFcnList, info, &funIndex);
iter += (keywordLen + whitespaceLen);
return info.fFunctionEnd;
// Check for end of word, so 'enum' doesn't also match 'enumerate'.
// But also check for '<', so 'impl<'a>' is a legit statement, even with no whitespace.
whitespaceLen = skipWhitespace(iter);
if (whitespaceLen == 0 && iter.strcmp("<", 1) != 0)
{
iter -= keywordLen + whitespaceLen;
return 0;
}
SInt32 start_of_name = iter.Offset();
SInt32 start_of_function;
while ((ch = iter.GetNextChar()))
{
if (ch == '{' || ch == ';')
{
iter--;
start_of_function = iter.Offset();
break;
}
else if (ch == '(')
{
while ((ch = iter.GetNextChar()))
{
whitespaceLen++;
if (ch == '{' || ch == ';')
{
break;
}
}
iter--;
start_of_function = iter.Offset();
break;
}
else if (ch == '\n')
{
start_of_function = iter.Offset();
break;
}
else if (ch)
{
whitespaceLen++;
}
else
{
iter -= (whitespaceLen + keywordLen);
return 0;
}
}
else
UInt32 funLen = skipToEndOfFunction(iter);
// Skip over trait method definitions and extern functions
if (funLen == 0)
{
iter -= keywordLen;
return 0;
}
UInt32 tokenOffset, funIndex;
UInt32 nameLen;
iter -= (wordLen + funLen);
iter -= (keywordLen + whitespaceLen);
nameLen = keywordLen + whitespaceLen + wordLen;
bblmAddTokenToBuffer(callbacks, params.fFcnParams.fTokenBuffer, iter.Address(),
nameLen, &tokenOffset);
iter += (nameLen - wordLen);
iter -= (keywordLen + whitespaceLen);
BBLMProcInfo info;
info.fFirstChar = info.fFunctionStart = iter.Offset();
info.fSelStart = iter.Offset() + keywordLen + whitespaceLen;
info.fSelEnd = info.fSelStart + wordLen;
info.fFunctionStart = start_of_function;
info.fFunctionEnd = info.fSelEnd + funLen;
info.fIndentLevel = indentLevel;
info.fKind = typeIfSo;
info.fFlags = 0;
info.fNameStart = tokenOffset;
info.fNameLength = nameLen;
bblmAddFunctionToList(callbacks, params.fFcnParams.fFcnList, info, &funIndex);
// But still allow the user to fold them
// (the length changes here are to cut off the opening { and closing } from the fold range
bblmAddFoldRange(callbacks, start_of_function + 1, funLen - 2, kBBLMFunctionAutoFold);
iter += (keywordLen + whitespaceLen);
return info.fFunctionEnd;
}
return 0;
}
@@ -320,24 +502,24 @@ static OSErr scanForFunctions(BBLMParamBlock &params, const BBLMCallbackBlock *c
UniChar ch;
std::stack<int> indents;
SInt32 funEnd;
while ((ch = iter.GetNextChar()))
{
while (!indents.empty() && iter.Offset() >= indents.top())
{
indents.pop();
}
const char* symbolToScanFor = NULL;
int typeIfSo;
switch (ch)
{
case '"':
iter--;
skipString(iter);
break;
case '/':
ch = iter.GetNextChar();
if (ch == '/')
@@ -355,38 +537,38 @@ static OSErr scanForFunctions(BBLMParamBlock &params, const BBLMCallbackBlock *c
iter--;
}
break;
case 'e':
symbolToScanFor = "enum";
typeIfSo = kBBLMFunctionMark;
break;
case 'f':
symbolToScanFor = "fn";
typeIfSo = kBBLMFunctionMark;
break;
case 'i':
symbolToScanFor = "impl";
typeIfSo = kBBLMTypedef;
break;
case 'm':
symbolToScanFor = "mod";
typeIfSo = kBBLMFunctionMark;
break;
case 's':
symbolToScanFor = "struct";
typeIfSo = kBBLMFunctionMark;
break;
case 't':
symbolToScanFor = "trait";
typeIfSo = kBBLMFunctionMark;
break;
}
if (symbolToScanFor != NULL)
{
iter--;
@@ -400,7 +582,7 @@ static OSErr scanForFunctions(BBLMParamBlock &params, const BBLMCallbackBlock *c
}
}
}
return noErr;
}
@@ -423,12 +605,25 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
BBLMTextIterator iter(params, 0);
SInt32 runStart = iter.Offset();
SInt32 runLen;
UniChar ch;
bool wordchr = false;
while ((ch = iter.GetNextChar()))
{
if (ch == '"')
if (ch == 'r' && iter.CharsLeft() >= 3 && iter.strcmp("##\"", 3) == 0)
{
iter--;
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipRawString(iter);
// Use the heredoc colour to highlight raw strings.
// It's not exactly a heredoc, but it's the closest!
if (!addRun(kBBLMHereDocStringRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch == '"')
{
iter--;
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
@@ -437,7 +632,7 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
if (!addRun(kBBLMDoubleQuotedStringRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
// Have to distinguish the following things:
// 'a' (character)
// '\a' (escaped character)
@@ -492,25 +687,171 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
}
}
}
else if (ch == 'f')
else if (!wordchr && ch == 'm')
{
ch = iter.GetNextChar();
if (ch == 'n')
if (ch == 'o')
{
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWhitespace(iter);
runLen += skipWord(iter);
if (!addRun(functionColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
ch = iter.GetNextChar();
if (ch == 'd')
{
ch = iter.GetNextChar();
if (isspace(ch))
{
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWhitespace(iter);
runLen += skipWord(iter);
if (!addRun(moduleColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch)
{
iter--;
}
}
else if (ch)
{
iter--;
}
}
else if (ch == 'a' && iter.CharsLeft() >= 10 && iter.strcmp("cro_rules!", 10) == 0)
{
iter += 10;
ch = iter.GetNextChar();
if (isspace(ch))
{
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWhitespace(iter);
runLen += skipWord(iter);
if (!addRun(functionColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch)
{
iter--;
}
}
else if (ch)
{
iter--;
}
}
else if (!wordchr && ch == 'f')
{
ch = iter.GetNextChar();
if (ch == 'n')
{
ch = iter.GetNextChar();
if (isspace(ch))
{
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWhitespace(iter);
runLen += skipWord(iter);
if (!addRun(functionColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch)
{
iter--;
}
}
else if (ch)
{
iter--;
}
}
else if (!wordchr && ch == 'u')
{
ch = iter.GetNextChar();
if (ch == 's')
{
ch = iter.GetNextChar();
if (ch == 'e')
{
ch = iter.GetNextChar();
if (isspace(ch))
{
skipWhitespace(iter);
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = 0;
bool spacey = false;
while ((ch = iter.GetNextChar()))
{
if (spacey && isupper(ch))
{
iter--;
if (!addRun(kBBLMFileIncludeRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWord(iter);
if (!addRun(identifierColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = 0;
}
else if (ch == ';' || ch == '\n')
{
iter--;
if (!addRun(kBBLMFileIncludeRunKind, runStart, runLen, *callbacks)) return noErr;
break;
}
else if (ch)
{
spacey = isspace(ch) || ch == ':' || ch == '{';
runLen++;
}
else
{
break;
}
if (iter.strcmp(" as ", 4) == 0)
{
if (!addRun(kBBLMFileIncludeRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
iter += 4;
if (!addRun(kBBLMCodeRunKind, runStart, 4, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWord(iter);
if (!addRun(moduleColour, runStart, runLen, *callbacks)) return noErr;
iter++;
runLen = 0;
break;
}
}
if (!addRun(kBBLMFileIncludeRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipWord(iter);
}
else if (ch)
{
iter--;
}
}
else if (ch)
{
iter--;
}
}
else if (ch)
{
iter--;
}
}
else if (ch == '/')
{
ch = iter.GetNextChar();
@@ -537,17 +878,28 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
iter--;
}
}
else if (ch == '#')
{
iter--;
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
runLen = skipAttribute(iter);
if (!addRun(attributeColour, runStart, runLen, *callbacks)) return noErr;
if (!addRun(kBBLMPreprocessorRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch == '$')
{
iter--;
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
runStart = iter.Offset();
iter++;
runLen = skipWord(iter) + 1;
if (runLen > 1 && !addRun(kBBLMVariableRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (!wordchr && isupper(ch))
{
iter--;
@@ -557,7 +909,26 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
if (!addRun(identifierColour, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (!wordchr && (ch == '+' || ch == '-'))
{
ch = iter.GetNextChar();
if (isdigit(ch))
{
iter -= 2;
if (!makeCodeRun(iter, runStart, *callbacks)) return noErr;
iter++;
runStart = iter.Offset() - 1;
runLen = skipNumber(iter) + 1;
if (!addRun(kBBLMNumberRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
else if (ch)
{
iter--;
}
}
else if (!wordchr && isdigit(ch))
{
iter--;
@@ -567,22 +938,25 @@ OSErr calculateRuns(BBLMParamBlock &params, const BBLMCallbackBlock *callbacks)
if (!addRun(kBBLMNumberRunKind, runStart, runLen, *callbacks)) return noErr;
runStart = iter.Offset();
}
wordchr = isalpha(ch) || isdigit(ch);
// '.' is considered a word char to avoid the "0.0" in "tuple.0.0"
// being classified as a floating-point number.
wordchr = isalpha(ch) || isdigit(ch) || ch == '_' || ch == '.';
}
makeCodeRun(iter, runStart, *callbacks);
return noErr;
}
static bool isSpecialKind(NSString* kind)
/*static bool isSpecialKind(NSString* kind)
{
return [kBBLMBlockCommentRunKind isEqualToString:kind]
|| [kBBLMLineCommentRunKind isEqualToString:kind]
|| [identifierColour isEqualToString:kind]
|| [attributeColour isEqualToString:kind]
|| [lifetimeColour isEqualToString:kind];
}
|| [lifetimeColour isEqualToString:kind]
|| [functionColour isEqualToString:kind];
}*/
OSErr adjustRange(BBLMParamBlock &params, const BBLMCallbackBlock &callbacks)
{
@@ -591,12 +965,12 @@ OSErr adjustRange(BBLMParamBlock &params, const BBLMCallbackBlock &callbacks)
SInt32 charPos;
SInt32 length;
UInt32 index = params.fAdjustRangeParams.fStartIndex;
while (index > 0 && bblmGetRun(&callbacks, index, language, kind, charPos, length) && isSpecialKind(kind))
while (index > 0 && bblmGetRun(&callbacks, index, language, kind, charPos, length)/* && isSpecialKind(kind)*/)
{
index--;
}
params.fAdjustRangeParams.fStartIndex = index;
return noErr;
}
@@ -604,12 +978,16 @@ OSErr adjustRange(BBLMParamBlock &params, const BBLMCallbackBlock &callbacks)
OSErr guessLanguage(BBLMParamBlock &params)
{
BBLMTextIterator iter(params);
if (iter.strcmp("use ", 4) == 0 || iter.strcmp("#![crate_id", 11) == 0)
if (iter.strcmp("#![crate_name", 13) == 0)
{
params.fGuessLanguageParams.fGuessResult = kBBLMGuessDefiniteYes;
}
else if (iter.strcmp("use ", 4) == 0 || iter.strcmp("//! ", 4) == 0)
{
params.fGuessLanguageParams.fGuessResult = kBBLMGuessMaybe;
}
return noErr;
}
@@ -622,29 +1000,29 @@ extern "C"
{
// Dispatch message.
OSErr result = noErr;
switch (params.fMessage)
{
case kBBLMDisposeMessage:
case kBBLMSetCategoriesMessage:
// Message understood, but no action required.
break;
case kBBLMInitMessage:
break;
case kBBLMScanForFunctionsMessage:
result = scanForFunctions(params, &bblmCallbacks);
break;
case kBBLMCalculateRunsMessage:
result = calculateRuns(params, &bblmCallbacks);
break;
case kBBLMGuessLanguageMessage:
result = guessLanguage(params);
break;
case kBBLMAdjustRangeMessage:
result = adjustRange(params, bblmCallbacks);
break;
@@ -652,7 +1030,7 @@ extern "C"
default:
result = paramErr;
}
return result;
}
}
}

BIN
screenshots.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

141
smoke.rs Normal file
View File

@@ -0,0 +1,141 @@
// Keywords
// --------
abstract, alignof, as, become, box, break, const, continue, crate, do, else, enum,
extern, false, final, fn, for, if, impl, in, let, loop, macro, match, mod, move, mut,
offsetof, override, priv, pub, pure, ref, return, sizeof, static, self, struct, super,
true, trait, type, typeof, unsafe, unsized, use, virtual, where, while, yield.
// Types
// -----
- ()
- bool, char, str
- u8, u16, u32, u64
- i8, i16, i32, i64
- f32, f64
- usize, isize
- int, uint // these are no longer valid!
// Comments
// --------
// This is a comment
/* So is this */
/// This is a doc comment
/** So is this */
// Characters and Lifetimes
// ------------------------
'a' // a character
'a // a lifetime
'static // also a lifetime
b'a' // a byte
' ' // this is also a character (space)
'\t' // characters can be escaped
'\'' // including the quote character itself!
"geese" // a string
r##"geese"## // a raw string. This part should not be highlighted!
b"geese" // a byte string
br##"geese"## // a raw byte string. This part should still not be highlighted
"there's a \" in this string" // be sure to handle escapes
"\"geese\"" // including at the edges
r##"there's a " in this string"## // the string shouldn't end until ##
r##"there's a # in this string"## // even if there's a # in the middle
// " // in case the above failed :)
// Decimal Numbers
// ---------------
7, 12, 1048576 // are all numbers
1_000_000 // is a number with underscore separators
_, _1000, 1000_ // beware of sole/leading/trailing underscores
// Hex Numbers
// -----------
0xff // hex numbers start with 0x
0xFF // and can be in lowercase or uppercase
0x0123_4567 // and can have separators
// Octal Numbers
// -------------
0o77 // octal numbers start with 0o
0o12345678909 // and should finish after an 8 or 9
// Binary Numbers
// --------------
0b0000_1111 // binary numbers start with 0b
0b01234311 // and should finish after a 2 or higher
// Floating-Point Numbers
// ----------------------
6.022E-23 // floating point notation
5.974e24 // lowercase e
7.348e+22 // uppercase E and plus
.1234 // no leading zero (invalid)
let tuple = ((8, 4), 48);
tuple.0
tuple.0.0 // tuple indexing (not really numbers)
// Numeric Suffixes
// ----------------
123i32, 123u32 // numbers can have literals
123_u32, 0xff_u8
0o70_i16, 0b1111_1111_1001_0000_i32
0usize, 7isize
123.0f64
0.1f64
0.1f32
12E+99_f64
0us, 7is // Invalid!
2.f64 // Also invalid!
// Attributes
// ----------
#[attribute]
#[derive(This, That, Other)]
#![top_level_attribute]
#not_an_attribute
#[macro_use] use this_is_not_an_attribute;
#[unfinished_attribute // not a comment
and this should be back to regular code. // back to comments again
#[unfinished_attribute="but look \ // not a comment
a string!"] // back to comments again
// Macros
// ------
macro_rules! parse {
($thing: expr) => { $thing };
}
// `use` statements
// ----------------
use flux;
use flux::capacitor;
use flux::capacitor::Component::*;
use flux::capacitor::Component::{ImpurePalladium, ThinkingAluminium, TimeyWimeyDevice};
use flux::capacitor as cap;
use super;
use self;