| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
| |
Instead of handling aliases in the recite() function, which requires two
loops to handle properly with the current implementation, offload
checking for aliases to the read() function.
|
|
|
|
|
|
| |
The `which` command is not necessarily a builtin, however, it can
display shell aliases. This patch adds a line into dist/etc/dwvshrc,
which allows /usr/bin/which to detect our shell aliases, and print them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Make sure to interpret alias values as their own poems, since aliases
can be fairly complex.
Notes:
Previously, I was doing a simple find and replace for aliases within
each verse. However, aliases can be fairly complex, containing their own
range of meters, commands, and io operations. This could cause problems,
since a verse should never have, for instance, a pipe (`|`) in the
middle of it. This patch fixes it, so that we iterate once through the
poem, generating a new poem based on aliases that are found. In order to
avoid two loops in the recite() function, it might make sense to offload
handling aliases to read().
|
|
|
|
|
| |
Add documentation for anthology::lookup(), with a list containing all
the default aliases for builtin commands.
|
|
|
|
|
|
| |
Add docstring comments for all the incant function throughout the
anthology, documenting what each function does, and an example of it's
shell command.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously, if an environment variable was given in a string, such as:
'$PATH' or "$PATH", both would be replaced with the value of $PATH from
the environment. However, for single quotes strings, any values inside
should be taken at face value. In other words, echo '$PATH' should
simply write out: $PATH, and not whatever environment value $PATH
happens to be. This patch replaced '$' in single quoted strings with
the ASCII shift out (x0e) character. Any ASCII SO placeholder is
replaced with a '$' in recite(), after the environment variables have
been accounted for.
|
|
|
|
|
| |
Instead of passing a hard-coded value for the prompt, use $PS1. The
default is '|> ', set in dist/etc/dwvshrc.
|
|
|
|
|
|
| |
Replaced all (non-test) instances of env!("HOME") with env::var("HOME").
The env! macro should only be used in instances where the environment
variable should be resolved during compile time.
|
|
|
|
|
| |
Add some better comments/move around existing comments to make some of
the actions in recite() more clear.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch fixes a bug for internal poems, where the output would always
get split on newlines, regardless of the verse's verb. This breaks
things like 'export DIR=`ls`', since output from `ls` might have
newlines, meaning that $DIR will only contains the first item from the
`ls` command. This will only perform the newline split when sending the
output to a non-builtin command.
Notes:
This fix works for export (and alias), but could cause issues with other
builtins in the future. Worth keeping an eye on this, as this probably
isn't a perfect solution.
|
|
|
|
|
| |
Add the 'unset' command to remove global environment variable
definitions from the shell.
|
|
|
|
|
|
|
|
|
|
|
| |
The shell now has support for aliases (via alias foo=bar). The 'unalias'
command is also available to remove aliases. Finally,
Environment::aliases was changed to be a HashMap<String, String>,
instead of a Vec<String>.
Since the verse's verb might change (for instance, it is an environment
variable, or an alias), add another check in Poem::recite, which simply
continues, instead of running the spellchecker, if the verb is empty.
|
|
|
|
| |
Need to include line to import compose::Environment.
|
|
|
|
|
|
|
|
| |
Instead of having to pass around a bunch of different data structures
for various shell functions, create the wrapper compose::Environment,
which serves as a global shell state. It is configured via
login/profile/rc scripts initially, but can of course be modified
throughout the lifetime of the shell.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use $PATH, instead of a hard-coded PATH from main(). This means that
there is no longer a need to pass around PATH to
repl()/recite()/path::refresh(), since path::refresh() can call env::var
directly.
Since the hard-coded paths were removed, there needs to be some way to
define $PATH. When running the debug build, dwvsh will look in
'dist/etc/dwvshrc' for the initial environment setup. For the release
target, dwvsh will look in '/etc/dwvshrc'. After the global rc file is
sourced, dwvsh will try to source ~/.dwvshrc if it exists, so users can
extend their environment without root access (assuming a release install).
Notes:
Throughout a lot of this program, we're calling `env!("HOME")`, in order
to get the user's home directory. Technically, this is not correct. The
env!() macro resolves environment variables during compile time, while
env::var() gets environment variables for the running process (i.e. the
shell). See https://users.rust-lang.org/t/env-vs-env-var/88119 for more
info. In the near future, this will need to be addressed. Might be worth
looking into what other shells do, though one idea I had was to invoke
'/usr/bin/id', grab the user's ID, and use it to grab the rest of the
info from /etc/passwd. This would be handled in an /etc/dwvlogin or
/etc/dwvprofile most likely.
|
|
|
|
|
|
| |
The anthology module was added to run built-in commands. The 'cd' and
'exit' built-ins were moved from the main recite() loop to this module.
Additionally, the 'export' and 'source' built-ins were added.
|
|
|
|
|
| |
The parser will now interpret the '#' character as a single-line comment
string, which works on it's own line, or at the end of an existing line.
|
|
|
|
|
| |
Updated the docs for repl() in main.rs, to include the 'at_prompt'
function parameter.
|
|
|
|
|
| |
Updated the description in Cargo.toml to fix a typo, as well as add a
clarification for the POSIX compliance.
|
|
|
|
|
|
| |
Previously, if a directory could not be read, dwvsh would panic.
Instead of panicking, dwvsh should continue processing the other
directories on the $PATH.
|
|
|
|
|
|
| |
Rename the path::prefresh() function to path::refresh(). Calling
convention should be to `use crate::path;` or `mod path;`, and then call
path::refresh(...), for verbosity.
|
|
|
|
| |
Don't need double quotes if just printing a newline.
|
|
|
|
|
|
| |
Add back tests for Rune::Read, Rune::Write, and Rune::Addendum,
following the new parser output. Also, renames some tests, since Read,
Write, and Addendum are no longer meters.
|
|
|
|
|
| |
Remove some commented out code, that is no longer needed after the
parser overhaul.
|
|
|
|
| |
Add docstring for `incant_quiet_io`.
|
|
|
|
| |
Remove println!() in main that was used for debugging the parser output.
|
|
|
|
|
| |
Fix the ~ test, so that it uses env!("HOME"), instead of my hard-coded
home directory.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Rebuilt the LR parser (i.e. read()) from the ground up. This required
that some changes be made to recite(), in order to accomodate the new
data structures. These data structures were each split out into their
own file, in order to make working with each component a bit easier.
In addition to reworking the parts of the parser already present, some
new features were also added, such as:
- Support for strings (' and ")
- Support for environment variables ($)
- Support for interpreting tild as $HOME (~)
- Support for sub-reading and sub-reciting (`)
Notes:
This is a huge commit that changes almost the entire program (main.rs is
still the same, except for imports). Ideally, huge sweeping changes like
this should not occur on the codebase, but since this is still
pre-alpha, I guess this is acceptable. This is far from the end of
patch set, however, as there is quite a lot of cleanup that needs to be
done. For instance, checking for internal poems and environment
variables should get split out to their own functions/macros. There is
also some defunct code (that's commented out), that is unlikely to be
useful in the future.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Added the following macros:
push!: Creates a Verse from a stanza, taking into account some extra
options (such as the Meter).
push1!: Creates a Verse from a stanza, but also allows looking ahead
by a single character, in order to pattern match certain meters (i.e.
And ('&&') and Addendum ('>>')).
Replaced the code in the huge, redundant match statements in Poem::read
with the macros described above.
|
|
|
|
|
| |
Fixed formatting of macro_export in src/recite/ps.rs to be more
consistent.
|
|
|
|
|
|
|
| |
Added six new units tests related to the IO meters (Read, Write, and
Addendum). The first three tests check the meters under normal operation
, and the last three tests ensures that the parser throws an error,
unless one or more files where specified for the operation.
|
|
|
|
|
| |
Clear the 'out' buffer after we have written STDOUT to the files
specified after the Meter::Write or Meter::Addendum verse.
|
|
|
|
|
|
|
| |
Remove commented code relating to error checks for the incant_io
functions. The parser should detect if no files where specified for
Meter::Read, Meter::Write, or Meter::Addendum, meaning that these checks
are not necessary.
|
|
|
|
|
|
|
|
|
|
|
| |
Added the following file redirection capabilies:
- '<': Read input into STDIN
- '>': Write STDOUT to file
- '>>': Append STDOUT to file
If no files are specified, this counts as a parser error, and so no code
will be executed, even when used in combination with the string (';')
meter. Currently, there is no way to redirect STDERR.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Keep track of a new atomic variable: at_prompt, which is set to true
just before blocking on io::stdin.read_line, and set to false just
calling Poem::read. Additionally, for background tasks, there is a new
ps macro called btask, which changes the process group of commands that
are forked into the background, so that they don't receive SIGINT from
the keyboard.
Notes:
Changing the process group on the Command is done via CommandExt. More
details here:
https://doc.rust-lang.org/std/os/unix/process/trait.CommandExt.html#tymethod.process_group
|
|
|
|
| |
The 'debian-latest' isn't a real runner, so change to 'ubuntu-latest'.
|
|
|
|
|
| |
Add a yaml file to run `cargo check`, `cargo fmt`, and `cargo test`,
every time a branch is pushed, or every time a pull request is made.
|
|
|
|
| |
Added twelve different tests for the parser (Poem::read).
|
|
|
|
|
|
| |
Added a match statement in the main parser loop that pushes a new verse
into the poem if a newline is found. This might happen if parsing a poem
from a file.
|
|
|
|
|
| |
[Verse] is not in scope for the ps module, so removed the link in the
documentation comments.
|
|
|
|
|
| |
Added documentation comments for the recite::ps::task and
recite::ps::ctask macros.
|
|
|
|
|
| |
Added documentation comments for the Meter::incant_ functions,
describing how each function operates.
|
|
|
|
|
|
|
|
|
| |
Added an index to keep track of what position each char is at in the
loop. Added a more verbose error message, which prints out the column
that the parse error was detected, as well as the glyph that threw the
error. Added more comments to the '&', whitespace, and char match
statements. Changed parser behavior, so that a ';' glyph without a
stanza does not cause a parser error.
|
|
|
|
|
|
|
| |
Moved the 'couplet' and 'metered' variables into functions impl'd for
Verse. This cuts down on the boilerplate in the parsing loop, and also
makes it so that their match statements are only ran when needed, rather
than being called at every iteration of the loop.
|
|
|
|
|
|
| |
Introduce a switch to break from recite() if the forked process returns
a non-zero exit code. The one except to this, is when using semicolons,
then we do not care if the previous command failed.
|
|
|
|
|
| |
Reaping is currently handled by a signal handler, so this code is no
longer necessary.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Removes the custom errors in src/recite/erro.rs, and replaces them with
std::io::Errors throughout (recite(), incant_, macros).
Fixed a bug with the way forking to the background is handled, where
registering the signal handler in main for all processes would break
couplets (i.e. pipes). Instead, this sets up a new signal handler each
time a process is forked into the background. It uses a Vec<i32> to keep
track of all the background processes.
Notes:
First off, there is some defunct code in the main repl loop, which is an
example of killing zombie processes after each prompt. This should be
removed, but I kept it in, just in case I go back to it for some reason.
To be honest, I have no clue why this code works. In theory, I should
have to remove the pid from the pids: Vec<i32> if waitpid returns a
positive integer. However, when I tried this, it completely broke the
program. ¯\_(ツ)_/¯
Also, it's worth noting that registering a signal handler with
signal_hook::low_level::register, is somewhat costly, according to their
docs. Given that this only occurs for background processes that are
forked, however, I think it is acceptable.
Finally, we never unregister the signal handler, so I'm not sure if
that's still hanging out in memory somewhere or no.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
First off, moved the giant match statements out of recite(), and into
macros in src/recite/ps.rs. There still needs to be two, since any verse
using the 'couplet' meter will need to redirect its STDOUT. Now the
recite() function returns a Result<(), Mishap>, which can be invoked
when calling the incant_ functions.
Custom errors were added in the form of 'Mishap''s. They are intended to
be returned from the incant_ functions, in the event that something goes
wrong with the Command::spawn() or Child::wait(). They each take a
String, which should be the verb or stanza that was entered by the user.
The incant_ functions separate the functionality of each type of meter
from the recite() function. They return a Result<i32, Mishap>, where
i32 is the exit code of the program that ran, and Mishap is a possible
error.
Before, the shell was cheating at forking a process to the background.
It would actually spawn a thread to wait for that process to finish.
Now, the program simply registers a handler for SIGCHLD, and uses libc's
waitpid() function to reap the child process, and print some output to
the user, indicating that it's finished.
Notes:
This was a huge patch which did some desperately needed cleanup of the
recite() function. Moving forward, will need to add more documentation,
and will probably scrap the custom errors, since this implementation is
a little half-baked. It's worth looking into in the future, but we can
probably live with io::Error's for the time being.
Fixing forking was a pretty big deal, though. In Linux, and other
u**x-like operating systems, parent processes need to reap their child
processes, otherwise they become zombies. Previously, the dwvsh did this
by spawning a separate thread to wait for child processes that were
forked to the background. Now, we are registering a handle for SIGCHLD,
which is a signal that gets sent to the parent when one of their
children finishes, or is killed. Using waitpid(2), we can determine
which process ended, and do something about it. In the case of a
processes that was forked into the background, when it finished,
waitpid(2) will return its PID. For foreground processes, it returns -1.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replaced the 'ctrlc' crate with 'signal-hook' for handling of SIGINT.
The 'signal_hook::low_level::register' function is actually unsafe.
However, according to
https://docs.rs/signal-hook/latest/signal_hook/low_level/fn.register.html,
it is only unsafe in the case of multithreaded applications. There are
some race conditions as well. For instance, it appears that even when we
fork to a child process, SIGINT is captured on both that process, as
well as the shell.
Notes:
The replacement was motivated by the fact that 'ctrlc' appears to use a
separate thread to handle interrupts. This is evident if you run:
ps aux | grep dwvsh
USER PID %CPU %MEM VSZ RSS TTY STAT START COMMAND
user pid 0.0 0.0 71500 3072 term Sl+ 20:08 target/debug/dwvsh
Further reading in 'man ps' under 'PROCESS STATE CODES', reveals that 'l'
is a process state referring to multithreaded applications.
Given the nature of interupts, this seems unnecessary.
The issue where SIGINT is captured by both the shell, and child process
will have to be addressed.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Broke out the structs for a poem into their own file: src/recite.rs.
Also put the 'prefresh' function into it's own file: src/recite/path.rs.
Commented most of the parser code (including structs and helper methods
related to parsing (i.e. Verse, Stanza, Meter, Poem)). Renamed any
instance of the 'paths' variable to 'path'.
Notes:
The biggest task now is to cleanup Poem::recite. It has a ton of bogus
error messages, and (seemingly) redundant code.
|