about summary refs log tree commit diff
diff options
context:
space:
mode:
authorProfpatsch <mail@profpatsch.de>2021-01-17T11·32+0100
committerProfpatsch <mail@profpatsch.de>2021-01-17T11·37+0000
commit80e1ece32931530a0a024db9828d197f3fdb1951 (patch)
tree0a98a447b56c1c4d897025a7ff1ad73eecebdfd5
parentf8b3e2a100fdb28cad24948703439d2964c31580 (diff)
feat(users/Profpatsch): set up a file watcher for tree sitter r/2121
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 <mail@profpatsch.de>
-rw-r--r--third_party/nixpkgs-exposed/exposed/default.nix4
-rw-r--r--users/Profpatsch/lib.nix14
-rw-r--r--users/Profpatsch/rust-crates.nix32
-rw-r--r--users/Profpatsch/tree-sitter.nix96
4 files changed, 136 insertions, 10 deletions
diff --git a/third_party/nixpkgs-exposed/exposed/default.nix b/third_party/nixpkgs-exposed/exposed/default.nix
index 8c666bbf59..32630ca6e2 100644
--- a/third_party/nixpkgs-exposed/exposed/default.nix
+++ b/third_party/nixpkgs-exposed/exposed/default.nix
@@ -13,6 +13,7 @@
     avrlibc
     bashInteractive
     bat
+    bc
     buildBazelPackage
     buildFHSUserEnv
     buildGoModule
@@ -44,6 +45,7 @@
     emacsPackagesGen
     execline
     fd
+    fdtools
     fetchFromGitHub
     fetchgit
     fetchurl
@@ -87,9 +89,11 @@
     mkShell
     moreutils
     nano
+    ncurses
     nginx
     ninja
     nix
+    ocamlPackages
     openssh
     openssl
     overrideCC
diff --git a/users/Profpatsch/lib.nix b/users/Profpatsch/lib.nix
index 69e6f73e40..9215f5b19c 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 ebe6d73ceb..ecf3c96077 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 dd1dc05a64..4a05c825ba 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<u8> {
+            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
     ;
 }