Tabbed/Table output

Hi All

Is it possible to output a quasi table?

i.e like what you might see when you do mysql show databases?

At the moment I’ve got

for(var plugin in plugins)
{
print.boldLine(plugin.id & " | " & plugin.title).
indentedyellowLine(plugin.updatedAt).toConsole();
}

but I want a way of doing

Well, simply put, you can output whatever you want! :slight_smile:

If you’re asking for a library or helper to create the table for you, nothing exists like that to my knowledge. I’ve actually considered making something like that but I’ve just never had a real need for it. The closest I came is when I make the Snake game, but that was sort of custom. I also, haven’t gotten the stupid “high ascii” characters to display correctly on Linux. (╚ ╔ ╩ ╦ ╠ ═ ╬ ╣ ║ ╗ ╝)

I would start by making a little helper function to output fixed width data and then just built up the table as you go. The standard console window is only going to be 80 characters wide, however you can get the current height and width to make it dynamic like so:

shell.getTermHeight()
shell.getTermWidth()

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thanks Brad, I’ll give it a go - it’s not a massive priority, just thought it would make things like query outputs easier to read.

I’m afraid I have other questions (I’ve spent the day starting a CLI for cfwheels)…

  1. I need to set a fair amount of variables to make available to other functions. I ended up making a base.cfc, which extends commandbox.system.BaseCommand, then all the sub cfc’s extend that with super.init() to grab the variables scope. Bad idea? or ok?
  2. I needed a temp directory, so created (and then destroyed post function) to download and expand zip files to within the working directory - but I see there’s a designated temp folder in .commandbox - is that ‘safe’ to use for custom functions? Does it get cleared out any point?
  3. Ditto for local caching - we’ve got a XML plugin list which gets downloaded - I’ve ended up saving it in /commands/wheels/plugins.xml - is there a ‘better’ place/way?
  4. Is there a way to do (essentially) a cfdump to console (of potentially complex structures?), i.e writeDump(foo).toConsole?
  5. What’s the best way to read a file, and then find a line and extract it’s value? I know there’s cat - I was trying to extract a certain line from a config file: runCommand(“echo cat #localWheelsConfig# | grep application.$wheels.version”); how would you normally read and write configuration lines in a CLI environment? I appreciate this one is a bit of ‘it depends’ question.

Sorry for the questions! Am getting quite far though!
Ta
T

I can answer some of these questions for you.

I basically made a JSON / CF Struct file… called settings.json.

I made a wrapper CFC, and it looks like this.

component {

function init() {
return this;
}

function loadSettings(){
var jsonObj = fileRead( ‘settings.json’ );
return DeserializeJSON( jsonObj );

}

function saveSettings( required struct settingsObj ){
fileWrite( ‘settings.json’, SerializeJSON( settingsObj ) );
}

function set( required string settingName, required string settingValue ){
settingsObj = loadSettings();
settingsObj[settingName] = settingValue;

saveSettings( settingsObj );
}

function get( required string settingName ){
settingsObj = loadSettings();
if ( structKeyExists( settingsObj, settingName ) ) {
return settingsObj[settingName];
}
else {
return ‘’;
}

}

}

The file is relative to the module, so you can start with a {}
I just use it for my settings, pull them in and out.
You could have an InitDefault as well if you wanted, that loaded the defaults, and gives you the option to reset them to a default.

Pretty simple, quick, and easily to parse / use etc.

Some of the other questions Brad would be the best to answer.
Basically, if you are managing packages and bundles, think about making them into box.json modules / packages, and let dependencies deal with it all for you.

Hope this helps.

Gavin Pickin
gpickin@gmail.com
http://www.gpickin.com

> I ended up making a base.cfc, which extends commandbox.system.BaseCommand, then all the sub cfc’s extend that with super.init() to grab the variables scope. Bad idea? or ok?

I don’t see anything wrong with that. I would remove the run() method or at least set excludeFromHelp=true in the component declaration so it doesn’t show up in 'help".
You can also create service CFCs in your command directory that aren’t commands but contain shared functionality. Unfortunately, I don’t think we have a way right now to ask WireBox for them. For what it’s worth, I’m not too happy with how commands work right now and I wanted to update it, but it got deferred to a later version: https://ortussolutions.atlassian.net/browse/COMMANDBOX-121

> I see there’s a designated temp folder in .commandbox - is that ‘safe’ to use for custom functions?

Yep, you can use it. Just inject the path like so:
property name=“tempDir” inject=“tempDir@constants”;

> Does it get cleared out any point?
I don’t think so. I always clean up after myself if I put anything in there, but don’t ever reply on stuff persisting there across restarts.

> Ditto for local caching - we’ve got a XML plugin list which gets downloaded

For caching the return of ForgeBox REST API calls, I just set the data into the variable scope of the forgebox service: https://github.com/Ortus-Solutions/commandbox/blob/master/src/cfml/system/util/ForgeBox.cfc#L76
Now, that said, we already have WireBox under the hood. It wouldn’t be hard to add in CacheBox-- especially since one of the stand-alone distributions of WireBox actually includes CacheBox.

> Is there a way to do (essentially) a cfdump to console

Yes, and it’s actually built into CFML :slight_smile:
writeDump( var=[1,2,3], output=“console” );
You can also serialize as JSON before passing through the print object. And if you want some pretty formatting, do this:

print.line( formatterUtil.formatJson( serializeJSON( tree ) ) );

Also, keep in mind LogBox is also configured for you to use for debugging purposes (It’s part of WireBox). Just inject like so:

property name=“logger” inject=“logbox:logger:{this}”;

And use it like this:

logger.debug( “Here’s some information I’d like to log.” );

The log file for CommandBox is found under .CommandBox/logs/commandbox.log

If you want to log from a service, where there’s no print command, we have a special named logger called “console” that will append to the consule anything that’s logged to it. Check out the PackageService for examples of this in use.

> What’s the best way to read a file, and then find a line and extract it’s value?

It depends on the file format :slight_smile: If you have control over the file’s format, I would use an existing standard like a property file, XML or JSON and just use the inbuilt features of CFML to parse the files. For any other scenarios, you have the full power of CFML at your finger tips. Write whatever you want! :slight_smile: The PackageService has a number of functions for dealing with the box.json file, but there’s nothing else in particular written in.

On this note, we have planned to have a global settings file for CommandBox ( and associated service/commands to interact with them) but we haven’t actually built that yet. Perhaps we should also build a way for a command or namespace to have it’s own collection of persistent settings. Also, for what it’s worth, box.json can have anything set in it as it’s just JSON, just remember that it’s specific to the package, not global to the CommandBox installation.

> Sorry for the questions

No apologies needed at all. I’m super pumped to see people digging in and playing with this stuff :slight_smile:

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Thanks Brad - awesome info. Got a bit of reading to do though now :slight_smile:
Cheers!
T