He's a Friend of Ours | Main | Your Daily Moment of Ed

March 31, 2004

Anything to Stay Out of a Browser Text Box

Posted by Mike on March 31, 2004 1:02 AM

I accidentally opened up the BBEdit "Default Worksheet" stationery today and discovered what a BBEdit worksheet actually is: It's a text buffer that processes shell commands.

So if you've got a command in the worksheet file like:

ls -l

you just press CMD-return and it kicks back the output as if it had been typed in the shell. The sample stationery page offers a bunch of examples, like:

find /usr/include -name "*.h" | grep exception | xargs bbedit

which feeds all the header files in /usr/include that contain the string "exception" into BBEdit for editing.

It was pretty simple to set up a worksheet to utilize mtsend.py as a blogging tool from within BBEdit. CMD-returning on a given line causes the output of the line to appear in the document. Passed through a little sed, the output is munged into another command. The document itself forms a sort of "blog editing pipeline checklist" to play around with.

Two nuisances:

  1. Python's whitespace/indenting requirements make it a real PitA for quick hacking if you're not a Python person anyhow. I have to run some of mtsend's output through a lot of sed munging because my attempts at hacking out the bits I didn't need ended up throwing syntax errors over unexepected indentation. My choice: Learn more python or just go to the CPU expense of passing the output through a familiar tool. sed and cut are my friends, Python is a chilly acquaintance.

  2. (and this is a much bigger nuisance) BBEdit, even though it's running a bash shell within the Worksheet document, doesn't inherit the user's bash environment, meaning that my attempts to stay neat and clean by putting mtsend.py in my own ~/bin were thwarted by BBEdit not understanding that ~/bin is in my $PATH. There's supposed to be a fix for this from Apple but it involves turning my .bashrc into a plist. Apple's document on the matter says "It is actually fairly simple process to set environment variables for processes launched by a specific user," which begs the question of why it doesn't just do that anyhow. If I'm smart enough to modify my .bashrc, I'd like to be trusted with e-z access to my labor without having to reconcile it with a plist.

I put my current blogging worksheet within the extended entry if you're dying of curiosity. Note the ugly need to declare where MTSEND is until such time as I can make OS X just honor my .bashrc (yes, yes, I could put it in /usr/bin and be done with it... I didn't want to).

Oh. And in answer to the question "Why?" Because it seemed like a thing to do.

Here's my current "is this thing on?" worksheet. Pressing CMD-Return on any uncommented line executes that line:

export MTSEND="/Users/mph/bin/mtsend.py"
export BLOG="puddingtime"
export BLOG="blogmarks"
export BLOG="sammich"

# List the five most recent posts from the selected blog
$MTSEND -q -L 5 -a "$BLOG"

#Get latest five from default blog and make them ready for e-z export:
$MTSEND -q -L 5|grep ^\|\ [1-9]|sed s/\|//g |cut -b 1-5,28-|sed s/^\ /export\ POSTID\=\"/g|sed s/\ /\"\ \#/2

# Retrieve the post id and feed it to BBEdit
$MTSEND -q -G $POSTID > $HOME/.reedit && bbedit .reedit

# Repost the contents of POSTID to the blog
cat $HOME/.reedit | $MTSEND -q -E $POSTID && echo "Done."

#Miscellaneous other things and under construction

#List of all available blogs
$MTSEND -B pbowl

Comments

Having run into this stuff with other apps, it certainly seems like they didn't think the design decisions all the way through. Damned if that .plist ain't much more in functionality than autoexec.bat. Those env vars are set in stone until you log out. I find this intensely frustrating.

OTOH, you could also just source your .bashrc in the worksheet and have done with it.

Also, if you start BBEdit from a shell with the command tool, the worksheet gets your whole env.

Posted by: jbm at March 31, 2004 9:31 AM

That was more a Bash issue than an OS X one; if you use the Zsh, which is mostly compatible with bash, you have three initialisation files, ~/.zshenv, ~/.zshrc and ~/.zlogin. The first gets loaded for every zsh, the second for interactive zshes, and the third for login zshes.

Bash only loads ~/.bashrc when it is an interactive shell, which a subprocess in BBedit won't be, normally. A workaround would be to set BASH_ENV to your ~/.bashrc in the PList file; if a non-interactive bash is started with that environment variable set, it will try to source the commands in it.

Posted by: Aidan Kehoe at April 24, 2004 2:46 AM

Thanks, Aidan. But shouldn't bash load .bash_profile (mine sources ~/.bashrc) for non-interactive sessions?

Posted by: mph at April 24, 2004 7:48 AM

Nope. An "interactive session" is one where isatty(fileno(stdin)) is true. A "login session" is one where the first letter of argv[0] is "-", because that's what login(1) traditionally set it to. A "non-interactive session" normally means one where neither of these things are true.

All three kinds of session inherit their environment (the strings getenv() can return). So, if you log in to a remote machine over SSH, start up Emacs, type M-x shell RET, you will have an interactive shell that has inherited a login shell's environment via Emacs. (Type C-h v process-environment RET within Emacs if you want to check.)

If you type M-! env RET you will be launching the env command using a non-interactive shell. (Emacs doesn't fork and exec it directly--instead it fires up a shell to run it, because it wants to allow your shell RC files to be sourced.) This non-interactive shell will again see an environment inherited from a login shell.

However, if you're working locally, BBEdit inherits its environment from /System/Library/CoreServices/LoginWindow.app [as far as I know :-)], and there's no shell involved at all. So, the environment BBEdit has, and the environment inherited by its non-interactive shell children, doesn't reflect the contents of your ~/.bashrc or your ~/.bash_profile.

In summary; if you want options and environment variables to be sourced from ~/.bashrc, for non-interactive, non-login shells, set the BASH_ENV environment variable to something appropriate. :-)

Posted by: Aidan Kehoe at April 25, 2004 6:25 AM