Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Monday, August 3, 2009

Shortening bash prompts inside a virtualenv

This post will describe a way to shorten your bash prompt in Linux so that inside the inevitable multiple directories caused by using virtualenv, you can still have a small prompt.

I wanted to take an existing library and split it into it's own library. On my computer, I was going to work wit this library at ~/projects/sc/kespa_scrape.

Of course, that kespa_scrape directory is actually the directory holding the virtual_env...


kespa_scrape/
|-- bin
| |-- activate
| |-- activate_this.py
| |-- easy_install
| |-- easy_install-2.6
| |-- nosetests
| |-- nosetests-2.6
| |-- python
| |-- testall.sh
| `-- to3.sh
|-- include
| `-- python2.6 -> /usr/include/python2.6
|-- kespa_scrape
| `-- kespa_scrape
`-- lib
`-- python2.6


This is what the kespa_scrape directory looks like. You can see it has a kespa_scrape directory inside it as well. This directory is the root to the actual project. This directory will probably also have a kespa_scrape directory which would be the actual library package directory. Obviously, there is redundancy, but it's necessary redundancy to keep all the parts where I want them.

Some people complain about virtualenv because then you need to cd through a whole bunch of directories to start working. I make this easier with a script. This is how it is used...


gobo@gobo:~$ cd projects/sc/
gobo@gobo:~/projects/sc$ activate_project kespa_scrape
(kespa_scrape)gobo@gobo:~/projects/sc/kespa_scrape/kespa_scrape$


As you can see, I change to the directory where the project is, enter "activate_project", and it will put me into the virtual environment as well as change to the root directory of the project.

The problem I still had with this is that now my prompt is huge. I would typically change directories once more into the next kespa_scrape package, and with a large enough library name, have a prompt that easily took up half the screen.

At first, I made sure to choose short library names, but now I've come up with a better solution. It rewrites the bash prompt to replace the virtual environment directory with two tildes, and looks like this...


gobo@gobo:~$ cd projects/sc
gobo@gobo:~/projects/sc$ activate_project kespa_scrape
(kespa_scrape)gobo@gobo:~~$


Check out the difference for yourself...


(kespa_scrape)gobo@gobo:~/projects/sc/kespa_scrape/kespa_scrape$
(kespa_scrape)gobo@gobo:~~$


Here's the full script...


#!/bin/bash

# Remove possible slash at end.
DIR=${1%/}

ACTIVATE_FILE=$1/bin/activate

if [ -z "$DIR" ]; then
echo "usage: $0 directory"
return 1
fi

if [ ! -d "$DIR" ]; then
echo "Directory not found: $DIR"
return 1
fi

if [ ! -d "$DIR/$DIR" ]; then
echo "Child directory not found: $DIR/$DIR"
return 1
fi

if [ ! -e "$DIR/bin/activate" ]; then
echo "Activate file not found. Are you sure this is a virtualenv directory?"
return 1
fi


cd $DIR
source bin/activate
cd $DIR

CUR_DIR_CMD='pwd | sed -e '\''s!'$VIRTUAL_ENV/$DIR'!~~!g'\'' | sed -e '\''s!'$HOME'!~!g'\'
PS1=${PS1//\\w/$\($CUR_DIR_CMD\)}

alias cdp='cd '$VIRTUAL_ENV/$DIR


After checking to make sure all the files exist, it sets a variable called CUR_DIR_CMD. This is basically a variable that contains a bash command to take the current directory, and replace any instances of the virtual directory with ~~. Since virtualenv sets the VIRTUAL_ENV variable, it basically looks for "/projects/sc/kespa_scrape/kespa_scrape" and replaces it with ~~. It will also take the result of that and replace instances of the home directory with ~. This is so that if I change directories to something outside of the virtualenv, I can still have '~' instead of '/home/gobo'

Next, I need to replace all instances of \w in the prompt string with this expression. \w is the special string you'd use when setting your bash prompt to give you the full directory that you're in. Replacing it with my custom command allows me to replace the area where the directory should go with what I want, but leave the rest of the prompt (including virtualenv's addition to the beginning) intact.

The entire process also does pretty well when you change directories to outside the virtualenv, since you're just left with the directory...


(kespa_scrape)gobo@gobo:~~$ cd
(kespa_scrape)gobo@gobo:~$ cd projects/
(kespa_scrape)gobo@gobo:~/projects$


The only thing I want to fix up on it is to allow activate_project to work from ANY directory. Currently, it assumes that the project directory is right in front of you. This is good enough for now though.

----

Edit: Feb 18, 2010

Also, one thing to keep in mind, for those who don't really deal much with bash scripts, is that typically when you launch a script the script runs inside it's own shell, and when it completes, the shell closes. This means you lose things such as the new alias or the changes to the directory. So, you can't run the script in any of these ways:


sh /home/mark/bin/activate_project project_name
/home/mark/bin/activate_project project_name


If you did this, the script would run, but you would not see anything changed, since all the changes would be done in the shell created for the script, which exits without changing the shell that ran the script. To ensure that you run the script on the shell you run the script with, you need to use the source or dot operator.


. /home/mark/bin/activate_project project_name
source /home/mark/bin/activate_project project_name


As a side note, now you really know what that source bin/activate line does! Anyway, you don't want to deal with this hassle, so set up an alias...


alias activate_project="source /home/mark/bin/activate_project"

Saturday, June 20, 2009

Changing console keyboard layout under Ubuntu

Here's my contribution to the "where's the file located" pool of googleable blog post.

If you look for where to change keyboard mappings for Ubuntu, you'll find answers related to xmodmap or something in the gnome taskbar. I'm working on a computer where I installed Ubuntu server edition, and want to change things on the console (no X here).

In the past, the distribution stored it under /usr/share/keymaps, and I could quickly switch my capslock and escape keys like a good little vim user. In Ubuntu, this directory was nowhere to be found. However, I did find that the important file was located under /etc/console/boottime.kmap.gz. Standard "be careful/make backups" disclaimers apply.

Wednesday, June 10, 2009

Connecting from virtualbox guest to host

Seems simple enough, but I'm not sure why it took me so long to figure it out. I thought it would be a complex thing.

While making a website, using paste or just some small script, I can start up a test web server, and access the website I'm working on by going to localhost on port 8000..

http://localhost:8000/

I also wanted to connect to this using my virtualbox guest images (three of them, each having a different version of Interent Explorer), but obviously on those computers, localhost is local to Windows XP, and the test server is on the Linux box. Up until now, I just worked around this issue by putting them on another computer on my home network. But obviously this didn't work if I was away from home...

Virtualbox uses natting by default, so my Linux host was sort of working like a router. Thus, the answer was to do the same thing if you wanted to connect to a router: use the gateway address.

So, in my case, the gateway address for the Windows guest network interface was 10.0.2.2, so I could connect to the local computer using...

http://10.0.2.2:8000/

Thursday, May 28, 2009

Blocking facebook (but not pidgin-facebookchat) with iptables

I wanted to be able to have an iptable rule to block me from using the internet (as part of a script I wrote to keep my nose to the grindstone) with a few exceptions. One was irc chats, as they're useful and don't really take up much time. The second is facebook chats. My script limits me to a certain amount of time with full internet access, and I found it annoying to constantly turn it on and off to see if my girlfriend was home from work yet.

Using the pidgin facebook plugin, I'm able to chat on facebook without the browser, but since the plugin uses http anyway, it will still be blocked. The trick that I'm using is that the User agent used by the facebook plugin is Opera, whereas I use firefox. So, I changed my iptables rule to match the user agent as well as the destination port.


iptables -A OUTPUT --protocol tcp --dport 80
-m string --string "User-Agent: Mozilla" --algo=kmp
-j REJECT


This rule will block me from going to facebook when I've turned off access to the internet, but still allow me to chat.

Wednesday, May 27, 2009

Dynamic screen setup of switchable graphics in Linux using Fluxbox

First post, I'll keep it easy :)

The T400 has switchable graphics, so I can set to use the integrated Intel card or the discrete ATI card in the BIOS. Unfortunately, the wiring is such that only by using the ATI card can I recognize both the VGA and DVI outputs on the docking station, so if I want to go dual-screen I need to make sure to switch over to ATI.

Using the idea that I saw on a site by Ariel Vardi (with the idea attributed to John Lathouwers), I added a few lines in my ~/.fluxbox/startup file to use the correct xrandr command for dual-screen (I don't deal with the xorg.conf file itself, which is how John did it).

Fluxbox also makes it very simple to set up how windows should appear through the ~/.fluxbox/apps file. Here you can match windows to use certain specifications, such as their dimensions, if they're stickied, minimized/maximized, workspace, etc. Fluxbox has support for multi-head displays, so there's even an option for what head to display it on.

Now, typically, my setup looks like this: I have firefox maximized and stickied on the right monitor, with key bindings for 11 different workspaces. Typically, each workspace just has one window on it, so switching between applications is really a matter of switching between workspaces. So, my ~/.fluxbox/apps file looks like this for firefox:

[app] (name=Navigator) (class=Firefox) (role=browser)
[Head]> {2}
[Position]> (UPPERLEFT)>{241 27}
[Sticky]> {yes}
[Maximized]> {yes}
[end]


The important parts here is that it's on the second head, and stickied. Unfortunately, this does not work when I'm not at home. My laptop no longer has two screens, so I typically just use one of my workspaces for firefox. The apps entry would look like this:

[app] (name=Navigator) (class=Firefox) (role=browser)
[Head]> {1}
[Position]> (UPPERLEFT)>{241 27}
[Maximized]> {yes}
[Workspace]> {4}
[end]


Note that it is not longer stickied, but instead put in a defined workspace. Now, how to make sure that the correct entry is used?

For this, I created a new directory in ~/.fluxbox called "templates"...

templates
`-- apps
`-- base
`-- one_head
`-- two_heads


Here, I have three files that use the "app" format. "base" will contain all the entries that I use whether I'm on one head or two, and the other two will contain the entries specific for one or two heads.

Now at fluxbox startup, I make sure to concatenate base with the the correct head-specific script, and store the results as the true ~/.fluxbox/apps file. Of course, this means that any changes done on the fly that are written to the apps file are overwritten, but I don't typically use that feature often.

This process takes place in the startup file, using the same check as the xrandr script. The final results are below:


VIDEO=`/usr/bin/lspci | grep -c ATI`
DIR='/home/gobo/.fluxbox/'
T_DIR=$DIR'templates/'

if [ "$VIDEO" = 1 ]; then
xrandr --output LVDS --off --output VGA-0 --mode 0x69 --crtc 0 --output DVI-0 --mode 0x4f --crtc 1 --right-of VGA-0
FILE='two_heads'
else
xrandr --output LVDS --auto
FILE='one_head'
fi

cat $T_DIR"apps/base" $T_DIR"apps/"$FILE > $DIR"apps"