Skip to content

Commit

Permalink
Enable Logging and Terminal configuration from IDE
Browse files Browse the repository at this point in the history
This allows the user to enable logging from within the IDE. When they do
this, environment variables will be set to turn on logging to console
at Information level with a default set of logging scopes. The program
is started with a separate console to allow the logging to be viewed
separate from the program (unless the program is $Console:Only and has
no graphical view).

The terminal configuration is specific for Linux and used for both
logging output and $Console programs. It allows the user to configure a
terminal emulator to be used for running programs, allowing the output
of $Console programs to be viewed from it as well as logging output when
enabled.

When no terminal is configured we have logic that checks a list of
common terminal emulators to see if any of them are availiable, and if
so uses a known good configuration for them. The user can change
this via a GUI dialog.
  • Loading branch information
mkilgore committed Nov 27, 2024
1 parent b1eb01e commit 07758bd
Show file tree
Hide file tree
Showing 6 changed files with 306 additions and 26 deletions.
2 changes: 2 additions & 0 deletions source/ide/config/cfg_global.bas
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ DIM SHARED StripDebugSymbols AS LONG
DIM SHARED OptimizeCppProgram AS LONG
DIM SHARED GenerateLicenseFile AS LONG
DIM SHARED UseGuiDialogs AS _UNSIGNED LONG
DIM SHARED DefaultTerminal AS STRING
DIM SHARED LoggingEnabled AS _UNSIGNED LONG

'===== Define and check settings location =====================================
ConfigFolder$ = "settings" 'relative config location inside the qb64pe main folder
Expand Down
8 changes: 8 additions & 0 deletions source/ide/config/cfg_methods.bas
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ SUB ReadInitialConfig

UseGuiDialogs = ReadWriteBooleanSettingValue%(generalSettingsSection$, "UseGuiDialogs", -1)

DefaultTerminal = ReadWriteStringSettingValue$(generalSettingsSection$, "DefaultTerminal", "")
If DefaultTerminal = "" AND OS$ = "LNX" AND MacOSX = 0 Then
DefaultTerminal = findWorkingTerminal$
WriteConfigSetting generalSettingsSection$, "DefaultTerminal", DefaultTerminal
End If

LoggingEnabled = ReadWriteBooleanSettingValue%(generalSettingsSection$, "LoggingEnabled", 0)

'--- Mouse settings
result = ReadConfigSetting(mouseSettingsSection$, "SwapMouseButton", value$)
IF UCASE$(value$) = "TRUE" OR VAL(value$) = -1 THEN
Expand Down
1 change: 1 addition & 0 deletions source/ide/ide_global.bas
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ DIM SHARED FileMenuExportAs AS INTEGER, FileMenuExportAsSubMenuID AS INTEGER
DIM SHARED ViewMenuCompilerWarnings AS INTEGER
DIM SHARED RunMenuID AS INTEGER, RunMenuSaveExeWithSource AS INTEGER, brackethighlight AS INTEGER
DIM SHARED GenerateLicenseEnableMenu AS INTEGER
DIM SHARED LoggingEnableMenu AS INTEGER
DIM SHARED OptionsMenuGuiDialogs AS INTEGER
DIM SHARED DebugMenuID AS INTEGER, DebugMenuCallStack AS INTEGER, DebugMenuWatchListToConsole AS INTEGER
DIM SHARED DebugMenuAutoAddCommand AS INTEGER
Expand Down
181 changes: 181 additions & 0 deletions source/ide/ide_methods.bas
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,13 @@ FUNCTION ide2 (ignore)
menuDesc$(m, i - 1) = "Sets string returned by COMMAND$ function"
menu$(m, i) = "-": i = i + 1

LoggingEnableMenu = i
menu$(m, i) = "Display #Logging Output": i = i + 1
menuDesc$(m, i - 1) = "Turns on logging output and displays it in a console window"
IF LoggingEnabled THEN
menu$(RunMenuID, LoggingEnableMenu) = CHR$(7) + menu$(RunMenuID, LoggingEnableMenu)
END IF

RunMenuSaveExeWithSource = i
menu$(m, i) = "Output EXE to Source #Folder": i = i + 1
menuDesc$(m, i - 1) = "Toggles compiling program to QB64-PE's folder or to source folder"
Expand All @@ -320,6 +327,10 @@ FUNCTION ide2 (ignore)
IF GenerateLicenseFile THEN
menu$(RunMenuID, GenerateLicenseEnableMenu) = CHR$(7) + menu$(RunMenuID, GenerateLicenseEnableMenu)
END IF
IF os$ = "LNX" AND MacOSX = 0 THEN
menu$(m, i) = "Change #Terminal": i = i + 1
menuDesc$(m, i - 1) = "Configure the terminal used for $CONSOLE and logging output"
END IF
menu$(m, i) = "-": i = i + 1

IF os$ = "LNX" THEN
Expand Down Expand Up @@ -5177,6 +5188,21 @@ FUNCTION ide2 (ignore)



IF MID$(menu$(m, s), 1) = "Display #Logging Output" OR MID$(menu$(m, s), 2) = "Display #Logging Output" THEN
PCOPY 2, 0
LoggingEnabled = NOT LoggingEnabled
WriteConfigSetting generalSettingsSection$, "LoggingEnabled", BoolToTFString$(LoggingEnabled)

IF LoggingEnabled THEN
menu$(RunMenuID, LoggingEnableMenu) = CHR$(7) + "Display #Logging Output"
ELSE
menu$(RunMenuID, LoggingEnableMenu) = "Display #Logging Output"
END IF

PCOPY 3, 0: SCREEN , , 3, 0
GOTO ideloop
END IF

IF RIGHT$(menu$(m, s), 28) = "Output EXE to Source #Folder" THEN
PCOPY 2, 0
SaveExeWithSource = NOT SaveExeWithSource
Expand Down Expand Up @@ -5207,6 +5233,17 @@ FUNCTION ide2 (ignore)
GOTO ideloop
END IF

IF menu$(m, s) = "Change #Terminal" THEN
PCOPY 2, 0

ideTerminalBox

'retval is ignored
PCOPY 3, 0: SCREEN , , 3, 0
GOTO ideloop
END IF


IF RIGHT$(menu$(m, s), 29) = "#Output Watch List to Console" THEN
PCOPY 2, 0
WatchListToConsole = NOT WatchListToConsole
Expand Down Expand Up @@ -15785,6 +15822,150 @@ FUNCTION ideCompilerSettingsBox
LOOP
END FUNCTION

SUB ideTerminalBox

'-------- generic dialog box header --------
PCOPY 0, 2
PCOPY 0, 1
SCREEN , , 1, 0
focus = 1
DIM p AS idedbptype
DIM o(1 TO 100) AS idedbotype
DIM sep AS STRING * 1
sep = CHR$(0)
'-------- end of generic dialog box header --------

'-------- init --------

i = 0

idepar p, 60, 7, "Default Terminal"

i = i + 1
PrevFocus = 1
o(i).typ = 1
o(i).y = 2
o(i).nam = idenewtxt("Terminal Command")
o(i).txt = idenewtxt(DefaultTerminal)
o(i).sx1 = 0
o(i).v1 = LEN(DefaultTerminal)

i = i + 1
o(i).typ = 3
o(i).y = 7
o(i).txt = idenewtxt("#OK" + sep + "#Cancel")
o(i).dft = 1
'-------- end of init --------

'-------- generic init --------
FOR i = 1 TO 100: o(i).par = p: NEXT 'set parent info of objects
'-------- end of generic init --------

DO 'main loop


'-------- generic display dialog box & objects --------
idedrawpar p
f = 1: cx = 0: cy = 0
FOR i = 1 TO 100
IF o(i).typ THEN

'prepare object
o(i).foc = focus - f 'focus offset
o(i).cx = 0: o(i).cy = 0
idedrawobj o(i), f 'display object
IF o(i).cx THEN cx = o(i).cx: cy = o(i).cy
END IF
NEXT i
lastfocus = f - 1
'-------- end of generic display dialog box & objects --------

'-------- custom display changes --------
LOCATE p.y + 4, p.x + 2
PRINT CHR$(34) + "$$" + CHR$(34) + " is replaced with the executable";
LOCATE p.y + 5, p.x + 2
PRINT CHR$(34) + "$@" + CHR$(34) + " is replaced with the COMMAND$ string";
'-------- end of custom display changes --------

'update visual page and cursor position
PCOPY 1, 0
IF cx THEN SCREEN , , 0, 0: LOCATE cy, cx, 1: SCREEN , , 1, 0

'-------- read input --------
change = 0
DO
GetInput
IF mWHEEL THEN change = 1
IF KB THEN change = 1
IF mCLICK THEN mousedown = 1: change = 1
IF mRELEASE THEN mouseup = 1: change = 1
IF mB THEN change = 1
alt = KALT: IF alt <> oldalt THEN change = 1
oldalt = alt
_LIMIT 100
LOOP UNTIL change
IF alt AND NOT KCTRL THEN idehl = 1 ELSE idehl = 0
'convert "alt+letter" scancode to letter's ASCII character
altletter$ = ""
IF alt AND NOT KCTRL THEN
IF LEN(K$) = 1 THEN
k = ASC(UCASE$(K$))
IF k >= 65 AND k <= 90 THEN altletter$ = CHR$(k)
END IF
END IF
SCREEN , , 0, 0: LOCATE , , 0: SCREEN , , 1, 0
'-------- end of read input --------

'-------- generic input response --------
info = 0
IF K$ = "" THEN K$ = CHR$(255)
IF KSHIFT = 0 AND K$ = CHR$(9) THEN focus = focus + 1
IF (KSHIFT AND K$ = CHR$(9)) OR (INSTR(_OS$, "MAC") AND K$ = CHR$(25)) THEN focus = focus - 1: K$ = ""
IF focus < 1 THEN focus = lastfocus
IF focus > lastfocus THEN focus = 1
f = 1
FOR i = 1 TO 100
t = o(i).typ
IF t THEN
focusoffset = focus - f
ideobjupdate o(i), focus, f, focusoffset, K$, altletter$, mB, mousedown, mouseup, mX, mY, info, mWHEEL
END IF
NEXT
'-------- end of generic input response --------

'specific post controls
IF focus <> PrevFocus THEN
'Always start with TextBox values selected upon getting focus
PrevFocus = focus
IF focus = 1 THEN
o(focus).v1 = LEN(idetxt(o(focus).txt))
IF o(focus).v1 > 0 THEN o(focus).issel = -1
o(focus).sx1 = 0
END IF
END IF

IF K$ = CHR$(27) OR (focus = 3 AND info <> 0) THEN
ClearMouse
EXIT SUB
END IF

IF K$ = CHR$(13) OR (focus = 2 AND info <> 0) THEN
DefaultTerminal = idetxt(o(1).txt)

WriteConfigSetting generalSettingsSection$, "DefaultTerminal", DefaultTerminal

ClearMouse
_KEYCLEAR
EXIT SUB
END IF
'end of custom controls

mousedown = 0
mouseup = 0
LOOP

END SUB

FUNCTION idemessagebox (titlestr$, messagestr$, buttons$)

'-------- generic dialog box header --------
Expand Down
93 changes: 67 additions & 26 deletions source/qb64pe.bas
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ DEFLNG A-Z
'-------- Optional IDE Component (1/2) --------
'$INCLUDE:'ide\ide_global.bas'


DIM SHARED NoExeSaved AS INTEGER

DIM SHARED vWatchErrorCall$, vWatchNewVariable$, vWatchVariableExclusions$
Expand Down Expand Up @@ -898,26 +897,86 @@ IF C = 9 THEN 'run

'execute program

IF LoggingEnabled THEN
ENVIRON "QB64PE_LOG_HANDLERS=console"
ENVIRON "QB64PE_LOG_SCOPES=qb64,libqb,libqb-image,libqb-audio"
ELSE
ENVIRON "QB64PE_LOG_HANDLERS="
ENVIRON "QB64PE_LOG_SCOPES="
END IF

ExecuteLine$ = ""

IF MacOSX THEN
IF path.exe$ = "" THEN path.exe$ = "./"

IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
ExecuteName$ = _FULLPATH$(lastBinaryGenerated$)
ELSE
ExecuteName$ = _FULLPATH$(path.exe$ + lastBinaryGenerated$)
END IF

IF path.exe$ = "./" THEN path.exe$ = ""

IF GetRCStateVar(ConsoleOn) OR LoggingEnabled THEN
IF LoggingEnabled THEN handler$ = "console" ELSE handler$ = ""

generateMacOSLogScript ExecuteName$, handler$, "qb64,libqb,libqb-image,libqb-audio", ModifyCOMMAND$, tmpdir$ + "log.command"

' Spawning a program in a terminal is done via `open`.
' We have to use a separate script to be able to set environment variables for the program
ExecuteLine$ = "open -b com.apple.terminal " + _CHR_QUOTE + tmpdir$ + "log.command" + _CHR_QUOTE
ELSE
ExecuteLine$ = ExecuteName$
END IF
ELSEIF os$ = "WIN" THEN
IF GetRCStateVar(ConsoleOn) OR LoggingEnabled THEN
PrePend$ = "cmd /c"
ELSE
PrePend$ = ""
END IF

ExecuteLine$ = PrePend$ + QuotedFilename$(CHR$(34) + lastBinaryGenerated$ + CHR$(34)) + ModifyCOMMAND$
ELSEIF os$ = "LNX" THEN
IF path.exe$ = "" THEN path.exe$ = "./"

IF GetRCStateVar(ConsoleOn) OR LoggingEnabled THEN
ExecuteLine$ = DefaultTerminal

IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
ExecuteLine$ = StrReplace$(ExecuteLine$, "$$", QuotedFilename$(lastBinaryGenerated$))
ELSE
ExecuteLine$ = StrReplace$(ExecuteLine$, "$$", QuotedFilename$(path.exe$ + lastBinaryGenerated$))
END IF

ExecuteLine$ = StrReplace$(ExecuteLine$, "$@", ModifyCOMMAND$)
ELSE
IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
ExecuteLine$ = QuotedFilename$(lastBinaryGenerated$) + ModifyCOMMAND$
ELSE
ExecuteLine$ = QuotedFilename$(path.exe$ + lastBinaryGenerated$) + ModifyCOMMAND$
END IF
END IF

IF path.exe$ = "./" THEN path.exe$ = ""
END IF

IF iderunmode = 1 THEN
IF NoExeSaved THEN
'This is the section which deals with if the user selected to run the program without
'saving an EXE file to the disk.
'We start off by first running the EXE, and then we delete it from the drive.
'making it a temporary file when all is said and done.
SHELL ExecuteLine$

IF os$ = "WIN" THEN
SHELL QuotedFilename$(CHR$(34) + lastBinaryGenerated$ + CHR$(34)) + ModifyCOMMAND$ 'run the newly created program
SHELL _HIDE _DONTWAIT "del " + QuotedFilename$(CHR$(34) + lastBinaryGenerated$ + CHR$(34)) 'kill it
END IF
IF path.exe$ = "" THEN path.exe$ = "./"
IF os$ = "LNX" THEN
IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
SHELL QuotedFilename$(lastBinaryGenerated$) + ModifyCOMMAND$
KILL lastBinaryGenerated$
ELSE
SHELL QuotedFilename$(path.exe$ + lastBinaryGenerated$) + ModifyCOMMAND$
KILL path.exe$ + lastBinaryGenerated$
END IF
END IF
Expand All @@ -927,29 +986,10 @@ IF C = 9 THEN 'run
GOTO sendcommand
END IF



IF os$ = "WIN" THEN SHELL _DONTWAIT QuotedFilename$(CHR$(34) + lastBinaryGenerated$ + CHR$(34)) + ModifyCOMMAND$
IF path.exe$ = "" THEN path.exe$ = "./"
IF os$ = "LNX" THEN
IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
SHELL _DONTWAIT QuotedFilename$(lastBinaryGenerated$) + ModifyCOMMAND$
ELSE
SHELL _DONTWAIT QuotedFilename$(path.exe$ + lastBinaryGenerated$) + ModifyCOMMAND$
END IF
END IF
IF path.exe$ = "./" THEN path.exe$ = ""
SHELL _DONTWAIT ExecuteLine$
ELSE
IF os$ = "WIN" THEN SHELL QuotedFilename$(CHR$(34) + lastBinaryGenerated$ + CHR$(34)) + ModifyCOMMAND$
IF path.exe$ = "" THEN path.exe$ = "./"
IF os$ = "LNX" THEN
IF LEFT$(lastBinaryGenerated$, LEN(path.exe$)) = path.exe$ THEN
SHELL QuotedFilename$(lastBinaryGenerated$) + ModifyCOMMAND$
ELSE
SHELL QuotedFilename$(path.exe$ + lastBinaryGenerated$) + ModifyCOMMAND$
END IF
END IF
IF path.exe$ = "./" THEN path.exe$ = ""
SHELL ExecuteLine$

DO: LOOP UNTIL INKEY$ = ""
DO: LOOP UNTIL _KEYHIT = 0
END IF
Expand Down Expand Up @@ -23829,6 +23869,7 @@ END FUNCTION
'$INCLUDE:'utilities\type.bas'
'$INCLUDE:'utilities\give_error.bas'
'$INCLUDE:'utilities\format.bas'
'$include:'utilities\terminal.bas'
'$INCLUDE:'emit\logging.bas'

DEFLNG A-Z
Expand Down
Loading

0 comments on commit 07758bd

Please sign in to comment.