diff --git a/graphics/Banner.jpg b/graphics/Banner.jpg index 1077b70..a30efaa 100644 Binary files a/graphics/Banner.jpg and b/graphics/Banner.jpg differ diff --git a/graphics/Banner.xcf b/graphics/Banner.xcf index 825bbfc..0d7afdb 100644 Binary files a/graphics/Banner.xcf and b/graphics/Banner.xcf differ diff --git a/graphics/ScreenShot.jpg b/graphics/ScreenShot.jpg index 359f77b..a97c570 100644 Binary files a/graphics/ScreenShot.jpg and b/graphics/ScreenShot.jpg differ diff --git a/mdbook/src/Chapters/CommandLineOptions.md b/mdbook/src/Chapters/CommandLineOptions.md index 223f0e7..5ae261c 100644 --- a/mdbook/src/Chapters/CommandLineOptions.md +++ b/mdbook/src/Chapters/CommandLineOptions.md @@ -11,10 +11,7 @@ You can set the number of memory slots, decimal alignment, debug mode, and other |Option|Name|Description| |------|----|-----------| |-D | `DEBUG MODE`| Runs the program in debug mode. This will display quite a bit of information in RED as you use the program. This is mostly used by the developer and clutters everythign up, but you may find it useful if you are trying to debug something. I could certainly add a lot more if needed, but it's useful today. You can also toggle debug mode on/off by entering in the command `debug` while within the program - you don't have to restart RPNCalc| -|-l name |`LOAD STACK`| Load a saved stack. This essentially will "name" your session and store the stack upon exit in the Java preferences system. You can load the stack with the `-l name` command line option, or from within the program by using the `load name` command. Please note the name field is whatever you want to call the instance but avoid spaces in the name. I'm not aware of a limit to the number of saved stacks You can have. If the name to load does not exist, the stack will be created and saved when you exit.| -|-a l
-a d
-a r | `ALIGNMENT`| This option sets the display alignment of the numbers on the stack. Alignment can either be an `-a l` for LEFT alignment, an `-a r` for RIGHT alignment, or a `-a d` to align to the decimal point. This impacts the display only and doesn't impact the calculations. For example, when I load my saved stack `-l checkbook`, I align by decimal which makes it a bit easier to read a stack with only two decimal place numbers. Alignments can also be changed within the program itself using the `a` command| -|-m [slots]| `MEMORY SLOTS`| Override the default of ten available memory slots. If you need 25 memory slots, just use `-m 25` when starting the program. Please note that if you have 25 slots, the slot numbers within the program will be 0 - 24. Slots are saved and restored between sessions, but if you run the program again and do not specify `-m 25`, it will default to 10 and you'll lose the memory slots greater than that. If this is important, define an alias| -|-w width| `WIDTH`| Set the width of the program header and status line. Default is 80 characters. Useful if you are using a very small terminal. The minimum width of the console is currently 46 characters and RPNCalc will adjust to that if a lesser number is provided| +|-l `name` |`LOAD STACK`| Load a saved stack. This essentially will "name" your session and store the stack upon exit in the Java preferences system. You can load the stack with the `-l name` command line option, or from within the program by using the `load name` command. Please note the name field is whatever you want to call the instance but avoid spaces in the name. I'm not aware of a limit to the number of saved stacks You can have. If the name to load does not exist, the stack will be created and saved when you exit.| |-z| `DISABLE COLOR`| Disable colorized output. Useful if your current terminal doesn't support ANSI color sequences| |-v| `VERSION`| This will display the current program version, but will also check GitHub for the leatest release. It is possible, especially if you are using RPNCalc as a Snap, to have a later version than the latest GitHub release.| |-h or -?| `HELP`| Display the program help page and exit. This is the same as the `h` or `help` command within RPNCalc| \ No newline at end of file diff --git a/mdbook/src/Chapters/MemoryCommands.md b/mdbook/src/Chapters/MemoryCommands.md index 7f2491e..0e77b84 100644 --- a/mdbook/src/Chapters/MemoryCommands.md +++ b/mdbook/src/Chapters/MemoryCommands.md @@ -2,7 +2,11 @@ # Memory Commands -The memory capabilities are fairly flexible. By default, there are 10 memory slots you can use (numbers 0 - 9). This amount can be increased with the `-m NumSlots` command. But be aware, that if you use the `-m` command, it only applies for that instance. +The memory capabilities are fairly flexible. By default, there are 10 memory slots you can use (numbers 0 - 9). This amount can be increased with the `set memslots` command. If you increase or decrease the number of memory slots, it is persistent across RPNCalc executions. You can change it as will, but if you decrease the number of slots, anything held in the "no longer there" slots will be discarded. + +For example, say you `set memslots 20` and store values in all of them. If you later `set memslots 10`, the values in the upper 10 slots will be gone. + +The operational command `reset` will set the number of memory slots back to the default of 10. The basic need to is to save a value from the current `line1` into a memory slot and copy it back later. The memory slots are saved between program executions so if you need it in a later session, it will be there. It's saved in the Java preferences system as discussed earlier. diff --git a/mdbook/src/Chapters/OperationalCommands.md b/mdbook/src/Chapters/OperationalCommands.md index 1e25546..16f7726 100644 --- a/mdbook/src/Chapters/OperationalCommands.md +++ b/mdbook/src/Chapters/OperationalCommands.md @@ -10,11 +10,14 @@ Operational commands are commands that do not directly impact your stack numbers |list mem|Display the contents of the memory slots| |list undo|Displays all of the saved stacks and their contents used for undo operations. Basically what your stack will look like when you perform an undo. These are not saved between RPNCalc executions| |list func|Show a list of the defined User Defined Functions (UDF) and the steps within each one| -|load NAME|Load the named stack. You can `load` a stack name even if it doesn't exist, and it will be created. This is how a new stack is created and is similar to using the `-l name` command line switch. Exiting the program or loading another stack will save the current stack before switching| -|import FILENAME|With `import` RPNCalc will replace the current stack with one loaded from a file. The file format is simple, just one number per line. Do not include any comments or alphanumeric/special characters. Just one number per line with the last number being `line1` - just like the display in RPNCalc| +|load `NAME`|Load the named stack. You can `load` a stack name even if it doesn't exist, and it will be created. This is how a new stack is created and is similar to using the `-l name` command line switch. Exiting the program or loading another stack will save the current stack before switching| +|import `FILENAME`|With `import` RPNCalc will replace the current stack with one loaded from a file. The file format is simple, just one number per line. Do not include any comments or alphanumeric/special characters. Just one number per line with the last number being `line1` - just like the display in RPNCalc| |ss|Swap the current stack with the secondary. The primary and secondary stacks are described in the Stacks section. Executing `ss` again will swap them back. The secondary stack it just a place to do a bit of other work then you can swap back. They are in no way connected. The secondary stack is also saved upon exit| |debug|Toggle debug mode which will display additional information on what's happening internally in the program. Same as the `-D` command line switch. Probably not the useful for a normal user| -|a l
a d
a r| Align the display output to be `l(eft)`, `d(ecimal)`, or `r(ight)`. This is the same as the `-a ` command line switch. `align` or `alignment` may also be used| +|set width `NUM`| Sets the width of the program. The default is 80 characters. If you are using a small display, and the calculator wraps, this can be used to make the width smaller (or larger). Please note that there is a minimium width that must be used. At the time of this writing, it's 46 characters. This setting is persistent across RPNCalc executions| +|set memslots `NUM`| Set the number of memory slots available to RPNCalc to `NUM`. The default is 10 slots, numberd 0 through 9. If you need more, or less, it can be changed with this command. The setting is persistent across RPNCalc executions. `set mem` or `set memoryslots` may also be used. See the memory commands chapter for more information| +|set align `l\|d\|r`| Set the alignment of the stack when it's displayed. The default is `l` or left alignment. The numbers are aligned to the left. `r` or right alignment has the numbers aligned to the right. `d` or decimal aligns all of the decimal points together in a column. This setting is persistent acrsoss PRNCalc executions. `set alignment` may also be used| +|reset| This command resets the configuration setting that are set with the `set` command back to their default values| |ver| Display the current version number and copyright as well as the latest GitHub release. This is equivalent to the `-v` command line option. Users of Snap installations will automatically be up to date.| |h
?|`h` or `?` will display the in-program help page| |cx|`cx` will clear the stack and then exit the program| diff --git a/mdbook/src/Chapters/Stacks.md b/mdbook/src/Chapters/Stacks.md index f51fe69..07f8981 100644 --- a/mdbook/src/Chapters/Stacks.md +++ b/mdbook/src/Chapters/Stacks.md @@ -25,14 +25,8 @@ Saving and loading stacks is fundamental to RPNCalc. You can have as many named It is safe to delete these if you wish to stay tidy, but of course you'll lose any saved stacks, memory slots, and user defined functions which are stored there. They will be recreated again when RPNCalc is started. -Each stack you load (default or a named stack) actually has 2 internal stacks defined; a primary and secondary. You can quickly swap stacks using the swap stack `ss` command. For example, you are working on something and need to do a few calculations that you wish to keep separate from your main work. You can swap stacks, do the work, then swap back. They do not communicate in any way and are distinctly separate. The primary and secondadry stack data is saved and restored upon loading the stack. +Each stack you load (default or a named stack) actually has 2 internal stacks defined; a primary and secondary. You can quickly swap stacks using the swap stack `ss` command. For example, you are working on something and need to do a few calculations that you wish to keep separate from your main work. You can swap stacks, do the work, then swap back. They do not communicate in any way and are distinctly separate. The primary and secondadry stack data is saved and restored upon loading the stack. The primary and secondary stacks have their own unique undo stacks as of version 4.5. This was long standing issue that's now been resolved. When you start up RPNCalc, you can load a named stack with the `-l name` command. If the stack `name` exists, it will be loaded. If it does not exist, the stack will be created and when you leave the program it will be saved. You can always view what stack you are using in the lower right of the dashed bar. The `:1` or `:2` after the stack name will tell you if you are on the primary or secondary stack. As a side note, both stacks and memory slots are saved during shutdown. While the data in a stack is specific to that stack, memory slots are global. The default stack items are restored at startup (or whatever stack you choose to load with `-l name`.) Memory slots are also restored at startup. `list mem` will show the values in current memory, and `list stacks` will show the saved stacks available to load. - -
- -***`Please note that the undo functionality is shared (and shouldn't be) so you could undo on one stack and restore the other. I'm looking into correcting this or perhaps removing the secondary stack as I'm not sure how much it's being used`*** - -
diff --git a/mdbook/src/Chapters/TrigFunctions.md b/mdbook/src/Chapters/TrigFunctions.md index 2e6fc4a..37149f5 100644 --- a/mdbook/src/Chapters/TrigFunctions.md +++ b/mdbook/src/Chapters/TrigFunctions.md @@ -4,8 +4,6 @@ RPNCalc does not consider itself a scientific calculator (at least not currently). However, it's certainly beyond a very basic calculator. The trigonometry commands listed here are very basic, but do fill a need if you need to do a few basic calculations. - - Lastly, I'm happy to add more capabilities if there is a desire (and an offer to help test). |Command|Description| diff --git a/mdbook/src/Chapters/UserDefinedFunctions.md b/mdbook/src/Chapters/UserDefinedFunctions.md index 82290ac..e026fc4 100644 --- a/mdbook/src/Chapters/UserDefinedFunctions.md +++ b/mdbook/src/Chapters/UserDefinedFunctions.md @@ -14,7 +14,7 @@ User defined functions can be deleted with the `func del NAME` command or you ca Functions are global and can work across any stack. They are saved in the preferences system and will be reloaded when RPNCalc starts. They are saved immediatly after you give a new recording a name and press enter. -When you execute a function, the steps of that function are executed one after the other. Therefore when you execute `undo` you will undo back through your function step by step. You do not `undo` the entire function in one command. Of course you can always run `undo NUM` where num is the steps to undo. +When you execute a function, the steps of that function are executed one after the other. Therefore when you execute `undo` you will undo back through your function step by step. You do not `undo` the entire function in one command. Of course you can always run `undo NUM` where `NUM` is the steps to undo. The following commands can be entered during a recording, but are not recorded. - frac @@ -30,7 +30,7 @@ The following commands can be entered during a recording, but are not recorded. |-------|-----------| |record on
rec on|Turn on recording. Most commands and numbers entered after record is enabled will be saved. There are some that are excluded from being recorded as detailed above| |record off
rec off| Turn off recording. The user will be prompted to enter in a name for this function and that name will be used to run it in the future. If you do not enter in a name the recording is canceled and nothing will be saved| -|func del NAME|Delete a saved function. The name must match the one given when saved. A list of functions can be viewed with `list func`. Undo will not recover a deleted function| +|func del `NAME`|Delete a saved function. The name must match the one given when saved. A list of functions can be viewed with `list func`. Undo will not recover a deleted function| |func delall|Delete all saved user defined functions. Please note that undo will not recover deleted functions| ### Example diff --git a/mdbook/src/Chapters/Wrapup.md b/mdbook/src/Chapters/Wrapup.md index 59c7cf6..439dd27 100644 --- a/mdbook/src/Chapters/Wrapup.md +++ b/mdbook/src/Chapters/Wrapup.md @@ -6,4 +6,4 @@ Well, if you've read this far you probably know more about RPNCalc than I do. I I'll continue to add new features as I think about them. If you have suggestions, issues, or ideas, the links to reach out to me are on the Introduction page. -Best wishes and happy calculating... \ No newline at end of file +Best wishes and happy reverse Polish notation calculating... \ No newline at end of file diff --git a/pom.xml b/pom.xml index 2e3ab04..7db9f50 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.fross rpncalc - 4.4.2 + 4.5.0 jar rpncalc diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index e879713..a7f3db7 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: rpncalc -version: '4.4.2' +version: '4.5.0' summary: The command line Reverse Polish Notation (RPN) calculator description: | RPNCalc is an easy to use command line based Reverse Polish diff --git a/src/main/java/org/fross/rpncalc/CommandParser.java b/src/main/java/org/fross/rpncalc/CommandParser.java index 2532bcf..3cf8aed 100644 --- a/src/main/java/org/fross/rpncalc/CommandParser.java +++ b/src/main/java/org/fross/rpncalc/CommandParser.java @@ -271,7 +271,7 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu /******************************************************************************* * Stack Operational Commands ******************************************************************************/ - // List - Supported commands are "stacks" | "mem" | "undo" + // List case "list": StackOperations.cmdList(calcStack, cmdInputParam); break; @@ -296,15 +296,14 @@ public static void Parse(StackObj calcStack, StackObj calcStack2, String cmdInpu StackOperations.cmdDebug(); break; - // Display Alignment - case "a": - case "align": - case "alignment": - try { - StackOperations.cmdAlign(cmdInputParam.charAt(0)); - } catch (StringIndexOutOfBoundsException ex) { - Output.printColorln(Ansi.Color.RED, "ERROR: Must provide an alignment value of 'l'eft, 'd'ecimal, or 'r'ight"); - } + // Set configuration options + case "set": + StackOperations.cmdSet(cmdInputParam); + break; + + // Reset configuration to defaults + case "reset": + StackOperations.cmdReset(); break; // Version diff --git a/src/main/java/org/fross/rpncalc/Help.java b/src/main/java/org/fross/rpncalc/Help.java index 4a222f0..0ca2247 100644 --- a/src/main/java/org/fross/rpncalc/Help.java +++ b/src/main/java/org/fross/rpncalc/Help.java @@ -54,9 +54,6 @@ public static void Display() { Output.printColorln(Ansi.Color.YELLOW, "\nCommand Line Options:"); Output.printColorln(Ansi.Color.WHITE, " -l Load a saved named stack. Create the stack if it does not exist"); Output.printColorln(Ansi.Color.WHITE, " -D Start in debug mode. Same as using the 'debug' command"); - Output.printColorln(Ansi.Color.WHITE, " -a [lrd] Alignment of numbers. (l)eft, (r)ight, or (d)ecmimal. Default: left"); - Output.printColorln(Ansi.Color.WHITE, " -m num Set the number of memory slots. Default value is 10"); - Output.printColorln(Ansi.Color.WHITE, " -w num Set Width of header / status line. Default is 70 characters"); Output.printColorln(Ansi.Color.WHITE, " -v Display version information as well as latest GitHub release"); Output.printColorln(Ansi.Color.WHITE, " -z Disable colorized output"); Output.printColorln(Ansi.Color.WHITE, " -h | ? Show this help information. Either key will work."); @@ -130,15 +127,14 @@ public static void Display() { Output.printColorln(Ansi.Color.WHITE, " ss Swap primary and secondary stack"); Output.printColorln(Ansi.Color.WHITE, " load NAME Load (or create if needed) a named stack"); Output.printColorln(Ansi.Color.WHITE, " import FILE Replace current stack with file contents (one number per line)"); - Output.printColorln(Ansi.Color.WHITE, " a [lrd] Set display alignment to be (l)eft, (r)ight, or (d)ecmial"); + Output.printColorln(Ansi.Color.WHITE, " set align l|d|r Set alignment of the stack display to 'l'eft, 'd'ecimal, or 'r'ight"); + Output.printColorln(Ansi.Color.WHITE, " set width num Set the width of the display to num"); + Output.printColorln(Ansi.Color.WHITE, " set memslots num Set the number of memory slots"); + Output.printColorln(Ansi.Color.WHITE, " reset Resets configurations set with 'set' back to defaults"); Output.printColorln(Ansi.Color.WHITE, " debug Toggle DEBUG mode on/off"); Output.printColorln(Ansi.Color.WHITE, " ver Display the current version"); Output.printColorln(Ansi.Color.WHITE, " h|? Show this help information. Either key will work."); Output.printColorln(Ansi.Color.WHITE, " cx|x|exit Exit Calculator. 'cx' will clear before exiting"); - Output.printColorln(Ansi.Color.YELLOW, "\nNotes:"); - Output.printColorln(Ansi.Color.WHITE, " - You can place an operand at the end of a number & execute in one step."); - Output.printColorln(Ansi.Color.WHITE, " Example adding two numbers: 2 3+ will produce 5."); - Output.printColorln(Ansi.Color.CYAN, " - See GitHub homepage (listed above) for more detailed usage instructions\n"); } } diff --git a/src/main/java/org/fross/rpncalc/Main.java b/src/main/java/org/fross/rpncalc/Main.java index d0ded46..9158f0f 100644 --- a/src/main/java/org/fross/rpncalc/Main.java +++ b/src/main/java/org/fross/rpncalc/Main.java @@ -30,6 +30,7 @@ import java.io.InputStream; import java.util.Properties; import java.util.Scanner; +import java.util.prefs.Preferences; import org.fross.library.Debug; import org.fross.library.Format; @@ -48,18 +49,24 @@ public class Main { // Class Constants (or pseudo constants) public static final String PROPERTIES_FILE = "app.properties"; - public static int PROGRAMWIDTH = 80; public static int PROGRAM_MINIMUM_WIDTH = 46; + public static int CONFIG_DEFAULT_PROGRAM_WIDTH = 80; + public static int CONFIG_DEFAULT_MEMORY_SLOTS = 10; + public static String CONFIG_DEFAULT_ALIGNMENT = "l"; public static String VERSION; public static String COPYRIGHT; // Class Variables - static char displayAlignment = 'l'; static Scanner scanner = new Scanner(System.in); static boolean ProcessCommandLoop = true; static StackObj calcStack = new StackObj(); static StackObj calcStack2 = new StackObj(); + // Configuration Values + static int configProgramWidth = -1; + static int configMemorySlots = -1; + static String configAlignment = "Error"; + /** * DisplayStatusLine(): Display the last line of the header and the separator line. This is a separate function given it * also inserts the loaded stack and spaces everything correctly. @@ -73,7 +80,7 @@ public static void DisplayStatusLine() { String sfUndo = String.format("Undo:%02d", calcStack.undoSize()); // Determine how many dashes to use after remove space for the undo and stack name - int numDashes = PROGRAMWIDTH - 2 - sfMem.length() - sfUndo.length() - StackManagement.QueryLoadedStack().length() - 11; + int numDashes = configProgramWidth - 2 - sfMem.length() - sfUndo.length() - StackManagement.QueryLoadedStack().length() - 11; // [Recording] appears if it's turned on. Make room if it's enabled if (UserFunctions.recordingEnabled == true) @@ -109,6 +116,7 @@ public static void main(String[] args) { String cmdInput = ""; // What the user enters String cmdInputCmd = ""; // The first field. The command. String cmdInputParam = ""; // The remaining string. Parameters + Preferences prefConfig = Preferences.userRoot().node("/org/fross/rpn/config"); // Persistent configuration settings // Process application level properties file // Update properties from Maven at build time: @@ -123,51 +131,33 @@ public static void main(String[] args) { Output.fatalError("Unable to read property file '" + PROPERTIES_FILE + "'", 3); } + // Add default values to the configuration if none exist + if (prefConfig.get("alignment", "none") == "none") { + prefConfig.put("alignment", CONFIG_DEFAULT_ALIGNMENT); + } + if (prefConfig.getInt("programwidth", -1) == -1) { + prefConfig.putInt("programwidth", CONFIG_DEFAULT_PROGRAM_WIDTH); + } + if (prefConfig.getInt("memoryslots", -1) == -1) { + prefConfig.putInt("memoryslots", CONFIG_DEFAULT_MEMORY_SLOTS); + } + + // Set configuration variables from preferences + configProgramWidth = prefConfig.getInt("programwidth", -1); + configMemorySlots = prefConfig.getInt("memoryslots", -1); + configAlignment = prefConfig.get("alignment", "Error"); + // Process Command Line Options and set flags where needed - Getopt optG = new Getopt("RPNCalc", args, "Dl:a:m:w:vzh?"); + Getopt optG = new Getopt("RPNCalc", args, "Dl:vzh?"); while ((optionEntry = optG.getopt()) != -1) { switch (optionEntry) { case 'D': // Debug Mode Debug.enable(); break; + case 'l': StackManagement.SetLoadedStack(String.valueOf(optG.getOptarg())); break; - case 'a': - if (optG.getOptarg().charAt(0) == 'r') { - Output.debugPrint("RIGHT alignment selected"); - displayAlignment = 'r'; - } else if (optG.getOptarg().charAt(0) == 'd') { - Output.debugPrint("DECIMAL alignment selected"); - displayAlignment = 'd'; - } else if (optG.getOptarg().charAt(0) == 'l') { - Output.debugPrint("LEFT alignment selected"); - displayAlignment = 'l'; - } else { - Output.printColorln(Ansi.Color.RED, "ERROR: The -a alignment must be either a 'l', 'r', or 'd'"); - Help.Display(); - System.exit(0); - break; - } - break; - - case 'm': - StackMemory.SetMaxMemorySlots(optG.getOptarg()); - break; - - case 'w': - try { - int newSize = Integer.parseInt(optG.getOptarg()); - if (newSize < PROGRAM_MINIMUM_WIDTH) { - Output.printColorln(Ansi.Color.RED, "Error. Minimum width is " + (PROGRAM_MINIMUM_WIDTH) + ". Setting width to that value."); - PROGRAMWIDTH = PROGRAM_MINIMUM_WIDTH; - } else { - PROGRAMWIDTH = newSize; - } - } catch (NumberFormatException ex) { - Output.fatalError("Incorrect width value provided: '" + optG.getOptarg() + "'", 2); - } - break; case 'v': // Display current program version and latest GitHub release Output.printColorln(Ansi.Color.WHITE, "RPNCalc Version: v" + VERSION); @@ -200,8 +190,9 @@ public static void main(String[] args) { Output.debugPrint("Command Line Options"); Output.debugPrint(" -D: " + Debug.query()); Output.debugPrint(" -l: " + StackManagement.QueryLoadedStack()); - Output.debugPrint(" -a: " + displayAlignment); - Output.debugPrint(" -w: " + PROGRAMWIDTH); + Output.debugPrint(" -a: " + configAlignment); + Output.debugPrint(" -w: " + configProgramWidth); + Output.debugPrint(" -m: " + configMemorySlots); Output.debugPrint(" Color Enabled: " + Output.queryColorEnabled()); // Restore the items in the memory slots during startup @@ -213,11 +204,11 @@ public static void main(String[] args) { Output.debugPrint("Elements in the Stack: " + calcStack.size()); // Display the initial program header information - Output.printColorln(Ansi.Color.CYAN, "+" + "-".repeat(PROGRAMWIDTH - 2) + "+"); - Output.printColorln(Ansi.Color.CYAN, Format.CenterText(PROGRAMWIDTH, "RPN Calculator v" + VERSION, "|", "|")); - Output.printColorln(Ansi.Color.CYAN, Format.CenterText(PROGRAMWIDTH, COPYRIGHT, "|", "|")); - Output.printColorln(Ansi.Color.CYAN, Format.CenterText(PROGRAMWIDTH, "Enter command 'h' for help details", "|", "|")); - Output.printColorln(Ansi.Color.CYAN, Format.CenterText(PROGRAMWIDTH, "", "|", "|")); + Output.printColorln(Ansi.Color.CYAN, "+" + "-".repeat(configProgramWidth - 2) + "+"); + Output.printColorln(Ansi.Color.CYAN, Format.CenterText(configProgramWidth, "RPN Calculator v" + VERSION, "|", "|")); + Output.printColorln(Ansi.Color.CYAN, Format.CenterText(configProgramWidth, COPYRIGHT, "|", "|")); + Output.printColorln(Ansi.Color.CYAN, Format.CenterText(configProgramWidth, "Enter command 'h' for help details", "|", "|")); + Output.printColorln(Ansi.Color.CYAN, Format.CenterText(configProgramWidth, "", "|", "|")); // Start Main Command Loop while (ProcessCommandLoop == true) { @@ -254,7 +245,7 @@ public static void main(String[] args) { Output.printColor(Ansi.Color.CYAN, sn); // Configure the alignment based on the -a: option - if (displayAlignment == 'd') { + if (configAlignment.compareTo("d") == 0) { // Put in spaces to align the decimals int decimalLocation = Format.Comma(calcStack.get(i)).indexOf("."); for (int k = 0; k < maxDigitsBeforeDecimal - decimalLocation; k++) { @@ -262,7 +253,7 @@ public static void main(String[] args) { } sn = Format.Comma(calcStack.get(i)); - } else if (displayAlignment == 'r') { + } else if (configAlignment.compareTo("r") == 0) { sn = String.format("%" + maxLenOfNumbers + "s", Format.Comma(calcStack.get(i))); } else { @@ -316,6 +307,5 @@ public static void main(String[] args) { StackManagement.SaveStack(calcStack, "1"); StackManagement.SaveStack(calcStack2, "2"); - } // End Main - -} // End Class + } +} \ No newline at end of file diff --git a/src/main/java/org/fross/rpncalc/StackConversions.java b/src/main/java/org/fross/rpncalc/StackConversions.java index 030e348..0c3cb22 100644 --- a/src/main/java/org/fross/rpncalc/StackConversions.java +++ b/src/main/java/org/fross/rpncalc/StackConversions.java @@ -134,9 +134,9 @@ public static void cmdFraction(StackObj calcStack, String param) { // Output the fractional display String stackHeader = "-Fraction (1/" + (denominator * gcd) + ")"; - Output.printColorln(Ansi.Color.YELLOW, "\n" + stackHeader + "-".repeat(Main.PROGRAMWIDTH - stackHeader.length())); + Output.printColorln(Ansi.Color.YELLOW, "\n" + stackHeader + "-".repeat(Main.configProgramWidth - stackHeader.length())); Output.printColorln(Ansi.Color.WHITE, " " + calcStack.peek() + " is approximately '" + integerPart + " " + numerator + "/" + denominator + "'"); - Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.PROGRAMWIDTH) + "\n"); + Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.configProgramWidth) + "\n"); } /** diff --git a/src/main/java/org/fross/rpncalc/StackMemory.java b/src/main/java/org/fross/rpncalc/StackMemory.java index 4f02bf2..a0b8cea 100644 --- a/src/main/java/org/fross/rpncalc/StackMemory.java +++ b/src/main/java/org/fross/rpncalc/StackMemory.java @@ -32,11 +32,8 @@ import org.fusesource.jansi.Ansi; public class StackMemory { - // Class Constants - private static final int DEFAULT_MEMORY_SLOTS = 10; // Number of memory slots available for mem command - // Class Variables - protected static Double[] memorySlots = new Double[DEFAULT_MEMORY_SLOTS]; + protected static Double[] memorySlots = new Double[Main.configMemorySlots]; /** * SetMaxMemorySlots(): Sets the number of memory slot available to be used @@ -44,19 +41,24 @@ public class StackMemory { * @param numSlots */ public static void SetMaxMemorySlots(String slots) { + Preferences prefConfig = Preferences.userRoot().node("/org/fross/rpn/config"); try { - int numSlots = Integer.parseInt(slots); + int requestedSlots = Integer.parseInt(slots); // Ensure we always have at least one memory slot - if (numSlots >= 1) { - memorySlots = new Double[numSlots]; + if (requestedSlots >= 1) { + memorySlots = new Double[requestedSlots]; } else { Output.printColorln(Ansi.Color.RED, "Error: There must be at least 1 memory slot. Setting to 1."); memorySlots = new Double[1]; } + + Output.printColorln(Ansi.Color.CYAN, "Memory Slots set to '" + slots + "'"); + Main.configMemorySlots = Integer.parseInt(slots); + prefConfig.putInt("memoryslots", Integer.parseInt(slots)); } catch (NumberFormatException ex) { - Output.fatalError("Could not set the number of memory slots to '" + slots + "'", 4); + Output.printColorln(Ansi.Color.RED, "Error: Could not set the number of memory slots to '" + slots + "'"); } } diff --git a/src/main/java/org/fross/rpncalc/StackOperations.java b/src/main/java/org/fross/rpncalc/StackOperations.java index b24dc22..a32215a 100644 --- a/src/main/java/org/fross/rpncalc/StackOperations.java +++ b/src/main/java/org/fross/rpncalc/StackOperations.java @@ -38,21 +38,6 @@ import org.fusesource.jansi.Ansi; public class StackOperations { - /** - * cmdAlign(alignment): Set display alignment to l(eft), r(ight), or d(ecimal) - * - * @param al - */ - public static void cmdAlign(char al) { - // Validate we have one of the right values - if (al != 'l' && al != 'd' && al != 'r') { - Output.printColorln(Ansi.Color.RED, "ERROR: Must provide an alignment value of 'l'eft, 'd'ecimal, or 'r'ight"); - } else { - Output.debugPrint("Setting display alignment to: " + al); - Main.displayAlignment = al; - } - } - /** * cmdDebug(): Toggle debug setting * @@ -82,35 +67,36 @@ public static void cmdList(StackObj calcStack, String arg) { case "stack": String[] stks = StackManagement.QueryStacks(); - Output.printColorln(Ansi.Color.YELLOW, "\n-Saved Stacks" + "-".repeat(Main.PROGRAMWIDTH - 13)); + Output.printColorln(Ansi.Color.YELLOW, "\n-Saved Stacks" + "-".repeat(Main.configProgramWidth - 13)); for (int i = 0; i < stks.length; i++) { String sn = String.format("%02d: %s", i, stks[i]); Output.printColorln(Ansi.Color.CYAN, sn); } - Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.PROGRAMWIDTH) + "\n"); + Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.configProgramWidth) + "\n"); break; case "mem": - Output.printColorln(Ansi.Color.YELLOW, "\n-Memory Slots" + "-".repeat(Main.PROGRAMWIDTH - 13)); + Output.printColorln(Ansi.Color.YELLOW, "\n-Memory Slots" + "-".repeat(Main.configProgramWidth - 13)); for (int i = 0; i < StackMemory.memorySlots.length; i++) { Output.printColorln(Ansi.Color.CYAN, "Slot #" + i + ": " + StackMemory.memorySlots[i]); } - Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.PROGRAMWIDTH) + "\n"); + Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.configProgramWidth) + "\n"); break; case "undo": - Output.printColorln(Ansi.Color.YELLOW, "\n-Undo Stack for Stack #: " + StackManagement.QueryCurrentStackNum() + "-".repeat(Main.PROGRAMWIDTH - 26)); + Output.printColorln(Ansi.Color.YELLOW, + "\n-Undo Stack for Stack #: " + StackManagement.QueryCurrentStackNum() + "-".repeat(Main.configProgramWidth - 26)); for (int i = 0; i < calcStack.undoSize(); i++) { String sn = String.format("%02d: %s", i + 1, calcStack.undoGet(i)); Output.printColorln(Ansi.Color.CYAN, sn); } - Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.PROGRAMWIDTH) + "\n"); + Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.configProgramWidth) + "\n"); break; case "function": case "func": try { - Output.printColorln(Ansi.Color.YELLOW, "\n-User Defined Functions" + "-".repeat(Main.PROGRAMWIDTH - 23)); + Output.printColorln(Ansi.Color.YELLOW, "\n-User Defined Functions" + "-".repeat(Main.configProgramWidth - 23)); Preferences p = Preferences.userRoot().node(UserFunctions.PREFS_PATH_FUNCTIONS); // Loop through each function (child of the root) and display the details @@ -126,7 +112,7 @@ public static void cmdList(StackObj calcStack, String arg) { Output.printColorln(Ansi.Color.RED, "Error reading preferences system"); return; } - Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.PROGRAMWIDTH) + "\n"); + Output.printColorln(Ansi.Color.YELLOW, "-".repeat(Main.configProgramWidth) + "\n"); break; default: @@ -153,6 +139,84 @@ public static void cmdLoad(StackObj calcStack, StackObj calcStack2, String stack calcStack2 = StackManagement.RestoreStack("2"); } + /** + * set(): Set configuration Options + * + */ + public static void cmdSet(String arg) { + Preferences prefConfig = Preferences.userRoot().node("/org/fross/rpn/config"); + String[] argParse = null; + String command = ""; + String value = ""; + + // Parse the provided argument into a command and value + try { + argParse = arg.split(" "); + command = argParse[0]; + value = argParse[1]; + + Output.debugPrint("Set Command: '" + command + "'"); + Output.debugPrint("Set Value: '" + value + "'"); + + switch (command.toLowerCase()) { + case "align": + case "alignment": + if (value.toLowerCase().compareTo("l") != 0 && value.toLowerCase().compareTo("d") != 0 && value.toLowerCase().compareTo("r") != 0) { + Output.printColorln(Ansi.Color.RED, "Alignment can only be 'l'eft, 'd'ecimal, or 'r'ight. See help for mem command usage"); + return; + } + Main.configAlignment = value; + prefConfig.put("alignment", value); + Output.printColorln(Ansi.Color.CYAN, "Alignment set to '" + value + "'"); + break; + + case "width": + if (Integer.parseInt(value) < Main.PROGRAM_MINIMUM_WIDTH) { + Output.printColorln(Ansi.Color.RED, "Error. Minimum width is " + (Main.PROGRAM_MINIMUM_WIDTH) + ". Setting width to that value."); + value = "" + Main.PROGRAM_MINIMUM_WIDTH; + } + Main.configProgramWidth = Integer.parseInt(value); + prefConfig.putInt("programwidth", Integer.parseInt(value)); + Output.printColorln(Ansi.Color.CYAN, "Program Width set to '" + value + "'"); + break; + + case "mem": + case "memslots": + case "memoryslots": + StackMemory.SetMaxMemorySlots(value); + break; + + default: + Output.printColorln(Ansi.Color.RED, "ERROR: Unknown set command: '" + command + "'"); + return; + } + + } catch (Exception ex) { + Output.printColorln(Ansi.Color.RED, "Error parsing set command: 'set " + arg + "' See help for mem command usage"); + return; + } + } + + /** + * reset(): Resets the configuration variables back to default + */ + public static void cmdReset() { + Output.printColorln(Ansi.Color.CYAN, "Alignment, Width, and Memory slots reset to default values"); + Preferences prefConfig = Preferences.userRoot().node("/org/fross/rpn/config"); + + // Reset Alignment + prefConfig.put("alignment", Main.CONFIG_DEFAULT_ALIGNMENT); + Main.configAlignment = Main.CONFIG_DEFAULT_ALIGNMENT; + + // Reset Width + prefConfig.putInt("programwidth", Main.CONFIG_DEFAULT_PROGRAM_WIDTH); + Main.configProgramWidth = Main.CONFIG_DEFAULT_PROGRAM_WIDTH; + + // Reset the number of Memory Slots + prefConfig.putInt("memoryslots", Main.CONFIG_DEFAULT_MEMORY_SLOTS); + Main.configMemorySlots = Main.CONFIG_DEFAULT_MEMORY_SLOTS; + } + /** * cmdSwapStack(): Swap the primary and secondary stacks *