User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Just throwing this out there: backdir

Sun Mar 11, 2018 9:23 pm

I may put this on gthub eventually if I can find a course in how the site (and git) works, don't care much for it.

Anyway I wrote this mostly for programming use. It provides a temporary backup, or versioning, by copying files from the current directory to a subdir named backups. It appends the file date and time to the name so for instance bd.c is copied to ./backups/bd_2018-03-11_1552.c. The backups dir is created if it doesn't exist. If there's a file in there with the name that would be used nothing happens. To use it compile like "gcc -O -Wall -o bd bd.c" then copy bd to somewhere in your path like /usr/local/bin. Backup all the files in a directory by typing bd. Keep backing up what's changed by typing bd again. I use it after every successful compile. If I screw something up I can look up a good version.

Code: Select all

/*
    backdir - makes a backup of the files in a directory
    uses the original filenames with mtim appended to give versions
    
    Mostly for use in programming, doesn't copy to another machine or anything,
    just provides versioning.  But it will work with any file types: 
    spreadsheets, images, it doesn't care.
    
    Copies file.c to backups/file_yyyy-mm-dd_hhmm.c, keeping the original
    date and time as part of the new filename.
    
    Compile with: gcc -O -Wall -o bd bd.c

    AB1JX Alan Corey 5/4/2013  standard BSD copyright applies    
    3/23/2017 changed to not follow symlinks
    
*/

#if defined (linux)
  #define _XOPEN_SOURCE
  #define __USE_XOPEN
  #define _GNU_SOURCE
  #include <time.h>
#endif

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>

#define NEWMODE 0755  /* mode for backups dir */

int filecount = 0;

void checkdir(void) {  // check for a backups dir, make one if needed
  int rslt;
  struct stat sb;
  rslt = stat("backups", &sb);
  if (rslt == -1) {
    if (errno ==  ENOENT) {
      rslt = mkdir("backups",NEWMODE);
      if (rslt != 0) {
        printf("Error creating backups dir.\n");
        perror("mkdir ");
        exit(1);
      }
    }
  }
}

int fileexists(char *fname) { // like Delphi's a little
  int rslt;
  struct stat sb;
  rslt = stat(fname, &sb);
  if (rslt == 0)
    return 1;  // return 1 if it exists
  else
    return 0;  // else return 0
}

void master(void) {     /* slavedriver  :) */
  DIR* dirp;
  struct dirent *de;    /* in sys/dirent */
  struct stat sb;
  struct timespec mtim; /* 1 of the 3 file time values: modified time */
  time_t mtim_t;
  struct tm mtim_tm;
  char timestr[40];
  size_t siz;
  char oldname[512];
  char oldext[512];
  char nametmp1[512];
  char *p;
  char newname[512];
  char systr[1024];
  int rslt;
  dirp = opendir(".");
  if (dirp != NULL) {
    while ((de = readdir(dirp)) != NULL) {
      if (((de->d_type & DT_REG) == DT_REG) || ((de->d_type | DT_LNK) == 0)) {  // regular files only
        strncpy(oldname,de->d_name,512);
        if (oldname[0] != '.') {   // ignore . and .. (also hiddens)
          rslt = stat(oldname,&sb);
          if (rslt != 0) {
            printf("Error running stat() on %s\n",oldname);
            perror("stat ");
            closedir(dirp);
            exit(1);
          }
          if ((sb.st_mode & 0111) == 0) {  // nothing executable
            // gets a struct timespec
            mtim = sb.st_mtim;
            // gets the time_t part
            mtim_t = mtim.tv_sec;
            // make a struct tm
            (void) localtime_r(&mtim_t,&mtim_tm);
            // now strftime to format into timestr
            siz = strftime(timestr,40,"%Y-%m-%d_%H%M",&mtim_tm);
            if (siz != 0) {
              strncpy(nametmp1,oldname,512);
              p = strrchr(nametmp1,'.');  // find last period
              if (p != NULL) {
                strncpy(oldext,p,512);  // copy extension
                *p = '\0';  // terminate
                rslt = snprintf(newname,512,"backups/%s_%s%s",nametmp1,timestr,\
                  oldext);
              } else {
                rslt = snprintf(newname,512,"backups/%s_%s",nametmp1, timestr);
              }
              if (rslt == -1) {
                printf("Error making new name from %s\n",nametmp1);
                exit(1);
              }
              if (fileexists(newname) == 0) { // may not be new
                rslt = snprintf(systr,1024,"cp %s %s",oldname,newname);
                if (rslt == -1) {
                  printf("Error making system string 'cp %s %s'",oldname,newname);
                  exit(1);
                }
                rslt = system(systr);
                if (rslt == -1) {
                  printf("Error copying %s to %s\n",oldname,newname);
                  exit(1);
                }
                filecount++;
              }  // if backup doesn't exist already
            }  // if siz != 0
          }  // mode ok
        }  // if not . or ..
      }  // if type OK
    }  // while readdir
    rslt = closedir(dirp);
    if (rslt != 0) {
      printf("closedir on current dir failed.\n");
      perror("closedir ");
      exit(1);
    }
  } else {
    printf("opendir on current dir failed.\n");
    perror("opendir ");
    exit(1);
  }
}

int main(void) {
  checkdir();
  master();
  if (filecount == 1) {
    printf("1 file backed up.\n");  // don't use plural
  } else {
    printf("%i files backed up.\n",filecount);
  }
  return 0;
}

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Sun Mar 11, 2018 9:43 pm

ab1jx,
I may put this on gthub eventually if I can find a course in how the site (and git) works, don't care much for it.
The irony of your post is that you are creating a source code version control system, with backups, time stamps and so on, exactly the job that git does already!

Git may seem a bit weird and clunky but actually there are only a few simple git commands you ever normally need to use and it is very easy.

$ git init - Sets up a new git repository in your current directory (which should be your projects directory)

$ git add - Adds a file or files to what may become a committed version.

$ git commit - Creates a new commited version of your project.

$ git diff - to see the differences between your current edits and the last commited version

$ git checkout - to restore your project to the last, or some other, comitted version. Throwing away your current edits.

$ git status - To tell you what you have edited recently and what might need committing.

Then there is git push and git pull to put your changes into to some "upstream" repository or fetch the latest version down from there. Which may be gitgub or bitbucket or other.

Personally I would avoid all talk of "branches" when starting out on a one man project.

A nice git/github tutorial is here: https://product.hubspot.com/blog/git-an ... -beginners

git is the first and only source code management system I have ever used, there were many, that is actually helpful in developing code without getting in your way. I use it for even the smallest projects now.
Memory in C++ is a leaky abstraction .

User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Just throwing this out there: backdir

Sun Mar 11, 2018 10:34 pm

I wish github would add rsync as a protocol but they probably never will. This has been on my web site at http://ab1jx.1apps.com/ham/calcs/backdir/index.html for about 5 years as far as I can tell. That version doesn't ignore symlinks though. I was trying to get it into OpenBSD ports once but I got tired of requests for changes in it and gave up. I mostly don't have fulltime internet so github is just another site to download from. I grab the master.zip tarballs a lot. Git doesn't seem very robust on bad connections, wget works better.

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Sun Mar 11, 2018 10:57 pm

ab1jx,

You seem to be under some misapprehension...

git does not require an internet connection to be useful. It does not require github or bitbucket or whatever. Your project's git source code repository is maintained in the projects directory.

In that way git does everything your backdir does, only better :)

Of course git is designed to be distributed. But those distributed repositories could as well be another directory on the same machine or one you have access to locally.

I have used git with github, bitbucket and my own remote git servers, over all kind of crappy connections, not always connected, no problem. Your projects local git repo works just fine when there is no connection.

There is no point in adding rsync to git, it does all of that and more itself.
Memory in C++ is a leaky abstraction .

User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 2:16 am

When something is more work to learn than to write myself my inclination is to write it myself. Besides, I enjoy writing stuff, having to study somebody else's way of doing things and be sure I've got it right, and they aren't going to change the rules, I don't enjoy. This is entirely contained in one 8900 byte executable, it doesn't rely on the internet or anyone else. There's only one command: "bd" but you can rename it to whatever you like. It's simple. I've been using it for 5 years, it does what I want.

I wouldn't mind a free online site to stick things on but it probably won't be github.

User avatar
joan
Posts: 14473
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 3:32 am

I do something similar. Every 20 minutes or so any changed laptop files are copied to a network drive which is always on. The network drive timestamp versions them and holds them for posterity or earlier if i specify.

In the script I just specify which directories should be backed up and if the versions should be deleted after so many days.

I suppose I could use git to do some of this. However I have outlived quite a few code control systems and I expect to outlive git (or I'll die trying).

jamesh
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 24168
Joined: Sat Jul 30, 2011 7:41 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 9:35 am

ab1jx wrote:
Tue Mar 13, 2018 2:16 am
When something is more work to learn than to write myself my inclination is to write it myself.
This is one of the reasons Linus Torvalds wrote git in the first place. Ironically, it ended up as a very difficult to learn (properly) system.
Principal Software Engineer at Raspberry Pi (Trading) Ltd.
Contrary to popular belief, humorous signatures are allowed. Here's an example...
“I think it’s wrong that only one company makes the game Monopoly.” – Steven Wright

n67
Posts: 938
Joined: Mon Oct 30, 2017 4:55 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 9:48 am

jamesh wrote:
Tue Mar 13, 2018 9:35 am
ab1jx wrote:
Tue Mar 13, 2018 2:16 am
When something is more work to learn than to write myself my inclination is to write it myself.
This is one of the reasons Linus Torvalds wrote git in the first place. Ironically, it ended up as a very difficult to learn (properly) system.
In software, as in politics, you always end up re-inventing the system that you were originally complaining about/seeking to replace.
"L'enfer, c'est les autres"

G fytc hsqr rum umpbq rm qyw rm rfc kmbq md rfgq dmpsk:

Epmu Sn!

J lnacjrw njbruh-carppnanm vxm rb mnuncrwp vh yxbcb!

jahboater
Posts: 4843
Joined: Wed Feb 04, 2015 6:38 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 10:05 am

The big breakthrough I thought was concurrent version control. - hard to write that yourself as a small program.
CVS and later Subversion allowed multiple developers to check out and edit the same file at the same time, and can usually sort out the mess afterwards.
Presumably git can do that, I don't know.

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 11:40 am

ab1jx,
When something is more work to learn than to write myself my inclination is to write it myself.
Ha! I know that feeling all too well. I quite sympathize.
I wouldn't mind a free online site to stick things on but it probably won't be github.
I still don't see why not. It will only take you twenty minutes or so to learn enough about git and github to put it there. It is free and it is online, it fits your requirements perfectly.

Once you have a github account and created a new repo there it's just:

$ cd yourProject
$ git init
$ git add .
$ git commit -m "First commit"
$ git remote add origin https://github.com/yourName/yourProject.git
$ git push origin master

Job done.

https://help.github.com/articles/adding ... mand-line/

This does not preclude your using backdir as well as you work. Should you arrive at a new version that you want to release to the public it's only:

$ git add .
$ git commit -m "Super new release x.y.z"
$ git push origin master
Last edited by Heater on Tue Mar 13, 2018 12:23 pm, edited 1 time in total.
Memory in C++ is a leaky abstraction .

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 11:55 am

@n67,
In software, as in politics, you always end up re-inventing the system that you were originally complaining about/seeking to replace.
As far as I can tell from watching Linus' presentations on git, he did not create it because other systems were difficult to learn. Rather it was because the other systems did not do what he wanted. He was quite happy using bitkeeper except there was some problem with it's licensing.

@jahboater,
The big breakthrough I thought was concurrent version control...CVS and later Subversion allowed multiple developers to check out and edit the same file at the same time...Presumably git can do that, I don't know.
That is my impression as well. When I first heard one could do that with CVS years ago I was dumbfounded. "That's insane", I thought, "that will lead to chaos".

I was too used to being tortured with version control systems that did atomic file checkouts for years. They were universally complex, clunky and slow. From ClearCase to VisualSourceSafe, with many others along the way, having to use a version control system was a drudge.

CVS and subversion made life easier. Git finally got it right enough that it is actually beneficial to progress.

Yes git merges multiple checkouts. In a very nice way.
Memory in C++ is a leaky abstraction .

n67
Posts: 938
Joined: Mon Oct 30, 2017 4:55 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 12:20 pm

Yes git merges multiple checkouts. In a very nice way.
Are you going to setup a signature file proclaiming yourself a "Git Evangelist" ?
"L'enfer, c'est les autres"

G fytc hsqr rum umpbq rm qyw rm rfc kmbq md rfgq dmpsk:

Epmu Sn!

J lnacjrw njbruh-carppnanm vxm rb mnuncrwp vh yxbcb!

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 12:33 pm

Ha, "Git Evangelist", might be a good idea. Except I can be quite fickle, I'll use and enthuse about a thing until I find something else that works better.
Memory in C++ is a leaky abstraction .

ejolson
Posts: 3825
Joined: Tue Mar 18, 2014 11:47 am

Re: Just throwing this out there: backdir

Tue Mar 13, 2018 3:35 pm

Heater wrote:
Tue Mar 13, 2018 12:33 pm
Ha, "Git Evangelist", might be a good idea.
Don't forget to mention NodeJS evangelist as well!

User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Just throwing this out there: backdir

Sat May 19, 2018 6:01 pm

The program ignores executable files, so if it isn't backing up anything do an ls -lr in the directory and make sure the source isn't marked executable. A chmod -x <file> will fix it if so.

Heater
Posts: 13916
Joined: Tue Jul 17, 2012 3:02 pm

Re: Just throwing this out there: backdir

Sat May 19, 2018 6:35 pm

What, you did not change to using git then?

:)
Memory in C++ is a leaky abstraction .

ejolson
Posts: 3825
Joined: Tue Mar 18, 2014 11:47 am

Re: Just throwing this out there: backdir

Sat May 19, 2018 7:58 pm

Heater wrote:
Sat May 19, 2018 6:35 pm
What, you did not change to using git then?

:)
Maybe try BitKeeper as it is now open source. Which you prefer is a competition between not-invented-here, worse-is-better and the-right-thing approaches to software design.

mfa298
Posts: 1387
Joined: Tue Apr 22, 2014 11:18 am

Re: Just throwing this out there: backdir

Sat May 19, 2018 9:11 pm

ab1jx wrote:
Sat May 19, 2018 6:01 pm
The program ignores executable files, so if it isn't backing up anything do an ls -lr in the directory and make sure the source isn't marked executable. A chmod -x <file> will fix it if so.
I would also suggest spending some time with git. It does (fairly simply) all you've talked about and more (not always so simple but there's plenty of google hits to help). There's also a bunch of good documentation (including man pages) for it.

I'd also suggest the tutorials at https://www.atlassian.com/git/tutorials as a place to get started.

As others have said you don't need an internet connection to make use of it. In it's simplest form it works in a single folder (and that's how I usually start out) you can then push/pull with remote servers (which could include github or bitbucket or anything else with ssh) or folders (even a pendrive if you wanted an offline backup). Alternatively there are also tools to manage changes via email (as that's how stuff makes it into the kernel tree)

In terms of ignoring files that's simple it git, you just list patterns to ignore in the .gitignore file.

One feature git has over your solution which is very useful is the commit log should include a short description of the change and usually some extra detail. That can be really useful when you come back in 6 months and wonder why you made a change. Particularly if the fix wasn't the obvious fix. With the detailed commit log it's also easier to revert a single change from the history.

If you truly embrace the git way and work in branches per feature/fix which are then merged back into the master branch then it can become even more powerful. This potentially allows you to work on a few feature additions and bug fixes in parallel and then add them in as they're ready and tested. I often fail to work in that way and then realise I've been silly when all my work is in the master branch and I have one complete feature to push out but also partially completed features I can't push yet.

The way to think of git is as a set of patch files with descriptions (and other metadata) rather backups of each separate file after every change. This is what makes it easy to work on several branches of the code and then merge them back into the main working tree as well as viewing (and reverting) specific changes as needed.

User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Just throwing this out there: backdir

Sat May 19, 2018 9:50 pm

Yes, I've had an account there for a couple years, I forget why. Just got some automated email from them to update my email preferences.

I'm not interested in any of the version control stuff or in collaboration. I'm just looking for a free FTP host. Maybe I should use a free web site I can upload binaries to, but I had 2 of those and just this week discovered that neither works any more.

You can download OpenBSD via FTP, HTTP or Rsync, they don't offer Bittorrent. I'd like to see github be a little more versatile. They could add more ways to get to the same files, it isn't going to make them take more space. As far as I'm concerned git is about the same as svn or mercurial or cvs, there's nothing wonderful about it. It's not a high priority.

ejolson
Posts: 3825
Joined: Tue Mar 18, 2014 11:47 am

Re: Just throwing this out there: backdir

Sat May 19, 2018 11:03 pm

ab1jx wrote:
Sat May 19, 2018 9:50 pm
I'm not interested in any of the version control stuff or in collaboration.
It is a good point that small-scale single-developer projects are not the kind of projects that BitKeeper or git were designed for. At the same time, due to a lack of annoying advertising, Github turns out to be a reasonable place to keep files you want publicly accessible for download, even if you don't need to coordinate a large-scale multi-developer collaboration.

User avatar
DougieLawson
Posts: 36576
Joined: Sun Jun 16, 2013 11:19 pm
Location: Basingstoke, UK
Contact: Website Twitter

Re: Just throwing this out there: backdir

Sat May 19, 2018 11:08 pm

Gitolite - that gives you a local git repo.
GitWeb - that works with a Gitolite repo & Apache/Lighty/NGINX and gives you a web interface to your code stored in your local repo.

I only publish code to https://github.com when it may be useful to someone else.
Note: Having anything humorous in your signature is completely banned on this forum. Wear a tin-foil hat and you'll get a ban.

Any DMs sent on Twitter will be answered next month.

This is a doctor free zone.

mfa298
Posts: 1387
Joined: Tue Apr 22, 2014 11:18 am

Re: Just throwing this out there: backdir

Sat May 19, 2018 11:29 pm

ab1jx wrote:
Sat May 19, 2018 9:50 pm
I'm not interested in any of the version control stuff or in collaboration.
Yet your program seems to be doing a form of poor mans version control. As I said in my previous post (and others have also said) git can be used standalone on a single host, no internet, no github, no bitbucket.
ab1jx wrote:
Sat May 19, 2018 9:50 pm
I'd like to see github be a little more versatile. They could add more ways to get to the same files, it isn't going to make them take more space.
you can use github via http or ssh, or download specific commits as an archive. What else do you want (with how git works I'm not really sure they can offer much more). But then github isn't an integral part of git, it's just a website built around the git application.
ab1jx wrote:
Sat May 19, 2018 9:50 pm
As far as I'm concerned git is about the same as svn or mercurial or cvs, there's nothing wonderful about it. It's not a high priority.
They're the same in that they're all version control systems, the same similarity applies to your thing as well. Internally they're very different. I don't know much about mercurial but from memory cvs and svn both require a server to operate on. Git can be used by a single user in a single project folder. I've used cvs, svn and git over the years, for me git is the clear winner in terms of ease and features, followed by cvs.

User avatar
HermannSW
Posts: 1657
Joined: Fri Jul 22, 2016 9:09 pm
Location: Eberbach, Germany
Contact: Website Twitter YouTube

Re: Just throwing this out there: backdir

Sat May 19, 2018 11:44 pm

ab1jx wrote:
Sat May 19, 2018 9:50 pm
I'm not interested in any of the version control stuff or in collaboration.
You might be surprised using github, only for you, other people can fork from your git and add and/or correct stuff you were not aware. They can do pull requests to your branch and you can decide whether you want to take and what.
Doing your own stuff as you do you will rarely ever get an equivalent of a pull request.

I am (relatively) new to github myself, but it is really cool to work on my forks of 6by9's raspiraw and userland (containing raspivid) branches and being able to get my additions into his branches via pull requests.

With github you get a lot of stuff that is useful for free, I personally like Insights/Network, eg.:
https://github.com/Hermann-SW/raspiraw/network

Even without collaboration github offers much like nicely formatted diffs in browser, or links to any source code line, eg.:
https://github.com/Hermann-SW/userland/ ... id.c#L1629

P.S:
If 6by9 would not have started raspiraw branch for processing raw Bayer data from camera (without using closed source GPU code), I would not have been able to teach v2 camera taking 1007fps videos (v2 is sold as 90fps max):
Image
⇨https://stamm-wilbrandt.de/en/Raspberry_camera.html

https://github.com/Hermann-SW/Raspberry_v1_camera_global_external_shutter
https://stamm-wilbrandt.de/github_repo_i420toh264
https://github.com/Hermann-SW/fork-raspiraw
https://twitter.com/HermannSW

ghellquist
Posts: 68
Joined: Thu Aug 02, 2012 8:47 am
Location: Stockholm Sweden

Re: Just throwing this out there: backdir

Sun May 20, 2018 8:24 am

In one of my projects I use git exactly like this. No need for internet access and only a few commands to know. Understand that git and github is not the same thing --- GitHub adds a lot on top of git which you might elect to use or not.

Preparation
Create the folder where the project will be. Give the command

Code: Select all

git init
. Git will create a subfolder ( no internet needed )
Optionally: Create one file ".gitignore". Add the text lines for files that should be ignored, say "*.tmp", "*.o" and "*.exe".

Usage
When I add a file or modify it. Give the two commands

Code: Select all

git add . 
git commit -m "Changed some files" 

Git has now stored any updated files. The date and your commit message is there for you to search on.

Note . in git add, there has to be " around the Changed some files in the command. You might elect to put these two commands in a file, say bd.bat

Now you can go back in history anytime you want using the normal git commands, learn them when needed.

The good part is that git has a lot of added functions which you might want to learn step by step once you find the need. It will not outgrow you as single developer or if you start to work together with other programmers -- it is used to support the development of the extremely large code base of Linux kernel.

User avatar
ab1jx
Posts: 868
Joined: Thu Sep 26, 2013 1:54 pm
Location: Heath, MA USA
Contact: Website

Re: Just throwing this out there: backdir

Fri Jun 15, 2018 3:25 pm

When I type make and there are no errors I type bd. It doesn't mean I'm ready to publish it or give other people access, it just means it compiled. I may be adding a subroutine I'm not finished writing yet. I've had mismatched {} take hours to find if they were far apart, sometimes it's quicker to grab the last working version and go from there.

My editor (Joe), if you do ctrl-g on a { will jump to the } it thinks matches. And I usually put a little "// end for q" after them or whatever. I take great care about my indentation.

Code: Select all

                } // end switch
              } // for chan
            } // for rx
          } // for ry
        } // end if not masked
      } // end for x
    } // end for y
But if there's a { and the matching } 100 lines later got deleted I'm hosed. Sometime I print a section out and draw connecting lines, working from inside out. It's easier to type bd.

Return to “General discussion”