<commit_before>// (C) 1990-2016.  <NAME>.  Solomon.  All rights reserved.
// rpnterm.go
package main

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"log"
	"os"
	"os/exec" // for the clear screen functions.
	"runtime"
	"strconv"
	"strings"
	"time"
	"timlibg"

	//	"github.com/nsf/termbox-go"
	//
	"getcommandline"
	"hpcalc"
	"tokenize"

	"github.com/nsf/termbox-go"
)

const LastAltered = "14 Apr 2019"
const InputPrompt = " Enter calculation, HELP or (Q)uit to exit: "

type Register struct {
	Value float64
	Name  string
}

var Storage [36]Register // 0 ..  9, a ..  z
var DisplayTape, stringslice []string
var Divider string
var clear map[string]func()

var StartCol, StartRow, sigfig, MaxRow, MaxCol, TitleRow, StackRow, RegRow, OutputRow, DisplayCol, PromptRow, outputmode, n int
var BrightYellow, BrightCyan, Black termbox.Attribute

const SpaceFiller = "     |     "

const ( // output modes
	outputfix = iota
	outputfloat
	outputgen
)

const Storage1FileName = "RPNStorageName.gob" // Allows for a rotation of Storage files, in case of a mistake.
const Storage2FileName = "RPNStorageName2.gob"
const Storage3FileName = "RPNStorageName3.gob"
const DisplayTapeFilename = "displaytape.txt"
const TextFilenameOut = "rpntermoutput.txt"
const TextFilenameIn = "rpnterminput.txt"
const HelpFileName = "rpnhelp.txt"

// runtime.GOOS returns either linux or windows.  I have not tested mac.  I want either $HOME or %userprofile to set the write dir.

/*
This module uses the HPCALC module to simulate an RPN type calculator.
REVISION HISTORY
----------------
 1 Dec 89 -- Changed prompt.
24 Dec 91 -- Converted to M-2 V 4.00.  Changed params to GETRESULT.
25 Jul 93 -- Output result without trailing insignificant zeros,
		                   imported UL2, and changed prompt again.
3 Mar 96 -- Fixed bug in string display if real2str fails because
		                   number is too large (ie, Avogadro's Number).
18 May 03 -- First Win32 version.  And changed name.
1 Apr 13 -- Back to console mode pgm that will read from the cmdline.  Intended to be a quick and useful little utility.
		                   And will save/restore the stack to/from a file.
2 May 13 -- Will use console mode flag for HPCALC, so it will write to console instead of the terminal module routines.
		                   And I now have the skipline included in MiscStdInOut so it is removed from here.
15 Oct 13 -- Now writing for gm2 under linux.
22 Jul 14 -- Converting to Ada.
 6 Dec 14 -- Converting to cpp.
20 Dec 14 -- Added macros for date and time last compiled.
31 Dec 14 -- Started coding HOL command.
 1 Jan 15 -- After getting HOL command to work, I did more fiddling to further understand c-strings and c++ string class.
10 Jan 15 -- Playing with string conversions and number formatting.
 5 Nov 15 -- Added the RECIP, CURT, VOL commands to hpcalc.cpp
22 Nov 15 -- Noticed that T1 and T2 stack operations are not correct.  This effects HP2cursed and rpnc.
13 Apr 16 -- Adding undo and redo commands, which operate on the entire stack not just X register.
 2 Jul 16 -- Fixed help to include PI command, and changed pivot for JUL command.  See hpcalcc.cpp
 7 Jul 16 -- Added UP command to hpcalcc.cpp
 8 Jul 16 -- Added display of stack dump to always happen, and a start up message.
22 Aug 16 -- Started conversion to Go, as rpn.go.
 8 Sep 16 -- Finished coding rpn.go, started 26 Aug 16 as rpng.go, adding functionality from hppanel, ie, persistant storage, a display tape and operator substitutions = or + and ; for *.
11 Sep 16 -- Changed stack and storage files to use gob package and only use one Storage file.
 1 Oct 16 -- Made the stack display when the program starts.
 4 Oct 16 -- Made the storage registers display when the program starts.
 7 Oct 16 -- Changed default dump to DUMPFIXED.   Input is now using splitfunc by space delimited words instead of whole lines.
		                    Conversion to ScanWords means I cannot get an empty string back unless ^C or ^D.  So needed (Q)uit, EXIT, STOP.
 8 Oct 16 -- Updated the prompt to say (Q)uit to exit instead of Enter to exit, and sto command calls WriteRegToScreen()
 9 Oct 16 -- Added ability to enter hex numbers like in C, or GoLang, etc, using the "0x" prefix.
21 Oct 16 -- Decided that sto command should not also dump stack, as the stack does not change.
28 Oct 16 -- Will clear screen in between command calls.  I took this out when I did next revision.
30 Oct 16 -- Decided to rename this to rpnterm, and will now start to use termbox-go.
31 Oct 16 -- Debugged GetInputString(x,y int) string
 4 Nov 16 -- Changed hpcalc.go to return a string slice for everything.  Added outputmodes.
 6 Nov 16 -- Windows returns <backspace> code of 8, which is std ASCII.  Seems linux does not do this.
23 Nov 16 -- Will clear screen before calling init termbox-go, to see if that helps some of the irregularities
		                    I've found with termbox-go.  It doesn't help.
11 Dec 16 -- Fixed bug in GetRegIdx when out of range char is passed in.
13 Jan 17 -- Removed stop as an exit command, as it meant that reg p could not be stored into.
23 Feb 17 -- Added "?" as equivalent to "help"
 4 Apr 17 -- Noticed that HardClearScreen is called before MaxRow is set.  I fixed this by moving the Size call.
		                  And I commented out a fmt.Println() call that didn't do anything anyway, and is ignored on Windows.
16 Aug 17 -- Added code from when.go to use timestamp on executable as link time.
25 Feb 18 -- PrimeFactorMemoized added.
 6 Apr 18 -- Wrote code to save DisplayTape as a text file.
22 Aug 18 -- learning about code folding
 2 Dec 18 -- Trying GoLand for editing this code now.  And exploring adding string names for the registers.
               Need to code name command, display these names, deal w/ the reg file.  Code a converter.
 4 Dec 18 -- Made STO also ask for NAME.  And used ClearLine when the OutputLine is increased.
 5 Dec 18 -- Help command will print from here those commands that are processed here, and from hpcalc those that are processed there.
 6 Dec 18 -- Added "today" for reg name string, and it will plug in today's date as a string.
 8 Dec 18 -- Added StrSubst for register name operation, so that = or - becomes a space.  Note that = becomes + in GetInputString.
10 Dec 18 -- Register 0 will not ask for name, to match my workflow using these registers.
17 Dec 18 -- Starting to code :w and :r to/from text files, intended for clipboard access via vim or another text editor.
18 Dec 18 -- Fixed help to show :r, rd, read commands.
31 Jan 19 -- Added prefix of  :w to write a text file, and prefix of :R to read a text file.
13 Apr 19 -- If on a small screen, like the System76 laptop, there are too many help lines, so it panics.  Started to fix that.
*/

func main() {
	var INBUF, HomeDir string

	var x int
	//  var Holidays holidaycalc.HolType;
	//  var fgYellow,fgCyan termbox.Attribute;

	var Stk hpcalc.StackType // used when time to write out the stack upon exit.
	var err error

	ClearScreen() // ClearScreen before termbox.init fcn, to see if this helps.
	fmt.Println()
	//  fmt.Println("  I hope this helps.  But it likely won't.  ");  It didn't help.  I'm commenting it
	//  out, finally.
	fmt.Println()
	fmt.Println()

	termerr := termbox.Init()
	if termerr != nil {
		log.Println(" TermBox init failed.")
		panic(termerr)
	}
	defer termbox.Close()
	BrightYellow = termbox.ColorYellow | termbox.AttrBold
	BrightCyan = termbox.ColorCyan | termbox.AttrBold
	Black = termbox.ColorBlack
	err = termbox.Clear(BrightYellow, Black)
	check(err)
	e := termbox.Clear(Black, Black)
	check(e)
	e = termbox.Flush()
	check(e)
	MaxCol, MaxRow = termbox.Size()
	HardClearScreen() // I think there is a bug in termbox.

	stringslice = make([]string, 0, 35)
	sigfig = -1 // now only applies to WriteRegToScreen
	StartRow := 0
	StartCol := 0
	outputmode = 0

	if runtime.GOOS == "linux" {
		HomeDir = os.Getenv("HOME")
		StartRow = 2 // Could this be the source of my problems with screen updating correctly?
		StartCol = 1 // So I'll make it the same as under Windows, and I'll see what's going on, maybe?
	} else if runtime.GOOS == "windows" {
		HomeDir = os.Getenv("userprofile")
		StartRow = 2
		StartCol = 1
	} else { // then HomeDir will be empty.
		Print_tb(StartCol, StartRow+20, BrightYellow, Black, " runtime.GOOS does not say linux or windows.  Is this a Mac?")
	}
	Divider = strings.Repeat("-", MaxCol-StartCol)

	x = StartCol
	TitleRow = StartRow
	StackRow = StartRow + 4
	RegRow = StackRow + 12
	OutputRow = RegRow + 10
	DisplayCol = MaxCol/2 + 2
	PromptRow = OutputRow - 1

	Printf_tb(x, TitleRow, BrightCyan, Black, " HP-type RPN calculator written in Go.  Last altered %s", LastAltered)
	//  Printf_tb(x,TitleRow+1,BrightCyan,Black," GOOS = %s,  HomeDir = %s,  ARCH= %s. MaxCol = %d, MaxRow = %d",runtime.GOOS,HomeDir,runtime.GOARCH,MaxCol,MaxRow);
	Printf_tb(StartCol, TitleRow+1, BrightYellow, Black,
		" StartCol=%d,StartRow=%d,MaxCol=%d,MaxRow=%d,TitleRow=%d,StackRow=%d,RegRow=%d,OutputRow=%d,PromptRow=%d", StartCol, StartRow, MaxCol, MaxRow, TitleRow, StackRow, RegRow, OutputRow, PromptRow)
	Printf_tb(StartCol, MaxRow-1, BrightCyan, Black, Divider)
	e = termbox.Flush()
	check(e)

	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	Printf_tb(0, TitleRow+2, BrightCyan, Black, "%s was last linked on %s.  Full executable is %s.", ExecFI.Name(), LastLinkedTimeStamp, execname)

	DisplayTape = make([]string, 0, 100)
	theFileExists := true

	StorageFullFilenameSlice := make([]string, 5)
	StorageFullFilenameSlice[0] = HomeDir
	StorageFullFilenameSlice[1] = string(os.PathSeparator)
	StorageFullFilenameSlice[2] = Storage1FileName
	StorageFullFilename := strings.Join(StorageFullFilenameSlice, "")

	Storage2FullFilenameSlice := make([]string, 5)
	Storage2FullFilenameSlice[0] = HomeDir
	Storage2FullFilenameSlice[1] = string(os.PathSeparator)<commit_msg>04/14/2019 11:43:17 AM	modified:   rpnterm/rpnterm.go<commit_after>// (C) 1990-2016.  <NAME>.  Solomon.  All rights reserved.
// rpnterm.go
package main

import (
	"bufio"
	"encoding/gob"
	"fmt"
	"log"
	"os"
	"os/exec" // for the clear screen functions.
	"runtime"
	"strconv"
	"strings"
	"time"
	"timlibg"

	//	"github.com/nsf/termbox-go"
	//
	"getcommandline"
	"hpcalc"
	"tokenize"

	"github.com/nsf/termbox-go"
)

const LastAltered = "14 Apr 2019"
const InputPrompt = " Enter calculation, HELP or (Q)uit to exit: "

type Register struct {
	Value float64
	Name  string
}

var Storage [36]Register // 0 ..  9, a ..  z
var DisplayTape, stringslice []string
var Divider string
var clear map[string]func()

var StartCol, StartRow, sigfig, MaxRow, MaxCol, TitleRow, StackRow, RegRow, OutputRow, DisplayCol, PromptRow, outputmode, n int
var BrightYellow, BrightCyan, Black termbox.Attribute

const SpaceFiller = "     |     "

const ( // output modes
	outputfix = iota
	outputfloat
	outputgen
)

const Storage1FileName = "RPNStorageName.gob" // Allows for a rotation of Storage files, in case of a mistake.
const Storage2FileName = "RPNStorageName2.gob"
const Storage3FileName = "RPNStorageName3.gob"
const DisplayTapeFilename = "displaytape.txt"
const TextFilenameOut = "rpntermoutput.txt"
const TextFilenameIn = "rpnterminput.txt"
const HelpFileName = "helprpn.txt"

// runtime.GOOS returns either linux or windows.  I have not tested mac.  I want either $HOME or %userprofile to set the write dir.

/*
This module uses the HPCALC module to simulate an RPN type calculator.
REVISION HISTORY
----------------
 1 Dec 89 -- Changed prompt.
24 Dec 91 -- Converted to M-2 V 4.00.  Changed params to GETRESULT.
25 Jul 93 -- Output result without trailing insignificant zeros,
		                   imported UL2, and changed prompt again.
3 Mar 96 -- Fixed bug in string display if real2str fails because
		                   number is too large (ie, Avogadro's Number).
18 May 03 -- First Win32 version.  And changed name.
1 Apr 13 -- Back to console mode pgm that will read from the cmdline.  Intended to be a quick and useful little utility.
		                   And will save/restore the stack to/from a file.
2 May 13 -- Will use console mode flag for HPCALC, so it will write to console instead of the terminal module routines.
		                   And I now have the skipline included in MiscStdInOut so it is removed from here.
15 Oct 13 -- Now writing for gm2 under linux.
22 Jul 14 -- Converting to Ada.
 6 Dec 14 -- Converting to cpp.
20 Dec 14 -- Added macros for date and time last compiled.
31 Dec 14 -- Started coding HOL command.
 1 Jan 15 -- After getting HOL command to work, I did more fiddling to further understand c-strings and c++ string class.
10 Jan 15 -- Playing with string conversions and number formatting.
 5 Nov 15 -- Added the RECIP, CURT, VOL commands to hpcalc.cpp
22 Nov 15 -- Noticed that T1 and T2 stack operations are not correct.  This effects HP2cursed and rpnc.
13 Apr 16 -- Adding undo and redo commands, which operate on the entire stack not just X register.
 2 Jul 16 -- Fixed help to include PI command, and changed pivot for JUL command.  See hpcalcc.cpp
 7 Jul 16 -- Added UP command to hpcalcc.cpp
 8 Jul 16 -- Added display of stack dump to always happen, and a start up message.
22 Aug 16 -- Started conversion to Go, as rpn.go.
 8 Sep 16 -- Finished coding rpn.go, started 26 Aug 16 as rpng.go, adding functionality from hppanel, ie, persistant storage, a display tape and operator substitutions = or + and ; for *.
11 Sep 16 -- Changed stack and storage files to use gob package and only use one Storage file.
 1 Oct 16 -- Made the stack display when the program starts.
 4 Oct 16 -- Made the storage registers display when the program starts.
 7 Oct 16 -- Changed default dump to DUMPFIXED.   Input is now using splitfunc by space delimited words instead of whole lines.
		                    Conversion to ScanWords means I cannot get an empty string back unless ^C or ^D.  So needed (Q)uit, EXIT, STOP.
 8 Oct 16 -- Updated the prompt to say (Q)uit to exit instead of Enter to exit, and sto command calls WriteRegToScreen()
 9 Oct 16 -- Added ability to enter hex numbers like in C, or GoLang, etc, using the "0x" prefix.
21 Oct 16 -- Decided that sto command should not also dump stack, as the stack does not change.
28 Oct 16 -- Will clear screen in between command calls.  I took this out when I did next revision.
30 Oct 16 -- Decided to rename this to rpnterm, and will now start to use termbox-go.
31 Oct 16 -- Debugged GetInputString(x,y int) string
 4 Nov 16 -- Changed hpcalc.go to return a string slice for everything.  Added outputmodes.
 6 Nov 16 -- Windows returns <backspace> code of 8, which is std ASCII.  Seems linux does not do this.
23 Nov 16 -- Will clear screen before calling init termbox-go, to see if that helps some of the irregularities
		                    I've found with termbox-go.  It doesn't help.
11 Dec 16 -- Fixed bug in GetRegIdx when out of range char is passed in.
13 Jan 17 -- Removed stop as an exit command, as it meant that reg p could not be stored into.
23 Feb 17 -- Added "?" as equivalent to "help"
 4 Apr 17 -- Noticed that HardClearScreen is called before MaxRow is set.  I fixed this by moving the Size call.
		                  And I commented out a fmt.Println() call that didn't do anything anyway, and is ignored on Windows.
16 Aug 17 -- Added code from when.go to use timestamp on executable as link time.
25 Feb 18 -- PrimeFactorMemoized added.
 6 Apr 18 -- Wrote code to save DisplayTape as a text file.
22 Aug 18 -- learning about code folding
 2 Dec 18 -- Trying GoLand for editing this code now.  And exploring adding string names for the registers.
               Need to code name command, display these names, deal w/ the reg file.  Code a converter.
 4 Dec 18 -- Made STO also ask for NAME.  And used ClearLine when the OutputLine is increased.
 5 Dec 18 -- Help command will print from here those commands that are processed here, and from hpcalc those that are processed there.
 6 Dec 18 -- Added "today" for reg name string, and it will plug in today's date as a string.
 8 Dec 18 -- Added StrSubst for register name operation, so that = or - becomes a space.  Note that = becomes + in GetInputString.
10 Dec 18 -- Register 0 will not ask for name, to match my workflow using these registers.
17 Dec 18 -- Starting to code :w and :r to/from text files, intended for clipboard access via vim or another text editor.
18 Dec 18 -- Fixed help to show :r, rd, read commands.
31 Jan 19 -- Added prefix of  :w to write a text file, and prefix of :R to read a text file.
13 Apr 19 -- If on a small screen, like the System76 laptop, there are too many help lines, so it panics.  Started to fix that.
14 Apr 19 -- And took out a debug line at top that I should have done shortly after debugging this routine.
*/

func main() {
	var INBUF, HomeDir string

	var x int
	//  var Holidays holidaycalc.HolType;
	//  var fgYellow,fgCyan termbox.Attribute;

	var Stk hpcalc.StackType // used when time to write out the stack upon exit.
	var err error

	ClearScreen() // ClearScreen before termbox.init fcn, to see if this helps.
	fmt.Println()
	//  fmt.Println("  I hope this helps.  But it likely won't.  ");  It didn't help.  I'm commenting it
	//  out, finally.
	fmt.Println()
	fmt.Println()

	termerr := termbox.Init()
	if termerr != nil {
		log.Println(" TermBox init failed.")
		panic(termerr)
	}
	defer termbox.Close()
	BrightYellow = termbox.ColorYellow | termbox.AttrBold
	BrightCyan = termbox.ColorCyan | termbox.AttrBold
	Black = termbox.ColorBlack
	err = termbox.Clear(BrightYellow, Black)
	check(err)
	e := termbox.Clear(Black, Black)
	check(e)
	e = termbox.Flush()
	check(e)
	MaxCol, MaxRow = termbox.Size()
	HardClearScreen() // I think there is a bug in termbox.

	stringslice = make([]string, 0, 35)
	sigfig = -1 // now only applies to WriteRegToScreen
	StartRow := 0
	StartCol := 0
	outputmode = 0

	if runtime.GOOS == "linux" {
		HomeDir = os.Getenv("HOME")
		StartRow = 2 // Could this be the source of my problems with screen updating correctly?
		StartCol = 1 // So I'll make it the same as under Windows, and I'll see what's going on, maybe?
	} else if runtime.GOOS == "windows" {
		HomeDir = os.Getenv("userprofile")
		StartRow = 2
		StartCol = 1
	} else { // then HomeDir will be empty.
		Print_tb(StartCol, StartRow+20, BrightYellow, Black, " runtime.GOOS does not say linux or windows.  Is this a Mac?")
	}
	Divider = strings.Repeat("-", MaxCol-StartCol)

	x = StartCol
	TitleRow = StartRow
	StackRow = StartRow + 4
	RegRow = StackRow + 12
	OutputRow = RegRow + 10
	DisplayCol = MaxCol/2 + 2
	PromptRow = OutputRow - 1

	Printf_tb(x, TitleRow, BrightCyan, Black, " HP-type RPN calculator written in Go.  Last altered %s", LastAltered)
	// Printf_tb(x,TitleRow+1,BrightCyan,Black," GOOS = %s,  HomeDir = %s,  ARCH= %s. MaxCol = %d, MaxRow = %d",runtime.GOOS,HomeDir,runtime.GOARCH,MaxCol,MaxRow);
	// Printf_tb(StartCol, TitleRow+1, BrightYellow, Black, " StartCol=%d,StartRow=%d,MaxCol=%d,MaxRow=%d,TitleRow=%d,StackRow=%d,RegRow=%d,OutputRow=%d,PromptRow=%d", StartCol, StartRow, MaxCol, MaxRow, TitleRow, StackRow, RegRow, OutputRow, PromptRow)
	Printf_tb(StartCol, MaxRow-1, BrightCyan, Black, Divider)
	e = termbox.Flush()
	check(e)

	execname, _ := os.Executable()
	ExecFI, _ := os.Stat(execname)
	LastLinkedTimeStamp := ExecFI.ModTime().Format("Mon Jan 2 2006 15:04:05 MST")
	Printf_tb(0, TitleRow+2, BrightCyan, Black, "%s was last linked on %s.  Full executable is %s.", ExecFI.Name(), LastLinkedTimeStamp, execname)

	DisplayTape = make([]string, 0, 100)
	theFileExists := true

	StorageFullFilenameSlice := make([]string, 5)
	StorageFullFilenameSlice[0] = HomeDir
	StorageFullFilenameSlice[1] = string(os.PathSeparator)
	StorageFullFilenameSlice[2] = Storage1FileName
	StorageFullFilename := strings.Join(StorageFullFilenameSlice, "")

	Storage2FullFilenameSlice := make([]string, 5)
	Storage2FullFilenameSlice[0] = HomeDir
	Storage2FullFilenameSlice[1] = string(os.PathSeparator)
{'fraction_non_alphanumeric': 0.08698684734954165, 'fraction_numerical': 0.029294539657233956, 'mean_word_length': 3.400043840420868, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1503213', 'n_tokens_mistral': 6765, 'n_tokens_neox': 6098, 'n_words': 2768}