• Posts
  • RSS
  • ◂◂RSS
  • Contact

  • fix_path.py

    October 6th, 2008
    fix_path, programming, shell  [html]
    Working several hours a day on the command line now, I've gotten interested in what I can do with the command prompt itself. For a long time, my command prompt looked like:
    user@host /path/to/cwd $
    This was quite serviceable, though when deep into a directory hierarchy (especially one laid out by a windows user) /path/to/cwd might be more like a three line monster.

    Fixing this, though, isn't too hard. I've made several environment variables already that correspond to common places I want to go to. Because cd $FOO_SRC is way nicer than cd ~/code/current/foo/foo-1.2.4-rcA/src/. So why not make the command prompt know about this? So we could do:

    user@host ~ $ cd $FOO_SRC
    user@host $FOO_SRC $
    So I write a little python program, fix_prompt.py:
               import sys
               import os
    
               # if it happens to match but it really short, ignore it as
               # its probably not what we want
               IGNORE_LENGTH=10
    
               # these variables contain paths that would make little
               # sense to abbreviate to (except HOME, where we just want
               # to deal with it nicer)
               IGNORE_VARS=["PWD", "HOME", "OLDPWD"]
    
               # in order to still show home as ~ and /home/user as ~user
               # we need to have some special logic.  If you wanted a dir
               # /foobar to show up as the dir %, then you could add an
               # entry for that here.
               SPECIAL_REPLACEMENTS=[["/home/" + os.environ["USER"], "~"],
                                     ["/home/", "~"]]
    
               # we want to sort a pair of lists by the lengths of their
               # first elements, so we need a comparator function
               def longest_a_first_comp(x,y):
                   return len(y[0])-len(x[0])
    
               in_path = sys.argv[1] if sys.argv[1:] else ""
    
               # get all the environment variables, reversed in mapping so
               # we can do reverse variable expansion. Or is it
               # variable condension?  variable condensation?
               env = [[v,k] for k,v in os.environ.items()]
    
               # sort them by length.  This is so if we have:
               #    $FOO_SRC="/home/user/src/foo"
               #    $SRCS="/home/user/src"
               # we will take the longer one.  I think this is always what
               # a user wants.
               env.sort(longest_a_first_comp)
    
               for r in env:
                   # the substitution only happens if it would shorten the path
                   if in_path.startswith(r[0]) \
                          and r[1] not in IGNORE_VARS\
                          and len(r[0]) > IGNORE_LENGTH\
                          and len(r[1]) < len(r[0]):
                       # prefix with a dollar sign so it looks like an
                       # environment variable.  The dollar sign needs to
                       # be escaped, and it's escape needs to be escaped.
                       print "\\$" + in_path.replace(r[0], r[1], 1)
                       sys.exit(0)
    
               for r in SPECIAL_REPLACEMENTS:
                   if in_path.startswith(r[0]):
                       print in_path.replace(r[0], r[1], 1)
                       sys.exit(0)
    
               # if we didn't do any condensations, yield the original path
               print in_path
         
    Then I tell bash to call it, in ~/.bashrc:
               PS1="\u@\h \w $ "
               promptFunc() {
                   PS1="${COLOR_GREEN_BOLD}\u@\h"
                   PS1="${PS1}${COLOR_BLUE_BOLD}"
                   PS1="${PS1}$(python ~/bin/fix_path.py $(pwd)) $"
               }
    
               if [ $(whoami) == "myusername" ]
               then
                   PROMPT_COMMAND=promptFunc
               else
                   # so if someone does an "su" at my terminal its really obvious
                   unset PROMPT_COMMAND
               fi
         
    Someday I may be on a slow machine that can't run python snappily like I want. Then I'll rewrite in C. Shouldn't be too bad.

    One thing that surprises me about this is that I've not been able to find anyone else doing it online. Maybe I'm not calling it the right thing. "Path shortening"? "Path condensing"? The closest I found was some people putting in elipsies in the middle of things. It's sort of a reverse expansion of an environment variable.

    Now if only "shopt -s cdable_vars" would let me do tab completion on them.

    Comment via: facebook

    Recent posts on blogs I like:

    Fireside Friday, November 27, 2020

    Hey folks! Fireside this week. A bit of a change-up in terms of the coming attractions. I had planned to start “Textiles, How Did They Make It?” next, but I want to do a bit more reading on some of the initial stages of textile production (that is, the pr…

    via A Collection of Unmitigated Pedantry November 27, 2020

    Building Depth and Window Space

    How much window space does an apartment need, relative to its area, and how does this affect building style? A fascinating post from about a year ago on Urban Kchoze makes the argument that modern North American buildings are too deep – Simon calls them o…

    via Pedestrian Observations November 27, 2020

    Thoughts you mightn't have thunk about remote meetings

    Welcome to this week's edition of "building a startup in 2020," in which all your meetings are suddenly remote, and you probably weren't prepared for it. I know I wasn't. We started a "fully remote" company back in 2019, but …

    via apenwarr November 23, 2020

    more     (via openring)


  • Posts
  • RSS
  • ◂◂RSS
  • Contact