Cmd++

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
Hey Orbinauts,

So over the last couple of weeks I started work on a framework for command line programs, as I was becoming heartily sick of reinventing the wheel every time I wrote a program with a menu structure. I also was finding several general-purpose functions useful quite often, so I also created a sort of function repository to hold them, instead of copying & pasting with every new project.

Download link here for Cmd++ 1.10:
https://www.dropbox.com/s/3xaxemsgfryaoq0/Cmd%2B%2B%201.10.zip


This is open-source, so if you want to use it for anything, please feel free. I decided to name it Cmd++, continuing the corny tradition that helped name C++ itself. ;)

Update: As of now, the project is Cmd--. Github didnt like the + character, so I figured, hey why fight it?

Project on Github:

https://github.com/BruceJohnJennerLawso/Cmd--

:hailprobe:
 
Last edited:

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
2,064
Reaction score
507
Points
113
But after all of this work in creating such a nice menu structure, it dawned on me that I have no idea how to get out of it. The whole point of a structure like this is to allow a user to define menus in single lines, write their functions, & then go. The problem is that I have no idea how to get out of the Menu structure & go to a specific function by name. If anyone has any ideas how to break out, I would appreciate the input.
I am not sure what exactly you mean by 'break out', but if you were asking how to "translate" a user input value into a function call, I would recommend the powerfull combination of "function pointers" and (STL)"maps".
See my little example on usage:
Code:
#include <iostream> // for std::cout, std::cin
#include <string>  // for std::string
#include <map>    // for std::map

using namespace std;

// Some "functions"/"commands"
void cmdA (void* data) { cout << "CmdA called!\r\n"; }
void cmdB (void* data) { int val = data ? *(int*)data : 0; cout << "CmdB called! Int:" << val << "\r\n"; }
void cmdC (void* data) { char *val = data ? (char*)data : ""; cout << "CmdC called! Txt:" << val << "\r\n"; }
void cmdX (void* data) { cout << "CmdX called! Terminating!\r\n"; exit(0); }

// convenience typedefs
typedef void (*action_t)(void*);
typedef map<string, action_t> actionMap_t;


int main (int argc, char* argv[])
{
    // Build the "string" => function relations
    actionMap_t actionMap;
    actionMap["a"] = cmdA;
    actionMap["b"] = cmdB;
    actionMap["c"] = cmdC;
    actionMap["x"] = cmdX;


    string request;
    do {
        cin >> request;
        if (actionMap.find(request) == actionMap.end()) {
            cout << "Unknown command '" << request << "'\r\n";
            continue;
        }
        // Call it!
        actionMap[request](0); // we give NULL every time for simpicity of example
    } while (true);

    return 0;
}
The most important thing is that you have to commit yourself to a parameter/return-value signature.
I chose void pointer as parameter as the most "castable" type, but it is dangerous as well.
Another (better) approach would be a return value of "int", where the called method could signal, what the main loop should do (0:"exit", 1:"OK do nothing", -1:"OK go up",etc.pp. ...for example)
If your 'command-functions' don't need any parameters at all, it would make life even more easy ;)

If that's not what you mean by 'breaking out', sorry for the noise:lol:
/Kuddel
 
Last edited:

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
Sorry for taking so long to respond, but that looks exactly like what I needed. Thank you kuddel!

I cant get to it just yet, as I am currently working on a graphing utility for the library. Maybe more later today.

---------- Post added at 20:57 ---------- Previous post was at 11:31 ----------

Updated the code above to reflect some new changes.

I'm currently stuck with a rather perplexing bug in my graphing utility, written in the Frepo.h and Frepo.cpp files. My approach was to create a class that held data about a function, but could also be outputted as an ASCII plot. This appeared to go reasonably well at first, but after setting up the output function earlier today, everything went off a cliff. Now the program crashes every time I try to create a function object, and it crashes after listing the name of a predefined object in the list function.

It almost appears as if the crash is being caused every time that I access a CFunction object, and then go back to the menu loop for the graphs (Graph_access). Adding in cout messages at specific times shows that the crash is happening somewhere after the CFunction object initialization, but I cant pinpoint why.

I have no idea what is causing this. Running the program in debug mode didn't catch anything, and adding a try-catch around the object creation made no difference either. Does anyone see anything wrong here?
 
Last edited:

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
2,064
Reaction score
507
Points
113
I have no idea what is causing this. Running the program in debug mode didn't catch anything, and adding a try-catch around the object creation made no difference either. Does anyone see anything wrong here?

Sorry I can't see anything at all ;) It might help if you give us the code.
Only by your descriptions it is nearly impossible to really say anything useful.

The only thing I can tell you so far is: Watch the stack! In general it is the most common error when you work with function-pointers or such things, that the stack tear-down does not match the stack-buildup.
Anyway without having the (complete) code this is just guessing.
/Kuddel
 

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
Sorry I can't see anything at all ;) It might help if you give us the code.
Only by your descriptions it is nearly impossible to really say anything useful.

The only thing I can tell you so far is: Watch the stack! In general it is the most common error when you work with function-pointers or such things, that the stack tear-down does not match the stack-buildup.
Anyway without having the (complete) code this is just guessing.
/Kuddel

Code is updated in the original post at the top, if you have the time to read through all of it (there's a lot unfortunately)

But what do you mean by the stack? If you mean the vector for storing the object pointers, why is removing the vector members relevant before shutdown? There is a really dumb but of code in the CFunction destructor, but how could that be causing problems before it gets destroyed?
 

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
2,064
Reaction score
507
Points
113
Code is updated in the original post at the top, if you have the time to read through all of it (there's a lot unfortunately)
Ah! O.K. I might check that code later

But what do you mean by the stack? If you mean the vector for storing the object pointers, why is removing the vector members relevant before shutdown?
No, I meant the call stack!
[ame="http://en.wikipedia.org/wiki/Call_stack"]Call stack - Wikipedia, the free encyclopedia[/ame]
 

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
2,064
Reaction score
507
Points
113
O.K. I've tried to look at your code and there is much I have to ask ;)

  1. What kind of (programming-)language did you do before? The indetation style is very unusual for C/C++ programmers ;) But that's not important.
  2. I am missing the "Iteratorref" file(s). At least "Iteratorref.h" is missing
  3. What compiler are you using? (out of curiosity)
  4. I would recommend you put the sources (*.h and *.cpp) into a zip so it is easier for others to compile 'em

/Kuddel
 

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
What kind of (programming-)language did you do before? The indetation style is very unusual for C/C++ programmers ;) But that's not important.

Never written anything before the probe chose me to speak his perfect language. :hailprobe:

The best explanation I can give is that I find my style easy to read, and the best for line compression (ie most code per line)

The curly brackets are located so that the person reading the code can draw a box with the start & end parentheses as the corners which will enclose all of the code nested within it. Its especially effective in MSVC++ 2010, where clicking next to a curly bracket in the compiler will highlight the start & end brackets of the "box"

Otherwise my style isnt inspired by anything, although parts of it appear to resemble python vaguely. (very vaguely though)

What compiler are you using? (out of curiosity)

MSVC++ 2010, one of the few Microsoft things that I can ever recall having been impressed with, but no OS warfare in here...

I would recommend you put the sources (*.h and *.cpp) into a zip so it is easier for others to compile 'em

Current version should be available at the top soon, although the graphing stuff is gutted (I'll just leave that for another time). I'm semi-through midterms right now, and I really don't have the brain-steam to do anything with it for a little while. Just for now, here's Delta Vee!, rewritten to demonstrate the new framework:

View attachment 12223
 
Last edited:

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
Updated the first post with a link to a download of the Cmd++ files.
 

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
1.02 now up. Lots of changes and improvements in various areas.
 

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
1.10 is now up. Significant rewrite to the TCmdMenu structure, and documentation is now included.
 

Enjo

Mostly harmless
Addon Developer
Tutorial Publisher
Donator
Joined
Nov 25, 2007
Messages
1,665
Reaction score
13
Points
38
Location
Germany
Website
www.enderspace.de
Preferred Pronouns
Can't you smell my T levels?
I'd say that DRY is the principle that you should take most seriously for now.
 

BruceJohnJennerLawso

Dread Lord of the Idiots
Addon Developer
Joined
Apr 14, 2012
Messages
2,585
Reaction score
0
Points
36
I'd say that DRY is the principle that you should take most seriously for now.

As in the redundant copies of Cmd_plusplus namespace functions in the classes? I hated doing that, but using the namespace too much makes it difficult to avoid One definition rule problems. I can just chain all of my includes together with the Functionalize! library at the top, but it doesn't always work really well.
 
Top