Tree walking and display console app in Go

I hadn’t done anything at all interesting in Go. And some might say, I still haven’t. However, I wanted to do something that I’d find occasionally useful.

On Linux, this is already available, but the the Windows version is lacking. I wanted a tiny console app that would display a tree of the directory and file structure.

So, that’s what I built. Smile

It’s one small file with one external library dependency.

I did notice that the Go packages for directory scanning like ReadDir suffer from a common issue when using the traditional Win32 APIs: they do not adequately handle file paths longer than about 250 characters. When you have NodeJS source code on your system with lots of deeply nested paths, many Windows programs fail miserably when doing file/folder management operations (Windows Explorer, I’m looking at YOU). Using the one “easy” trick of prepending the path with \\?\, you can use the APIs like ReadDir reasonably reliably. Whereas in earlier versions of my tree app it would crash, it now can handle deeply nested directory structures.

image

go get github.com/fatih/color

Customize the External VS Code Console

I have Visual Studio 2015 installed and when I launch a command prompt on Windows, it’s generally the Visual Studio 2015 Developer Command prompt (in fact, I have it pinned to my Windows 10 task bar).

image

On Windows, using Visual Studio Code 1.7+, pressing SHIFT+CTRL+C opens a Windows Command prompt from the root directory of your opened folder. It’s super useful.

I wanted the Developer Command prompt to open instead of a standard command prompt.

To change that, open the User Settings:

image

Add the following:

"terminal.external.windowsExec": "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools\\VsDevCmd.bat"

Of course, you can use other batch or command files to customize the prompt. I just wanted all of the standard developer tools I have installed to be available.

MobX and TypeScript Experiement

I wanted to give MobX a try, in particular from TypeScript.

Here’s my first attempt. I liberally used the documentation example found within createTransformer as my guide.


import "core-js";
import { observable, autorun, createTransformer } from "mobx";

/*
 The store that holds our domain: boxes and arrows
*/

class Store implements Storable {
 @observable public boxes: Box[];
 @observable public arrows: Arrow[];
 @observable public selection: any;

 constructor(init: Storable = {}) {
     this.boxes = init.boxes || [];
     this.arrows = init.arrows || [];
     this.selection = init.selection;
 }
}

interface Storable {
    boxes?: any[];
    arrows?: Arrow[];
    selection?: any;
}

interface Box {
 id: string;
 caption?: string;
}

interface Arrow {
    id: string;
    to?: Box;
    from?: Box;
}

const serializeState = createTransformer<Store, Store>(store => {
 return new Store({
     boxes: store.boxes.map(serializeBox),
     arrows: store.arrows.map(serializeArrow),
     selection: store.selection ? store.selection.id : null
 });
});

// copy using Object.assign (as this is just a simple JS object anyway)
const serializeBox = createTransformer<Box, Box>(box => Object.assign({}, box));

const serializeArrow = createTransformer<Arrow, Arrow>(arrow => {
 // or can copy manually...
 console.log("serializeArrow");  // this is only called 3 times!
 return {
     id: arrow.id,
     to: arrow.to,
     from: arrow.from
 };
});

const store = new Store();
const states: Storable[] = [];

autorun(() => {
 // this could be used to create an undo buffer, or whatever
 // probably wouldn't want infinite growth ... 🙂 
 states.push(serializeState(store));
});

const b1 = { id: "b1", caption: "Box 1" };
const b2 = { id: "b2", caption: "Box 2" };
const b3 = { id: "b3", caption: "Box 3" };
store.boxes.push(b1);
store.boxes.push(b2);
store.boxes.push(b3);

store.arrows.push({ id: "a1", from: b1, to: b2 });
store.arrows.push({ id: "a2", from: b1, to: b3 });
store.arrows.push({ id: "a3", from: b2, to: b3 });
b1.caption = "Box 1 - Edited";

// Should be 8
console.log(states.length);

b1.caption = "Box 1 - Final";

// Should be 9
console.log(states.length);

To make that work:


npm install --S mobx reflect-metadata
npm install --D @types/core-js

Sweet that MobX includes a TypeScript declarations file. 🙂

The things of interest here is that MobX assists in maintaining a stack of the object graph’s state, something that could be used for example in an undo buffer or comprehensive log system.

In this example, that’s done by using the MobX autorun functionality. When any of the dependencies of autorun changes, the function executes. In the example above, it makes a clone of the current store, using the createTransformer function, which turns a function into a reactive and memoizing function. Through memoization, it only transforms portions of the objects that have changed, not everything, every time. That doesn’t mean that you won’t want to limit the growth of the states, but you shouldn’t worry that a large complex object structure is being built with every change.

As TypeScript doesn’t support the object spread operator (which is convenient for making a clone of an object), I’ve used Object.assign instead (which may require a polyfill depending on the environment in which you use this code).

 

 

Made in the USA Camera Bag Manufacturers

Below is the list I’ve gathered to more permanently record a list of made in the USA or made in America camera bags. There are a number of web sites that have attempted to list manufacturers, but they are often out of date and and worse, missing many options.

The current list is always here (opens in a new window).

 

I also need your help adding to the list (and keeping it up to date). It took me a surprisingly long time to collect this list and I’m sure I’ve missed some manufacturers. I’d really like to get them all!

For suggestions please use this survey.

image

Social-up your Business

Dear Small Business Owner,

As a potential customer of your small business, I’m frustrated by your lack of response to my email, tweet, Facebook post, Instagram Message, text message, Skype chat, etc.

I think I know what happened that led to my frustration.


 

You’ve got an established or new business.

At some point in the business life cycle, you decide to build a web site. (“Hey! You totally need a web site to drive more traffic!”). As you realize building web sites is not core to your business, you spend some hard earned income to invest $200 in a web site.

To your untrained eye, you may not recognize the Microsoft FrontPage style template that $200 bought.

Not only has the web designer created some static content, they’ve thoughtfully created:

  • A blog
  • An e-mail address
  • A “Contact me” form
  • The Full Social-Package™, including but not limited to: Twitter, Facebook Pages, Instagram, and Skype.

After an all-too-brief explanation, you, sit back and wait for new business opportunities to arrive, digitally.

And nothing happens.

Maybe a blog post will help. So, you create the first (and last) blog post.

And still nothing happens.

So, business resumes as normal. The web site goes unmodified. The blog post remains, dull, and outdated.

E-mails aren’t flooding in, so the e-mail address that was set up isn’t checked frequently or at all.

So, when a potential customer uses one of the social options or an email to contact your business, there is no timely response (if there’s one at all).

And then…, you’ve lost a customer.

Sorry, but I’m going to find a different business that meets my needs.


 

If a small business doesn’t check and respond to voice mails once a (work) day, they may loose business. If that same business does not check their email, social accounts, MySpace pages, etc., they also may loose business.

I’m sure they meant well by having a web site with an email address, etc., but if it’s not used, it’s no different than not answering the phone.

So, what happened? It started with unreasonable expectations.

A blog, social-media accounts, email accounts, do not directly create new business opportunities. They are simply new channels for communication. It’s two-way. If your business doesn’t have a plan for these new forms of communication, they will fail.

You will miss out on new customer opportunities. And worse, you may lose existing customers who may transition to using the other forms of communication you’ve claimed to offer. Spend an extra $100 to have a daily (or more frequently) plan developed to consistently use these communication options. Delete and remove any that don’t fit your business needs or that sit unused. If you don’t understand these forms of communication or how to integrate them effectively, there are lots of on line resources that can help, both paid and free.

I like buying local and will support businesses that work best with my lifestyle and communication preferences.

Small business owners can do better. Please.