Here are some details about how I use VIM with CSCOPE and CTAGS to navigate a codebase.

I keep all my different codebases/repositories in ~/repos/ – I then have a bash script (called “workon”, kept in ~/bin/workon) that is used to jump into a codebase and set up some environment variables. Edit the WORKSPACEROOT definition in the workon file if your repos live somewhere else.

Since “workon” modifies env vars in your current shell, you have to use it with the source command, like this:

$ source workon somecodebase

Since cscope and ctags need to store their database files somewhere, I chose to keep them in ~/scopetags/ so make a scopetags directory in your home directory first. After you’ve run the “source workon somecodebase” command to set up your env vars, run the “regen_cscope_ctags” bash script to analyze the selected codebase and store the database files in ~/scopetags/. Run this script whenever you want to update the database, so do it after you make changes or git fetch a bunch of new code.

Then, we need to tell vim how to interact with cscope/ctags. Edit the file ~/.vimrc and add this line to the end:

let &tags=$CTAGS_DB

Then, make a new directory ~/.vim/plugin/ and download this file into that plugin directory: http://cscope.sourceforge.net/cscope_maps.vim

Now, once you do the “source workon” you can open vim and use the ctags or cscope shortcuts to navigate the codebase. Here are the most common things to do.

Put the cursor inside a variable or function name. Press ctrl + \ + a letter code:

  • g = goto definition of that variable/function
  • s = search for all uses of that variable/function
  • c = callers of that function

This will usually open a little menu where you can pick from a list of all the search results.

Press ctrl + t to jump back.

You can also use ctrl + \ + f to search for a filename under your cursor (great for #include “foobar.h” lines).

You can also use vim commands to do searches, when your search term isn’t under your cursor:

Use CTAGS to search for a variable/function/file/etc – You can use tab-complete here.
:ts searchterm

Use CSCOPE to find the defintion/callers/uses/files (same letter codes as above)

:cs f g somevariable
:cs f c somefunction
:cs f s something
:cs f f somefilename

Hope that helps!


~/bin/workon

#!/bin/bash
#vi:syntax=sh

# This script must be sourced
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    echo "You should source this script instead of calling it."
    exit 1
fi

WORKSPACEROOT=$HOME/repos

if [[ $# -ne 1 || ! -d "$WORKSPACEROOT/$1" ]]; then
    echo "Usage: source workon workspace"
    echo "Available workspaces:"
    ls -1 $WORKSPACEROOT
fi

export WORKSPACE=$1
export WORKSPACEDIR=$WORKSPACEROOT/$WORKSPACE

# for vim:
SCOPETAGSDIR=$HOME/scopetags/$WORKSPACE
export CSCOPE_DB=$SCOPETAGSDIR/cscope.out
export CTAGS_DB=$SCOPETAGSDIR/tags

cd $WORKSPACEDIR

~/bin/regen_cscope_ctags

#!/bin/bash
#vi:syntax=sh

if [ -z "$WORKSPACEDIR" ]; then
    echo "Need to \"source workon $workspace\" first..."
    exit 1
fi

SCOPETAGSDIR=$HOME/scopetags/$WORKSPACE
if [[ ! -d $SCOPETAGSDIR ]]; then
    mkdir -p $SCOPETAGSDIR
fi
cd $SCOPETAGSDIR
INDEXFILES=$SCOPETAGSDIR/files

find -H $WORKSPACEDIR -name '*.c' -o -name '*.h' -o -name '*.a' > $INDEXFILES

echo "Generating cscope files..."
cscope -i$INDEXFILES -b -q
# -b            Build the cross-reference only.
# -q            Enable fast symbol lookup via an inverted index.


echo "Generating ctags files..."
ctags -L $INDEXFILES --extra=+f
# -L            Read the list of file names from the specified file.
# --extra=+f    Also include entries for base filename.

FYI, if you’re trying to use android adb (or some tool that uses adb, like helium backup), once you trigger the backup process from the computer, it should open a dialog on your phone. The dialog will ask you to confirm the backup process, and asks for your backup password, and a password to use to encrypt the backups (they can be the same password). Then there are two buttons at the bottom, notably “Back up my data”, which is the one to press to continue.

The most-recent time I tried to do this, I was unable to press the “Back up my data” button. Someone online pointed out that screen-overlay apps (like the Twilight app that makes your screen dimmer and more reddish after sunset [to help with sleep]) will interfere with this button. After pausing my Twilight app, it started working.

It’d be really nice if there was some sort of notification that this particular button is special and is unclickable if you have a screen overlap app :-p

I recently reinstalled my Ubuntu server (16.04 LTS) and wanted to set up the customary unix mail handing stuff so that my cron, temperature monitoring, and hard drive monitor scripts could automatically email me of anything went wrong. In the past I’ve used mandrill and sparkpost for this, but free services like these keep getting more and more difficult and persnickety to use, most-recently demanding things like opt-out/unsubscribe links in the emails and adding a privacy policy to the website (despite there not actually _being_ any website). So I wanted to see if it was easy to send email via Gmail’s SMTP interface.

I followed two nearly-identical guides:

  • http://www.havetheknowhow.com/Configure-the-server/Install-ssmtp.html
  • https://help.ubuntu.com/community/EmailAlerts

Basically, you need to install the ssmtp package, then edit the ssmtp.conf configuration file:

sudo apt-get install ssmtp

# Config file for sSMTP sendmail
#
# The person who gets all mail for userids < 1000
# Make this empty to disable rewriting.
#root=postmaster
root=MyEmailAddress@gmail.com

# The place where the mail goes. The actual machine name is required no
# MX records are consulted. Commonly mailhosts are named mail.domain.com
#mailhub=mail
mailhub=smtp.gmail.com:587

AuthUser=MyEmailAddress@gmail.com
AuthPass=MyPassword
UseTLS=YES
UseSTARTTLS=YES

# Where will the mail seem to come from?
#rewriteDomain=
rewriteDomain=gmail.com

# The full hostname
#hostname=MyMediaServer.home
hostname=MyEmailAddress@gmail.com

# Are users allowed to set their own From: address?
# YES - Allow the user to specify their own From: address
# NO - Use the system generated From: address
FromLineOverride=YES

If you have two-factor (2FA) authentication set up for your Google account, you need to create an "app password" for this "device". Visit this page to create an app password that doesn't use 2FA auth: https://myaccount.google.com/apppasswords

However, there is a problem with those two guides, specifically in the hostname= line. If you put your actual email address as the hostname entry, then google will complain when you try to connect. You can use this test command to see what is going on:

$ echo "Hello 1" | sudo ssmtp -vvv someone@example.org
[< -] 220 smtp.gmail.com ESMTP j76sm1853421ioi.14 - gsmtp
[->] EHLO MyEmailAddress@gmail.com
[< -] 501 5.5.4  https://support.google.com/mail/?p=helo j76sm1853421ioi.14 - gsmtp
ssmtp: Cannot open smtp.gmail.com:587

What you need to do is to set hostname=localhost in the ssmtp.conf file. Then it should work fine.

From a new page on my non-blog website (https://www.mbeckler.org/textures/):

Around 2010 my backup hard drive started to fail. The filesystem became corrupted and unrecoverable. I used a tool called PhotoRec that would search through the raw blocks of a hard drive, looking for the “magic numbers” at the start of common media files like JPG files. Those files, without their filesystem information such as original filename and directory structure, were randomly named and placed into a single folder. Fortunately I could use the EXIF data stored in most JPG files to extract the date and time when the photo was taken, and write a little script to sort the folders by year and month.

As part of the process of recovering my photos, I found several thousand small texture images. I have no idea where they came from, or why they were on my failing backup hard drive. That drive had contained a decade’s worth of computer backups from our computers and the computers of friends and family, so maybe there was some application that used all these textures? It’s a mystery. Anyway, I thought I’d post them here in case they might be useful for someone.

See these mysterious textures here: https://www.mbeckler.org/textures/

I recently started uploading photos to google photos, and it’s seemed to be pretty solid so far. However, when I’m trying to organize photos into albums by date (like wedding photos or vacation photos), the photo search seems to be a total failure!

Here are two photos taken in the same minute of the same day during our vacation to Hawaii:

It looks like Google Photos properly parsed the photo metadata (EXIF tags) and recognizes that both photos were taken on October 7, 2012 (which they were). However, when I search in Google Photos for “October 7, 2012” or “October 2012”, one of those photos does not show up anywhere!?!

Even weirder, is when I search for the original filenames, only one of these photos shows up!

Any ideas? My only thought is that since I uploaded all these photos the system is still trying to process all the images in the background and the search indices haven’t been updated?

A few weeks ago we packed up a bunch of meals to be frozen, then thawed and dumped into the slow cooker to simmer all day while we’re at work, ready to eat when we return. Today’s meal was a delicious Split Pea Soup.

This recipe is relatively simple to prepare. In a gallon freezer zip bag, freeze the following:

  • 1 pound dry split peas
  • 2 cups bacon, cooked and diced
  • 1 onion, diced
  • 1 cup celery, diced
  • 2 cups carrots, chopped
  • 3 cloves garlic, diced
  • 1/2 teaspoon cloves
  • 2 bay leaves

When the big day arrives, thaw the frozen bag overnight in the refrigerator.

In the morning, add the thawed contents to the slow cooker, plus four cups of chicken or vegetable broth.

Cook on low for 7-8 hours.

(side note: every time I hear the term “pea soup” I always think of this scene from The Rescuers Down Under… what a great movie!)

Really delicious soup for the winter. I think we got this recipe from our CSA one year.

Servings: 8
Prep: 15 mins
Cook: 35 mins
Total: 50 mins

Ingredients:
1/4 cup unsalted butter
2 sweet dumpling squash, peeled, seeded, chopped
1/2 cup onion, cleaned and chopped
1 pound carrot, chopped
1 teaspoon dried thyme
1 teaspoon dried sage
4 cups chicken or vegetable Stock
1 1/2 cup apple cider, divided use
6 tablespoons whipping cream
Salt
1/2 cup sour cream
Chive, chopped for garnish, optional

Directions:
Melt butter in heavy large sauce pan.
Add onion, squash, carrot and saute until softened.
Stir in thyme, sage, stock and 1 cup of cider.
Bring to boil.
Reduce heat to medium low, cover and simmer until veggies are tender, about 30 minutes.
Puree.
Mix in cream.
Season to taste with salt.

Meanwhile, in a separate saucepan, reduce remaining cider to 1/4 cup.
Cool.
Mix together cider and sour cream.

Serve soup, adding a drizzle of cider cream and a sprinkling of chopped chives on top of each bowl.

From our friend MegD

Ingredients:
1 can shopeg corn
1 can pinto beans (drain)
2 cans black eyed peas (drain)
1 each: red, yellow, green pepper
1/4 onion
1 1/3 c sugar
3/4 c vinegar
1/4 c vegetable oil

Directions:
Dice vegetables into 1/4″ cubes.
Mix corn, beans, pepper, and onion. Add oil, mix.
Mix-in sugar and vinegar, be sure to evenly distribute.
Eat with chips. Keep refrigerated. Enjoy.

Fantastic tomato soup for using up all those CSA tomatoes… I usually scale-up the recipe by 2, 3, 4, or even 6x. We always freeze some to save for those cold dreary January days when a fresh blast of summer veggies tastes just super delicious. My mom loves this recipe too, and recently said that she can’t eat the canned soup anymore since this is just so much better.

Prep: 20 min
Cook: 20 min
Cool: 10 min
Makes: 4 side-dish servings

Ingredients:
3 medium tomatoes, peeled and quartered (it’s a huge pain to peel them, so I don’t)
1.5 cups water
0.5 cup chopped onion (1 medium)
0.5 cup chopped celery (1 stalk)
1/2 of a 6oz can of tomato paste
2 Tbsp snipped fresh cilantro or basil
2 tsp instant chicken bouillon granules (I guessed that 1 cube is about 1 tsp)
1 tsp sugar
A few dashes of hot pepper sauce like Franks (I skipped this when I made it)
Snipped fresh cilantro or basil (for garnish when serving, optional)

Directions:
Seed the tomatoes if you want.
In a big pot combine tomato, water, onion, celery, paste, cilantro/basil, bouillon, sugar, and hot pepper sauce.
Bring to boiling; reduce heat.
Simmer, covered, for about 20 minutes or until celery and onion are tender.
Remove from heat, cool 10 minutes.
Blend the soup in the blender or food processor.

From my friend Jake.

Waffle Cookies
Makes: 12
Difficulty: Easy

Ingredients:
1/2 cup butter
1 cup sugar
2 eggs
1 tsp vanilla extract
1 1/4 cup flour
1/4 cup unsweetened cocoa powder
1 tsp baking powder
1/2 tsp salt
1/2 tsp ground cinnamon

Directions:

Combine using the creaming method.

Bake using waffle iron.