Skip to content
/ AYA Public

File system scripting from the comfort of a NodeJS REPL

Notifications You must be signed in to change notification settings

Jirinrin/AYA

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AYA

AYA (Ayaya!) is a wonderful/powerful CLI tool which enables you to:

  • Manipulate your file system in all kinds of ways, allowing to write complex logic and save it for later use
  • Do all the things a NodeJS REPL does, but with syntax highlighting and better auto-completion

To get started, either grab an executable from the releases (currently Windows only) on Github, or clone the repo to get the latest and greatest.
For the latter, run yarn init to start off. This will build the JS and generate an executable for your system architecture to use.
Then make it accessible from your shell by adding either the /path directory or the generated /bin directory to your PATH.

Have fun with it!

But tread with care! Aya is powerful and has all the priviledges your shell has, therefore one wrong command can seriously screw with your files and directories.

How it works

Aya's environment has some similarities to a shell: you always have a .cwd, and you can .ls and .cd to undiscovered places.

The core of Aya is a system of commands which (recursively) iterate over the files in your current working directory. Some of these commands allow you to pass in options and arguments, which can be simple strings or entire javascript callbacks to define the logic that is executed for each item.

Let's look at the main command on which a lot of other commands are built: doForEach. This command expects you to give it a JS callback which it will then execute for each item. For instance:

.doForEach f => console.log(f.name, f.ext)

or:

var counter = 0
.doForEach f => console.log(counter++)

Or what about another command I personally use a lot in batch renaming things in my file system:

var counter = 0
.renameEach fileName => `[${counter++}] ` + fileName.replace(/bla[012]/, 'blargh') --entType=file

Or what if you combine this with the built-in exec() function (docs down below)? Zip all files in a directory just like that:

.doForEach f => exec(`7za a \"${f.nameBase}.zip\" \"${f.name}\" `)

And it gets even cooler! To iterating commands like these you can add the --deep/-d option, which will make things go recursive to the number of levels specified in config.recursionDepth.
Watch out with this, as things can get ridiculous real quick. Especially when e.g. renaming directories that it then tries to scan items of etc...

Userscripts

A useful feature of Aya is userscripts: sequences of lines to be executed which you can save accross sessions.
Use the userscript commands (see .help) to interact with these.

Useful note: use the scriptFromHistory() global function (docs down below) e.g. like this: .userscript-set scriptFromHistory(1, 4)

Config

There are some config values you can set from the CLI, which will be persisted even when closing and reopening Aya. Use the config commands (see .help) to interact with these.

Explanation of the different config keys:

  • recursionDepth: Set how many layers the --deep versions of iterative commands continue.
  • syntaxHighlighting: Toggle syntax highlighting (because it may impact performance).
  • musicMetadata: Toggle fetching music-related metadata.
  • exifMetadata: Toggle fetching metadata on all kinds of files.
  • alwaysStart: Set to true to have aya always start in the current working directory, so you don't have to specify the -s flag.
  • initScriptsDir: Set this to a directory path for aya to load all scripts in that directory into its context. This allows you to expose custom functions you use a lot.
  • extraScriptsDir: Set this to a directory path, from which you can directly load the JS files using .loadScript. Useful for scripts you only need once in a while.

Available commands

I don't really feel like listing all commands here, so just type .help to get a list of all commands.
If you want to get just a single command's help, use the .helpp command, or add the --help flag to it.

There are a few default NodeJS REPL commands which you may want to be aware of: .break, .clear, .editor, .exit, .load, .save. These probably work as expected but I'm not making any guarantees.

Init args

There are some arguments available to pass to Aya:

  • --start / -s => start Aya without asking for a starting directory
  • If you just throw in some arguments, they'll be parsed as being a userscript:
    • Multiple line splitting with \n or ;;
    • Can reference to commands with or without dot
    • Can reference to userscript with or without .u(serscript) in front
    • Random js code also works as usual
  • --continueAfterCmd / -co => When providing stuff to run on init, Aya will by default close when it's done. Setting this option allows you to continue using it after the command/userscript is done.
  • --dir / -d => set starting directory as a command line arg
  • --help: get the available init flags

Random info about the REPL

  • It is recommended that you use var instead of const/let, because autocompletion only works with the former.
  • Essentially all functions that operate on your local file system are quite smart about resolving paths you pass to them. So e.g. you can do copy('C:\Users\Someone\Documents\bla.txt', 'myProject/random_txts'), in which case it will resolve the first path absolutely and the second path relative to the current CWD that AYA is in.

Available JS globals

Look at aya.global.d.ts for some (probably outdated) docs on the stuff that's available in the global scope of the REPL.

You can also use the type and doc properties on most global functions: e.g. just enter doForEach.type or question.doc. (There's also the secret typeX property, which will substitute type aliases used in the type by their actual definition. e.g. entering doForEach.typeX(2) will go 2 layers deep in doing this substitution)

File metadata

The files passed in doForEach (and other commands) have some 'metadata' on them, which you can use to make decisions.

interface {
  // Dirent
  isFile(): boolean;
  isDirectory(): boolean;
  isBlockDevice(): boolean;
  isCharacterDevice(): boolean;
  isSymbolicLink(): boolean;
  isFIFO(): boolean;
  isSocket(): boolean;
  name: string; // basename with ext
  // Custom metadata
  mm?: IAudioMetadata; // If config.musicMetadata == true
  em?: exif.Tags; // If config.exifMetadata == true
  ext: string;
  nameBase: string; // basename without ext
  path: string;
  dirPath: string;
}

Portable aya setup

It's desireable to be able to give someone who doesn't have AYA installed a portable exe to run aya and init it with a couple scripts you supply. This is how it's done:

  • Grab an aya binary from the releases or build it through yarn compile and grab it from the generated bin folder
  • Package a folder like this:
    • aya.exe (or other binary)
    • Possibly one or more shell/batch scripts that invoke e.g. aya myUserScript()
    • _aya/ folder
      • All JS/TS scripts in this will be auto-loaded at init and exposed as 'extraScriptsDir' to load
      • Optionally config.json to init AYA with a given config
      • Optionally userscripts.json to init AYA with a selection of userscripts

TODO

  • go through todos in code
  • refresh ENV.currentDirItems on more occasions / use in all places where you can use relative paths / implement fancier hash-based recursive system or sth
  • add to readme some gameplay footage
  • allow force quitting a command that's taking a long time
  • add ora fancy spinner thingy on longer running scripts?
  • have some [iter] like (colored?) label in the help of commands that iterate
  • do exe releases every once in a while? (and for macos and debian would need to do in docker container)
  • be able to give argument to userscripts?
  • some system for deep iteration to e.g. rename a folder and then still be able to go through the items in it
  • publish this on NPM so people can easily install it as CLI --globally

About

File system scripting from the comfort of a NodeJS REPL

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages