summaryrefslogtreecommitdiff
path: root/Biz/Ide
diff options
context:
space:
mode:
Diffstat (limited to 'Biz/Ide')
-rwxr-xr-xBiz/Ide/MakeTags.py105
-rwxr-xr-xBiz/Ide/hooks/post-checkout8
-rwxr-xr-xBiz/Ide/mktags.sh41
3 files changed, 110 insertions, 44 deletions
diff --git a/Biz/Ide/MakeTags.py b/Biz/Ide/MakeTags.py
new file mode 100755
index 0000000..add07c0
--- /dev/null
+++ b/Biz/Ide/MakeTags.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python
+"""
+Make tags for internal or external code.
+
+This should run fast, and be executable with just Python, meaning it does not
+require a build step.
+"""
+
+# : out maketags
+# : run universal-ctags
+import argparse
+import os
+import pathlib
+import subprocess
+import tarfile
+import zipfile
+
+
+def main() -> None:
+ """Run ctags on internal or external source code.
+
+ Raises:
+ ValueError: if CODEROOT is not set
+ ArgumentError: when explicit paths aren't provided
+ """
+ coderoot = os.environ.get("CODEROOT")
+ if coderoot is None:
+ msg = "CODEROOT not set"
+ raise ValueError(msg)
+ cabsrc = pathlib.Path(coderoot) / "_" / "src"
+ cli = argparse.ArgumentParser()
+ cli.add_argument(
+ "paths",
+ nargs="*",
+ default=".",
+ help="List of paths to run ctags on. Defaults to '.'",
+ )
+ cli.add_argument(
+ "-x",
+ "--external",
+ action="store_true",
+ help=" ".join([
+ "Use this when `paths` is a list of external packages,",
+ f"they will be extracted or linked into {cabsrc}",
+ ]),
+ )
+ args = cli.parse_args()
+ if args.external and args.paths == ".":
+ msg = "requires explicit paths"
+ raise argparse.ArgumentError(argument=args.external, message=msg)
+ if args.external:
+ extract_and_copy(cabsrc, args.paths)
+ ctags(["--recurse=yes"], cwd=cabsrc)
+ else:
+ ctags(["--exclude=*_/*", "--recurse=yes"], cwd=pathlib.Path(coderoot))
+
+
+def strip_nix_hash(path: str) -> str:
+ """Remove the /nix/store/ and hash prefix from a path."""
+ hash_len = 33
+ return path.removeprefix("/nix/store/")[hash_len:]
+
+
+def extract_and_copy(cabsrc: pathlib.Path, paths: list[str]) -> None:
+ """
+ Extract and copy or link sources.
+
+ Loop over `paths`, if the path is an archive, extract it into `cabsrc`. If
+ its a directory, just symlink the directory into `cabsrc`. Either way, we
+ end up with a directory full of source trees for running ctags on.
+ """
+ for path in paths:
+ outpath: pathlib.Path = cabsrc / strip_nix_hash(path)
+ if outpath.exists():
+ continue
+ if path.endswith(".zip"):
+ out = outpath.with_suffix("")
+ if out.exists():
+ continue
+ zipfile.ZipFile(path).extractall(out) # noqa: S202
+ elif path.endswith(".tar.gz"):
+ out = outpath.with_suffix("").with_suffix("")
+ if out.exists():
+ continue
+ with tarfile.open(path) as tarball:
+ tarball.extractall(out) # noqa: S202
+ elif pathlib.Path(path).is_dir():
+ outpath.symlink_to(path)
+
+
+def ctags(args: list[str], cwd: pathlib.Path = pathlib.Path()) -> None:
+ """Call `ctags` with `args` for both emacs and vim."""
+ os.chdir(cwd)
+ excludes = [
+ "--exclude=.mypy_cache",
+ "--exclude=.git",
+ "--exclude=.direnv",
+ "--exclude=.ruff_cache",
+ ]
+ subprocess.check_call(["ctags", *excludes, *args])
+ subprocess.check_call(["ctags", "-e", *excludes, *args])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/Biz/Ide/hooks/post-checkout b/Biz/Ide/hooks/post-checkout
index 72ec5a7..4f58c74 100755
--- a/Biz/Ide/hooks/post-checkout
+++ b/Biz/Ide/hooks/post-checkout
@@ -1,16 +1,18 @@
#!/usr/bin/env bash
set -e
-mktags=${CODEROOT:?}/Biz/Ide/mktags.sh
+function MakeTags {
+ ${CODEROOT:?}/Biz/Ide/MakeTags.py
+}
old=$1
new=$2
# filter out only the changed haskell files
mapfile -t changed < <(git diff --diff-filter=d --name-only "$old" "$new" -- '*.hs')
if [[ ! -r tags ]] || [[ ! -r TAGS ]]
then
- $mktags "$CODEROOT"/**/*
+ MakeTags "$CODEROOT"/**/*
elif [[ ${#changed[@]} -gt 0 ]]
then
- $mktags "${changed[@]}"
+ MakeTags "${changed[@]}"
fi
## START BRANCHLESS CONFIG
diff --git a/Biz/Ide/mktags.sh b/Biz/Ide/mktags.sh
deleted file mode 100755
index aae1505..0000000
--- a/Biz/Ide/mktags.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-#
-# script to generate tags automatically if there are none.
-#
- set -euo pipefail
- files="$*"
- vimtags=${CODEROOT:?}/tags
- emacstags=${CODEROOT:?}/TAGS
-#
- if [[ ! -r $emacstags ]]; then
- echo Generating emacs TAGS from scratch...
- fast-tags -e -R "${CODEROOT:?}"
- ctags -e \
- --append=yes \
- --recurse=yes \
- --exclude="$CODEROOT/_/*" \
- "${CODEROOT:?}"
- else
- fast-tags -e "$files"
- ctags -e \
- --append=yes \
- --exclude="_/*" \
- "$files"
- fi
-#
- if [[ ! -r $vimtags ]]; then
- echo Generating vim tags from scratch...
- fast-tags -R "${CODEROOT:?}"
- ctags \
- --append=yes \
- --recurse=yes \
- --exclude="${CODEROOT:?}/_/*" \
- "${CODEROOT:?}"
- else
- fast-tags "$files"
- ctags \
- --append=yes \
- --exclude="_/*" \
- "$files"
- fi
-##