Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
208 lines (156 sloc) 6.75 KB

Automatic proxy settings for Elvish

Manipulation of proxy-related environment variables (including auto-setting/unsetting based on a user-defined test) for Elvish.

This file is written in literate programming style, to make it easy to explain. See proxy.elv for the generated file.

Table of Contents

Usage

Install the elvish-modules package using epm:

use epm
epm:install github.com/zzamboni/elvish-modules

In your rc.elv, load this module:

use github.com/zzamboni/elvish-modules/proxy

Set your default proxy host (including port number) by assigning it to the $proxy:host variable. For example:

proxy:host = "proxy.corpnet.com:8079"

You can now manually set/unset the proxy environment variables by calling proxy:set and proxy:unset, respectively.

For now only the http_proxy and https_proxy environment variables are set.

If you want to enable automatic proxy switching, you need to define a check function and assign it to the $proxy:test variable. It should be a lambda which receives no arguments, and returns a true/false value. When the function returns true, the proxy will be set. For example, the following function will set the proxy whenever /etc/resolv.conf contains any search or domain definitions ending in “corpnet.com”:

proxy:test = { and ?(test -f /etc/resolv.conf) ?(egrep -q '^(search|domain).*corpnet.com' /etc/resolv.conf) }

If you want to temporarily disable the proxy auto-set function in the current session after having defined a test function, you can run the proxy:disable command. Use proxy:enable to reenable it when needed. Note that proxy:disable also unsets the proxy variables.

Implementation

Libraries

We use the prompt-hooks library to set up the hooks for the auto-set feature.

use ./prompt-hooks

Configuration

The $proxy:host variable contains the proxy host to used by default, in “http://host:port” format.

host = ""

$proxy:test contains the auto-set test function. It must be either $false (to disable auto-setting) or a lambda which receives no arguments, and return a true value (anything except $false or an error, as per Elvish’s booleanly interpretation of values) when the proxy needs to be automatically set, false otherwise.

To enable auto-setting you must override it with code that performs a meaningful check for your needs.

test = $false

Whether to print notifications when setting/unsetting the proxy.

notify = $true

Whether autoset should be disabled (useful for temporarily stopping the automatic proxy setting using proxy:disable).

disable-autoset = $false

The list of environment variables to set. By default only http_proxy and https_proxy are set.

env-vars = [ http_proxy https_proxy ]

Functions

Elvish does not include an eval function, but we emulate one using the -source command. We use this to dynamically query and set the variables according to the contents of $proxy:env-vars.

fn eval [str]{
  tmpf = (mktemp)
  echo $str > $tmpf
  -source $tmpf
  rm -f $tmpf
}

Check whether the proxy is set. We use the first variable in $proxy:env-vars for the check, with the assumption that the other variables follow. The need to dynamically determine which variable to check makes this function a bit tricky - basically we create a temporary file (using the mktemp command), and then evaluate code that removes the file if the proxy variable is unset - then the existence of the file indicates the setting of the variable.

fn is-set {
  -tmp-file = (mktemp)
  eval "if (eq $E:"(take 1 $env-vars)" '') { rm "$-tmp-file" }"
  -res = (bool ?(test -f $-tmp-file))
  rm -f $-tmp-file
  put $-res
}

Set the proxy variables to the given string. If no parameters are given but $proxy:host is set, then its value is used. Note that passing an argument to this function does not set $param:host, this needs to be done explicitly if you want it.

fn set [@param]{
  proxyhost = $host
  if (> (count $param) 0) {
    proxyhost = $param[0]
  }
  if (not-eq $proxyhost "") {
    eval (each [var]{ put "E:"$var" = "$host } $env-vars | joins "; ")
  }
}

Unset the proxy variables.

fn unset {
  eval (each [var]{ put "del E:"$var } $env-vars | joins "; ")
}

Disable auto-set and unset the proxy.

fn disable {
  disable-autoset = $true
  unset
}

Enable auto-set after it had been disabled using proxy:disable-autoset.

fn enable {
  disable-autoset = $false
}

This is the function that powers the auto-set feature. It runs $proxy:test and sets/unsets the variables depending on the result.

fn autoset [@_]{
  if (or (not $test) $disable-autoset) {
    return
  }
  if ($test) {
    if (and $host (not (eq $host ""))) {
      if (and $notify (not (is-set))) {
        echo (styled "Setting proxy "$host blue) > /dev/tty
      }
      set
    } else {
      fail "You need to set $proxy:host to the proxy to use"
    }
  } else {
    if (and $notify (is-set)) {
      echo (styled "Unsetting proxy" blue) > /dev/tty
    }
    unset
  }
}

The proxy:init function adds the proxy:autoset function to both the before- and after-command hooks.

fn init {
  prompt-hooks:add-before-readline $autoset~
  prompt-hooks:add-after-readline $autoset~
}

We call init automatically on module load.

init