From 80e1ece32931530a0a024db9828d197f3fdb1951 Mon Sep 17 00:00:00 2001 From: Profpatsch Date: Sun, 17 Jan 2021 12:32:09 +0100 Subject: feat(users/Profpatsch): set up a file watcher for tree sitter Uses inotify to watch a file and print when it is modified, so we can update the parser and display the sexp on the terminal. Now the setup is good enough to start experiementing with queries on the syntax tree. Change-Id: I091587fc495ff627c79a69a52915aaaa8c51fcd2 Reviewed-on: https://cl.tvl.fyi/c/depot/+/2411 Tested-by: BuildkiteCI Reviewed-by: Profpatsch --- users/Profpatsch/lib.nix | 14 +++++- users/Profpatsch/rust-crates.nix | 32 ++++++++++++++ users/Profpatsch/tree-sitter.nix | 96 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 132 insertions(+), 10 deletions(-) (limited to 'users') diff --git a/users/Profpatsch/lib.nix b/users/Profpatsch/lib.nix index 69e6f73e408a..9215f5b19c77 100644 --- a/users/Profpatsch/lib.nix +++ b/users/Profpatsch/lib.nix @@ -1,6 +1,8 @@ { depot, pkgs, ... }: let - bins = depot.nix.getBins pkgs.coreutils ["printf" "echo"]; + bins = depot.nix.getBins pkgs.coreutils [ "printf" "echo" "cat" "printenv" ] + // depot.nix.getBins pkgs.fdtools [ "multitee" ] + ; debugExec = msg: depot.nix.writeExecline "debug-exec" {} [ "if" [ @@ -15,9 +17,19 @@ let "fdmove" "-c" "1" "2" bins.printf "$@" ]; + eprint-stdin = depot.nix.writeExecline "eprint-stdin" {} [ + "pipeline" [ bins.multitee "0-1,2" ] "$@" + ]; + + eprintenv = depot.nix.writeExecline "eprintenv" { readNArgs = 1; } [ + "fdmove" "-c" "1" "2" bins.printenv "$1" + ]; + in { inherit debugExec eprintf + eprint-stdin + eprintenv ; } diff --git a/users/Profpatsch/rust-crates.nix b/users/Profpatsch/rust-crates.nix index ebe6d73ceba9..ecf3c960775b 100644 --- a/users/Profpatsch/rust-crates.nix +++ b/users/Profpatsch/rust-crates.nix @@ -50,4 +50,36 @@ rec { buildDependencies = [ cc ]; sha256 = "0jwwbvs4icpra7m1ycvnyri5h3sbw4qrfvgnnvnk72h4w93qhzhr"; }; + + libc = pkgs.buildRustCrate { + pname = "libc"; + crateName = "libc"; + version = "0.2.82"; + sha256 = "02zgn6c0xwh331hky417lbr29kmvrw3ylxs8822syyhjfjqszvsx"; + }; + + bitflags = pkgs.buildRustCrate { + pname = "bitflags"; + crateName = "bitflags"; + version = "1.2.1"; + sha256 = "0b77awhpn7yaqjjibm69ginfn996azx5vkzfjj39g3wbsqs7mkxg"; + }; + + inotify-sys = pkgs.buildRustCrate { + pname = "inotify-sys"; + crateName = "inotify-sys"; + version = "0.1.5"; + dependencies = [ libc ]; + sha256 = "1yiy577xxhi0j90nbg9nkd8cqwc1xix62rz55jjngvxa5jl5613v"; + }; + + inotify = pkgs.buildRustCrate { + pname = "inotify"; + crateName = "inotify"; + version = "0.9.2"; + edition = "2018"; + dependencies = [ bitflags libc inotify-sys ]; + sha256 = "0fcknyvknglwwk1pdzdlb4m0ry2dym1yx8r5prf2v00pxnjk0hv2"; + }; + } diff --git a/users/Profpatsch/tree-sitter.nix b/users/Profpatsch/tree-sitter.nix index dd1dc05a6401..4a05c825bab4 100644 --- a/users/Profpatsch/tree-sitter.nix +++ b/users/Profpatsch/tree-sitter.nix @@ -1,15 +1,17 @@ { depot, pkgs, lib, ... }: let + bins = depot.nix.getBins pkgs.coreutils [ "head" "printf" "cat" ] + // depot.nix.getBins pkgs.ncurses [ "tput" ] + // depot.nix.getBins pkgs.bc [ "bc" ] + // depot.nix.getBins pkgs.ocamlPackages.sexp [ "sexp" ]; + print-ast = depot.users.Profpatsch.writers.rustSimple { name = "print-ast"; dependencies = with depot.users.Profpatsch.rust-crates; [ libloading tree-sitter ]; - buildInputs = [ - pkgs.tree-sitter - ]; } '' extern crate libloading; extern crate tree_sitter; @@ -39,9 +41,7 @@ let let mut parser = Parser::new(); let lang = _load_language(so, symbol_name).unwrap(); parser.set_language(lang).unwrap(); - let mut bytes = Vec::new(); - let mut file = std::fs::OpenOptions::new().read(true).open(file).unwrap(); - file.read_to_end(&mut bytes); + let bytes = std::fs::read(&file).unwrap(); print!("{}", parser.parse(&bytes, None).unwrap().root_node().to_sexp()); } @@ -58,8 +58,85 @@ let }; }; - parse-nix-file = depot.nix.writeExecline "parse-nix-file" { readNArgs = 1; } [ - print-ast "${tree-sitter-nix}/parser" "tree_sitter_nix" "$1" + watch-file-modified = depot.users.Profpatsch.writers.rustSimple { + name = "watch-file-modified"; + dependencies = [ depot.users.Profpatsch.rust-crates.inotify ]; + } '' + extern crate inotify; + use inotify::{EventMask, WatchMask, Inotify}; + use std::io::Write; + + fn main() { + let mut inotify = Inotify::init() + .expect("Failed to initialize inotify"); + + let file = std::env::args().nth(1).unwrap(); + + let file_watch = inotify + .add_watch( + &file, + WatchMask::MODIFY + ) + .expect("Failed to add inotify watch"); + + fn to_netstring(s: &[u8]) -> Vec { + let len = s.len(); + // length of the integer as ascii + let i_len = ((len as f64).log10() as usize) + 1; + let ns_len = i_len + 1 + len + 1; + let mut res = Vec::with_capacity(ns_len); + res.extend_from_slice(format!("{}:", len).as_bytes()); + res.extend_from_slice(s); + res.push(b','); + res + } + + let mut buffer = [0u8; 4096]; + loop { + let events = inotify + .read_events_blocking(&mut buffer) + .expect("Failed to read inotify events"); + + for event in events { + if event.wd == file_watch { + std::io::stdout().write(&to_netstring(file.as_bytes())); + std::io::stdout().flush(); + } + } + } + } + + ''; + + # clear screen and set LINES and COLUMNS to terminal height & width + clear-screen = depot.nix.writeExecline "clear-screen" {} [ + "if" [ bins.tput "clear" ] + "backtick" "-in" "LINES" [ bins.tput "lines" ] + "backtick" "-in" "COLUMNS" [ bins.tput "cols" ] + "$@" + ]; + + print-nix-file = depot.nix.writeExecline "print-nix-file" { readNArgs = 1; } [ + "pipeline" [ print-ast "${tree-sitter-nix}/parser" "tree_sitter_nix" "$1" ] + "pipeline" [ bins.sexp "print" ] + clear-screen + "importas" "-ui" "lines" "LINES" + "backtick" "-in" "ls" [ + "pipeline" + # when you pull out bc to decrement an integer it’s time to switch to python lol + [ bins.printf "x=%s; --x\n" "$lines" ] + bins.bc + ] + "importas" "-ui" "l" "ls" + bins.head "-n\${l}" + ]; + + print-nix-file-on-update = depot.nix.writeExecline "print-nix-file-on-update" { readNArgs = 1; } [ + "if" [ print-nix-file "$1" ] + "pipeline" [ watch-file-modified "$1" ] + "forstdin" "-d" "" "file" + "importas" "file" "file" + print-nix-file "$file" ]; # copied from nixpkgs @@ -104,6 +181,7 @@ in { inherit print-ast tree-sitter-nix - parse-nix-file + print-nix-file-on-update + watch-file-modified ; } -- cgit 1.4.1