Skip to content

Latest commit

 

History

History
390 lines (307 loc) · 16.8 KB

e.rst

File metadata and controls

390 lines (307 loc) · 16.8 KB

e - e-nvironment processor

Author: [email protected]
Date: 2013-07-19
Copyright: GPLv2
Version: 0.1
Manual section:1
Manual group:environment handling

SYNOPSIS

$ mkdir -p ~/.e/sh; eval "$(/usr/bin/e init)"

DESCRIPTION

e is an application that helps manage a user's shell environment. This includes shell functions in bash, aliases in cshell and environment variables. It allows environment variables to be grouped into projects. Projects are groups of environment variables that share some sort of user defined commonality. I created because I work on many projects in the course of a day and got tired of updating .<shell>rc files to handle environment variables. Plus, I work on several hosts each with differing projects. e also allows evaluating environment variables to all quick execution of environment stored in e project file. It works with bash, zsh, and csh. For csh, more complex e usage requires specific shell settings. It is great for dynamic interactive shell sessions with many repetitive commands that require a lot of typing. Plus, if you use environment variables with the same names for ease of remembering, e allows switching projects and whole environment variables quickly.

INSTALLATION

  1. mkdir -p $HOME/.e/sh

  2. Download e into /usr/bin/e

  3. in .<shell>rc or .profile:

    • in bash or zsh add a line:

      eval "$(~/.e/e init)"

    • in csh add a line:

      eval "`$HOME/.e/e init`"

USAGE

e has commands that are set up as shell functions (bash, zsh) or aliases (csh) that can be typed at the prompt. Most commands are 2 characters for brevity and speed at the command line. The most important one is eh. eh will show the available e commands available.

Projects:

An e project contains numbered slots starting from 0 going to the number of entries contained in a project. Projects can have upto 100 slots for entries (0-99). But this can be adjusted on a per-project basis.

Projects are managed with the ep [[-c] <name>] command. If <name> is missing, this will list the available projects, and show the current project of the current host with a > in front of the title and in a different color. When <name> is specified, one of two things will happen. If <name> is the name of an existing project, it's environment is loaded into the shell. If <name> is not an existing project, then a new empty project is created.

Projects can be deleted with the erp <name> command. It doesn't really delete the project. It just removes it from the list of available projects. Basically there is a project file with the list of all the slots for that project and it gets renamed so the project list function doesn't see it (them).

Project files are stored in files named: $HOME/.e/sh/<name>.project. When projects are deleted the project name becomes <name>.oldproject. They can be removed with rm if desired. Removed project files will be restored with ep <name> if $HOME/.e/sh/<name>.oldproject exists. It gets renamed with a .project extension when the ep command is executed. Removing a project is a way to hide projects when they are not in use.

Environment variables and slots:

Each slot in a project contains a value and possibly a name. Slots are managed via the es, en, and ev. They useful when a command is evaluated very frequently. There are several other commands for managing several slots discussed below.

The es # <name> <value> store <value> into slot # named <name>. es # creates several shell environment settings. First it creates an $e# variable set to <value>. Then, it creates a command e# that evaluates <value>. It also creates an $<name> variable. If another slot contains <name>, it will be removed and moved to the new slot. Also, a command named <name> will be created or replaced if <name> doesn't conflict with normal e commands. The command is useful for evaluating the <value> in the current shell so commands like cd will work. If both <name> and value are not specified the slot is cleared as well as all the variables and shell commands. If <value> can be detected as a directory, the shell command becomes a cd <value> instead of the actual <value> for conveience.

The en # <name> change <name> of slot #. This is a convience command allowing the setting of just the slot name. If <name> is not specified, it is cleared from the slot.

ev # <value> is a convience command allowing the setting just the slot value.

e also contains per project variables. They can be referenced $e<project-name>_<var>, where var is an actual name of a slot or e# referencing the index. They may be evaluated via e<project-name>_<var> as well.

The environment variables also contain $<name> for each project. If there are multiple projects with $<name> set, they will be loaded alphabetically and overrided by later loaded projects variables. The current project is the last one loaded, so it takes precedence over all other projects. If a specific order is desired, a project name could be prepended with letters in the order desired (e.g. a_project3, b_project2, c_project1). Sometimes I have projects commands or variables referenced in other projects. For example, I have a path project:

$ el path
path                                                  $name
 0: # ------------ PATH ------------                              :0
 1: removepath $*;export PATH=$PATH:$*                $addpath    :1
 2: export PATH=$(echo $PATH|sed -e "s;:$*;;g")       $removepath :2
 3: echo $PATH                                        $p          :3
 4:                                                               :4

This allows me to add or remove PATH entries. In some projects, there are several cross-compilers built and used for different purposes. The path project is used during initialization of a project (described below). For setting/resetting PATH when switching projects or logging in the first time.

Evaluation of e slots:

e builds extra commands allowing the evaluation of the slot values. e# evaluates (executes) the slot value referenced at # in the current shell context. This is a powerful feature allowing creation of often executed commands can be setup in a slot. Not all slots have evaluatable values, but e has no way of knowing. So, it sets up the e# command reguardless. Because it's executed in the current shell context, things like cd will work as expected (which is a large part of how I use it).

e also creates <name> commands referencing the names of slots for convenience. e will not allow <name> to override the normal e commands. The en # command will display an error message if a <name> matches a an reserved e command.

Because e uses the shell's eval builtin, it will only evaluate one or two levels of env variable replacement. If you try more then 2 levels of env variable references in slot values, it may not work correctly. It's a limitation of shell and portability between all the shells supported.

Two special slot names 'init' and 'deinit' will be evaluated when a project is selected (init) or when a another project is selected (deinit). The 'init' will also be evaluated when e is first initialized.

A Slot named 'deinit' requires special care. If any slots are referenced, they need to be e<proj>_<name-or-e#> because of when e evaluates expressions. When an 'ep <proj>' is evaluated, several evaluations occur. Because the 'deinit' will be evaluated after the project has already been changed, the e<proj>_<name-or-e#> must be used. Otherwise, the 'deinit' will evaluate the new project's 'deinit' instead.

Other slot management commands:

The command 'el [<project>]' will list the <project> slots. If <project> is not specified, 'el' will list the current project. The listing shows the slot number, the value, and the name for each slot. The name is shown right justified as '($<name>)'.

'em' command shows the slots that have names. One slot per line is displayed with the format $<name>,<value>. This is useful to pipe to a command or see just the current name to value mapping. If '-a' is passed as an argument, this command will show all env variables from all projects that are exported.

'ex <from> <to>' exchanges slot <from> value and name with <to> value and name. It is primarily used for convenience.

'eu [<num>]' rotates the slots up <num> positions (default 1) wrapping the slots from slot 0 to the maximum slot entries.

'ed [<num>]' rotates the slots down <num> positions (default 1) wrapping from slot 0 to the maximum slot entries.

Miscellaneous commands:

'ei' reinitializes all e commands, env variables from the current shell.

'eq' removes all e commands, env variables from the current shell.

'eh' again shows the normal e commands available.

NOTE: the project files store slots one per line with the value separated
by a ','. When setting the value or name of a slot, they should not contain a ','. This will corrupt e handling of slots and the project file may have to be edited by hand or removed altogether.

EXAMPLE

Suppose we are working on 3 machines: 'larry', 'moe', and 'curly'. We are working on a project 'stooges'. 'stooges' has a directory $HOME/proj/stooges. Under the 'stooges' directory are directories: 'include', 'src', and 'doc'.

This is how I would setup my e project (under bash):

line ($ <text> is shell prompt and text to execute)
1   $ ep -c stooges
2   $ ev 20 # --- directories ---
3   $ ev 21 $HOME/proj/stooges
4   $ en 21 stooges
5   $ es 22 '$stooges/include'
6   $ en 22 include
7   $ es 23 src '$stooges/src'
8   $ es 24 doc '$stooges/doc'
9   $ ev 25 # --- ssh hosts ---
10  $ es 26 larray larry.domain.com
11  $ es 27 moe moe.otherdomain.com
12  $ es 28 curly curly.thirddomain.com

Line by line explanation:

1 - Create a e project called 'stooges'.

2 - Create an e env var at slot 20 containing '--- directories ---'.
This is just used as a comment for slots 21-24. This is helpful so when listing the e project, sections can have separators. There will be an env var $e20 set to '--- directories ---'.
3 - Create an e env var at slot 21 containing $HOME/proj/stooges.
This slot it's probably not as important but the next ones are. There will be an env var $e21 set to $HOME/proj/stooges. It also creates a shell command e21, though it will cause a shell error. It's probably not useful for this entry, but other values can be set to probably shell syntax and allow them to be executed. There are no "'" around the slot so $HOME gets replace before entered into the slot because e has limits to the number of env vars levels that can be replaced during evaluation.
4 - Name slot 21 to 'stooges'. This command also creates $stooges
with the slot value set in line 3.
5 - Create an e env var at slot 22 containing '$stooges/include'. Now
the quotes are important so env var can be evaluated in the shell properly. Plus, if slot 21 (named stooges) changes, this slot will not have to be changed.
6 - Name slot 22 to 'include'. The shell now has an env var $include.
This can be used in interactive commands as well as shell functions.
7-8 - This sets up slots 23 and 24 with names 'src' and 'doc' similar
to steps 5 and 6.

9 - Create another comment slot for ssh hosts the same as step 2.

10-12 - Setup other slots for the ssh hosts.

All the entries created above will be used for environment variables. Now, let's create slots that will be used for execution of commands. I like to keep slots 0-9 for quick command evaluation because they are 2 character commands and can be typed quickly. I often change slot 0 for the most often executed command for the current session. This command can be evaluated with a single keystroke 'e'.

line (# <text> is shell prompt and text to execute):

1  $ es5 'ssh $moe'
2  $ en5 smoe
3  $ ev6 slarray 'ssh $larry'
4  $ ev7 scurly 'ssh $curly'
5  $ es1 'cd $include'
6  $ en1 cin
7  $ ev2 csrc 'cd $src'
9  $ ev3 cdoc 'cd $doc'

Line by line explanation:

1-4 Setup ssh commands with names matching the host names with a
leading 's' prepended. The names aren't really required, they are used as an example. You can use them by typing 'eval $smoe' or 'esmoe' at the shell prompt. But it's much faster to just type 'e5'. What's nice is you can use any of the commands to your reference.
5-9 Setup cd commands with names matching the stored directory names
with a leading 'c' prepended. Just like the ssh commands described above, there are several ways to 'cd' to the directories: 'eval $cin', 'cin', or 'e1'. Take your pick.

These created commands can also take parameters from the command line which makes it very configurable. For example:

$ smoe ls proj

will ssh to moe and run 'ls proj'. It just appends the arguments onto the command before execution.

Lets look at other e commands:

If 'el' is executed the output is colorized and looks like:

line (# <text> is shell prompt and text to execute):

1  # el
stooges:
 0:                                                               :0
 1: cd $include                                       $cin        :1
 2: cd $src                                           $csrc       :2
 3: cd $doc                                           $cdoc       :3
 4:                                                               :4
 5: ssh $moe                                          $smoe       :5
 6: ssh $larry                                        $slarry     :6
 7: ssh $curly                                        $scurly     :7
 8:                                                               :8
 9:                                                               :9
10:                                                               :10
11:                                                               :11
12:                                                               :12
13:                                                               :13
14:                                                               :14
15:                                                               :15
16:                                                               :16
17:                                                               :17
18:                                                               :18
19:                                                               :19
20: --- directories ---                                           :20
21: /home/msg/proj/stooges                            $stooges    :21
22: $stooges/include                                  $include    :22
23: $stooges/src                                      $src        :23
24: $stooges/doc                                      $doc        :24
25: --- ssh hosts ---                                             :25
26: larry.domain.com                                  $larry      :26
27: moe.otherdomain.com                               $moe        :27
28: curly.thirddomain.com                             $curly      :28
29:                                                               :29

ADVANCED USAGE

More complex argument handling can be done but it will be more shell specific as bash and zsh use shell functions and csh uses aliases for handling of e commands. NOTE: if zsh is being used, the zsh option 'globsubst' should be disabled before attempting these examples. There may better ways to handle these situations but I haven't solved them yet.

As an example, lets create a command 'echo 1 <args> 3' to see how to pass arguments in different order:

For bash and zsh:

$ ev 0 'echo 1 $* 3'

It's relatively simple because the who expression is single quoted. When e command is evaluated with 'e0 <args>' the '$*' will be replaced with <args>.

Now, for csh:

$ ev 0 'echo 1 \\\!* 3'

The way arguments are substituted makes these operations tricky. The shells will interpret them different ways. The csh '\!*' was the only way I could get it to work correctly because all the e commands are aliases using the 'eval' builtin. These types of situations are rare but come up occasionally. Just make sure the '\!*' has exactly 3 ''s.

Sometimes I like to create an indirection where one slot value is used as a reference to another.