simple textmate syntax highlighting
This commit is contained in:
parent
de9f55842c
commit
11da3ddced
15 changed files with 280 additions and 28 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -210,6 +210,7 @@ dependencies = [
|
||||||
"tower-livereload",
|
"tower-livereload",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"url",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,4 @@ tower-livereload = "0.9.6"
|
||||||
log = "0.4.28"
|
log = "0.4.28"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
thiserror = "2.0.17"
|
thiserror = "2.0.17"
|
||||||
|
url = "2.5.7"
|
||||||
|
|
|
||||||
23
examples/api/customer/controller.crud
Normal file
23
examples/api/customer/controller.crud
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#path(/id/{uuid})
|
||||||
|
fn get(uuid: uuid) -> Customer:
|
||||||
|
service.get(uuid)?or(404)
|
||||||
|
|
||||||
|
#path(?firstname={name})
|
||||||
|
fn get(name: string) -> Customer:
|
||||||
|
if name:
|
||||||
|
service.get(id)
|
||||||
|
else:
|
||||||
|
404
|
||||||
|
|
||||||
|
#path(/)
|
||||||
|
fn get() -> list:
|
||||||
|
service.get_all()
|
||||||
|
|
||||||
|
#path(/)
|
||||||
|
fn post(customer: Customer):
|
||||||
|
service.add(customer)
|
||||||
|
|
||||||
|
|
||||||
|
#path()
|
||||||
|
fn put(customer: Customer):
|
||||||
|
service.update(customer)
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
///gets the customer
|
|
||||||
fn get(id: u32) -> Customer:
|
|
||||||
service.get(id)
|
|
||||||
|
|
||||||
fn post(customer: Customer):
|
|
||||||
service.add(customer)
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
struct Customer:
|
object Customer:
|
||||||
id: u32,
|
id: u32,
|
||||||
first_name: string,
|
first_name: string,
|
||||||
last_name: string,
|
last_name: string,
|
||||||
|
|
|
||||||
76
src/main.rs
76
src/main.rs
|
|
@ -1,15 +1,16 @@
|
||||||
use axum::extract::{State};
|
use axum::extract::{Request, State};
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::routing::get;
|
use axum::routing::{any, get};
|
||||||
use axum::{Json, Router};
|
use axum::{Json, Router};
|
||||||
use crudlang::ast_compiler;
|
use crudlang::ast_compiler;
|
||||||
use crudlang::bytecode_compiler::compile;
|
use crudlang::bytecode_compiler::compile;
|
||||||
use crudlang::chunk::Chunk;
|
use crudlang::chunk::Chunk;
|
||||||
use crudlang::scanner::scan;
|
use crudlang::scanner::scan;
|
||||||
use crudlang::vm::{interpret, interpret_async};
|
use crudlang::vm::{interpret_async};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use axum::response::IntoResponse;
|
||||||
use walkdir::WalkDir;
|
use walkdir::WalkDir;
|
||||||
use crudlang::errors::Error;
|
use crudlang::errors::Error;
|
||||||
use crudlang::errors::Error::Platform;
|
use crudlang::errors::Error::Platform;
|
||||||
|
|
@ -46,28 +47,40 @@ async fn main() -> Result<(), crudlang::errors::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let registry = Arc::new(registry);
|
let registry = Arc::new(registry);
|
||||||
if !paths.is_empty() {
|
// if !paths.is_empty() {
|
||||||
let mut app = Router::new();
|
// let mut app = Router::new();
|
||||||
for (path, code) in paths.iter() {
|
// for (path, code) in paths.iter() {
|
||||||
let state = Arc::new(AppState {
|
// let state = Arc::new(AppState {
|
||||||
name: format!("{}.get", path),
|
// name: format!("{}.get", path),
|
||||||
registry: registry.clone(),
|
// registry: registry.clone(),
|
||||||
});
|
// });
|
||||||
println!("adding {}", path);
|
// println!("adding {}", path);
|
||||||
app = app.route(
|
// app = app.route(
|
||||||
&format!("/{}", path.replace("/web", "")),
|
// &format!("/{}", path.replace("/web", "")),
|
||||||
get(handle_get).with_state(state.clone()),
|
// get(handle_get).with_state(state.clone()),
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.map_err(map_underlying())?;
|
// let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.map_err(map_underlying())?;
|
||||||
|
// println!("listening on {}", listener.local_addr().map_err(map_underlying())?);
|
||||||
|
// axum::serve(listener, app).await.map_err(map_underlying())?;
|
||||||
|
// }
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route("/", any(handle_any))
|
||||||
|
.route("/{*path}", any(handle_any));
|
||||||
|
|
||||||
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000")
|
||||||
|
.await
|
||||||
|
.map_err(map_underlying())?;
|
||||||
|
|
||||||
println!("listening on {}", listener.local_addr().map_err(map_underlying())?);
|
println!("listening on {}", listener.local_addr().map_err(map_underlying())?);
|
||||||
|
|
||||||
axum::serve(listener, app).await.map_err(map_underlying())?;
|
axum::serve(listener, app).await.map_err(map_underlying())?;
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_underlying() -> fn(std::io::Error) -> Error {
|
fn map_underlying() -> fn(std::io::Error) -> Error {
|
||||||
|e| Error::Platform(e.to_string())
|
|e| Platform(e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -85,3 +98,28 @@ async fn handle_get(State(state): State<Arc<AppState>>) -> Result<Json<String>,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn handle_any(req: Request) -> impl IntoResponse {
|
||||||
|
let method = req.method().clone();
|
||||||
|
let uri = req.uri();
|
||||||
|
|
||||||
|
// Parse path segments
|
||||||
|
let path_segments: Vec<&str> = uri.path()
|
||||||
|
.split('/')
|
||||||
|
.filter(|s| !s.is_empty())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Parse query parameters
|
||||||
|
let query_params: HashMap<String, String> = uri.query()
|
||||||
|
.map(|q| {
|
||||||
|
url::form_urlencoded::parse(q.as_bytes())
|
||||||
|
.into_owned()
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
format!(
|
||||||
|
"Method: {}\nPath: {}\nSegments: {:?}\nQuery: {:?}",
|
||||||
|
method, uri.path(), path_segments, query_params
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ impl Scanner {
|
||||||
};
|
};
|
||||||
self.add_token(t);
|
self.add_token(t);
|
||||||
}
|
}
|
||||||
|
'#' => self.add_token(TokenType::Hash),
|
||||||
'+' => self.add_token(TokenType::Plus),
|
'+' => self.add_token(TokenType::Plus),
|
||||||
':' => self.add_token(TokenType::Colon),
|
':' => self.add_token(TokenType::Colon),
|
||||||
';' => println!("Warning: Ignoring semicolon at line {}", self.line),
|
';' => println!("Warning: Ignoring semicolon at line {}", self.line),
|
||||||
|
|
|
||||||
4
syntax/crud/.vscodeignore
Normal file
4
syntax/crud/.vscodeignore
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
.vscode/**
|
||||||
|
.vscode-test/**
|
||||||
|
.gitignore
|
||||||
|
vsc-extension-quickstart.md
|
||||||
9
syntax/crud/CHANGELOG.md
Normal file
9
syntax/crud/CHANGELOG.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to the "crud" extension will be documented in this file.
|
||||||
|
|
||||||
|
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Initial release
|
||||||
25
syntax/crud/language-configuration.json
Normal file
25
syntax/crud/language-configuration.json
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"comments": {
|
||||||
|
"lineComment": "//",
|
||||||
|
"blockComment": [ "/*", "*/" ]
|
||||||
|
},
|
||||||
|
"brackets": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"]
|
||||||
|
],
|
||||||
|
"autoClosingPairs": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"],
|
||||||
|
["\"", "\""],
|
||||||
|
["'", "'"]
|
||||||
|
],
|
||||||
|
"surroundingPairs": [
|
||||||
|
["{", "}"],
|
||||||
|
["[", "]"],
|
||||||
|
["(", ")"],
|
||||||
|
["\"", "\""],
|
||||||
|
["'", "'"]
|
||||||
|
]
|
||||||
|
}
|
||||||
32
syntax/crud/package.json
Normal file
32
syntax/crud/package.json
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"name": "crud",
|
||||||
|
"displayName": "crud",
|
||||||
|
"description": "crud-lang",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"engines": {
|
||||||
|
"vscode": "^1.105.0"
|
||||||
|
},
|
||||||
|
"categories": [
|
||||||
|
"Programming Languages"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"languages": [{
|
||||||
|
"id": "crud",
|
||||||
|
"aliases": ["crud-lang", "crud"],
|
||||||
|
"extensions": [".crud"],
|
||||||
|
"configuration": "./language-configuration.json"
|
||||||
|
}],
|
||||||
|
"grammars": [{
|
||||||
|
"language": "crud",
|
||||||
|
"scopeName": "source.crud",
|
||||||
|
"path": "./syntaxes/crud.tmLanguage.json"
|
||||||
|
}],
|
||||||
|
"semanticTokenScopes": [
|
||||||
|
{
|
||||||
|
"scopes": {
|
||||||
|
"crud.custom.scope": ["annotation.crud"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
95
syntax/crud/syntaxes/crud.tmLanguage.json
Normal file
95
syntax/crud/syntaxes/crud.tmLanguage.json
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
|
||||||
|
"name": "crud-lang",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"include": "#keywords"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#operators"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#strings"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"include": "#chars"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"keywords": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "variable.other.crud",
|
||||||
|
"match": "(#.+?\\(.*?\\))"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.control.crud",
|
||||||
|
"match": "\\b(fn)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "storage.type.crud",
|
||||||
|
"match": "\\b(u32|u64|i32|i64\f32|f64|string|date|char|list|map|bool)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "support.function.crud",
|
||||||
|
"match": "\\b(get|put|post|delete|patch|options)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.numeric.crud",
|
||||||
|
"match": "\\b[0-9]+\\.?[0-9]*\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.language.crud",
|
||||||
|
"match": "\\b(true|false)\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "constant.character.escape.crud",
|
||||||
|
"match": "\\\\[nrt\\\\'\"]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "comment.line.crud",
|
||||||
|
"match": "(//.*)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"operators": {
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "keyword.operator.arithmetic.crud",
|
||||||
|
"match": "\\+|\\-|\\*|\\/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.operator.comparison.crud",
|
||||||
|
"match": "==|!=|<=|>=|<|>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "keyword.operator.assignment.crud",
|
||||||
|
"match": "="
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"strings": {
|
||||||
|
"name": "string.quoted.double.crud",
|
||||||
|
"begin": "\"",
|
||||||
|
"end": "\"",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "constant.character.escape.crud",
|
||||||
|
"match": "\\\\."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chars": {
|
||||||
|
"name": "string.quoted.single.crud",
|
||||||
|
"begin": "'",
|
||||||
|
"end": "'",
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"name": "constant.character.escape.crud",
|
||||||
|
"match": "\\\\."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scopeName": "source.crud"
|
||||||
|
}
|
||||||
29
syntax/crud/vsc-extension-quickstart.md
Normal file
29
syntax/crud/vsc-extension-quickstart.md
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Welcome to your VS Code Extension
|
||||||
|
|
||||||
|
## What's in the folder
|
||||||
|
|
||||||
|
* This folder contains all of the files necessary for your extension.
|
||||||
|
* `package.json` - this is the manifest file in which you declare your language support and define the location of the grammar file that has been copied into your extension.
|
||||||
|
* `syntaxes/crud.tmLanguage.json` - this is the Text mate grammar file that is used for tokenization.
|
||||||
|
* `language-configuration.json` - this is the language configuration, defining the tokens that are used for comments and brackets.
|
||||||
|
|
||||||
|
## Get up and running straight away
|
||||||
|
|
||||||
|
* Make sure the language configuration settings in `language-configuration.json` are accurate.
|
||||||
|
* Press `F5` to open a new window with your extension loaded.
|
||||||
|
* Create a new file with a file name suffix matching your language.
|
||||||
|
* Verify that syntax highlighting works and that the language configuration settings are working.
|
||||||
|
|
||||||
|
## Make changes
|
||||||
|
|
||||||
|
* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
|
||||||
|
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
|
||||||
|
|
||||||
|
## Add more language features
|
||||||
|
|
||||||
|
* To add features such as IntelliSense, hovers and validators check out the VS Code extenders documentation at https://code.visualstudio.com/api/language-extensions/overview
|
||||||
|
|
||||||
|
## Install your extension
|
||||||
|
|
||||||
|
* To start using your extension with Visual Studio Code copy it into the `<user home>/.vscode/extensions` folder and restart Code.
|
||||||
|
* To share your extension with the world, read on https://code.visualstudio.com/api/working-with-extensions/publishing-extension about publishing an extension.
|
||||||
Loading…
Add table
Reference in a new issue