Index: CHANGES.txt ================================================================== --- CHANGES.txt +++ CHANGES.txt @@ -1,5 +1,14 @@ +Version 0.10.0 +2022-03-10 + +[Feature] Log file creation. +[Changed] Replaced the build output window by a status window. +[Bugfix] Windows builds erroneously showed "-1" in the update status field. +[Bugfix] Building a document without a macro package works now. + + Version 0.9.9.1 2022-03-10 [Feature] macOS builds are working now. [Feature] First macOS release. Index: README.md ================================================================== --- README.md +++ README.md @@ -2,11 +2,11 @@ You know what was missing with `groff`? A good alternative to TeXstudio. Here we go. ## Screenshot -![Screenshot](https://i.imgur.com/ispa8x4.png) +![Screenshot](screenshot.png) ## Features * Written in Lazarus (Free Pascal). * Should be cross-platform (but Windows support is mediocre yet). ADDED screenshot.png Index: screenshot.png ================================================================== --- screenshot.png +++ screenshot.png cannot compute difference between binary files Index: src/buildoutputwindow.lfm ================================================================== --- src/buildoutputwindow.lfm +++ src/buildoutputwindow.lfm @@ -1,20 +1,21 @@ object BuildStatusWindow: TBuildStatusWindow - Left = 2050 - Height = 367 - Top = 149 - Width = 432 + Left = 493 + Height = 80 + Top = 160 + Width = 168 BorderStyle = bsDialog - Caption = 'build output' - ClientHeight = 367 - ClientWidth = 432 - LCLVersion = '2.2.0.4' - object mBuildOutput: TMemo - Left = 0 - Height = 367 - Top = 0 - Width = 432 - Align = alClient - ScrollBars = ssAutoBoth - TabOrder = 0 + Caption = 'building' + ClientHeight = 80 + ClientWidth = 168 + LCLVersion = '2.3.0.0' + object Label1: TLabel + Left = 32 + Height = 37 + Top = 16 + Width = 117 + Caption = 'building...' + Font.Height = -27 + ParentColor = False + ParentFont = False end end Index: src/buildoutputwindow.pas ================================================================== --- src/buildoutputwindow.pas +++ src/buildoutputwindow.pas @@ -25,35 +25,35 @@ type { TBuildStatusWindow } TBuildStatusWindow = class(TForm) - mBuildOutput: TMemo; + Label1: TLabel; private public - function BuildDocument(CommandLine: String): Boolean; + function BuildDocument(CommandLine: String; LogFile: String): Boolean; end; var OutputText: String; - BuildStatusWindow: TBuildStatusWindow; implementation {$R *.lfm} -function TBuildStatusWindow.BuildDocument(CommandLine: String): Boolean; +function TBuildStatusWindow.BuildDocument(CommandLine: String; LogFile: String): Boolean; var p: TProcess; - AStringList: TStringList; + n: LongInt; + str: String; + lh: TextFile; begin p := TProcess.Create(nil); - p.Options := p.Options + [poWaitOnExit, poUsePipes]; + p.Options := p.Options + [poUsePipes, poStderrToOutPut]; - AStringList := TStringList.Create; {$IFDEF WINDOWS} p.Executable := 'cmd'; p.Parameters.Add('/c'); {$ENDIF} {$IFDEF UNIX} @@ -61,26 +61,41 @@ p.Parameters.Add('-c'); {$ENDIF} p.Parameters.Add(CommandLine); p.Execute; - AStringList.LoadFromStream(p.Output); + if LogFile <> '' then + begin + AssignFile(lh, LogFile); + Rewrite(lh); + + while p.Running do + begin + n := p.Output.Read(str, 2048); + if n > 0 then + begin + writeln(lh, str); + end + else Sleep(100); + end; + + { We might have some buffer contents left. } + repeat + n := p.Output.Read(str, 2048); + if n > 0 then + begin + writeln(lh, str); + end; + until n <= 0; + + CloseFile(lh); + end; + + result := p.ExitStatus > 0; p.Free; - mBuildOutput.Text := AStringList.Text; - AStringList.Free; - - if Length(mBuildOutput.Text) = 0 then begin - // We don't have any output. We can close the window. - BuildStatusWindow.Close; - result := True - end - else begin - // There was some output. Chances are that warnings occurred. - // Keep it shown. - // TODO: This does not always work well... - result := False - end; + { Close the status window: } + Close; end; end. Index: src/groffstudio.lpi ================================================================== --- src/groffstudio.lpi +++ src/groffstudio.lpi @@ -20,13 +20,11 @@ - - - + DELETED src/groffstudio.lps Index: src/groffstudio.lps ================================================================== --- src/groffstudio.lps +++ src/groffstudio.lps @@ -1,221 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Index: src/unit1.lfm ================================================================== --- src/unit1.lfm +++ src/unit1.lfm @@ -1,21 +1,21 @@ object MainForm: TMainForm - Left = 819 + Left = 976 Height = 692 - Top = 147 - Width = 861 + Top = 91 + Width = 857 Caption = 'groffstudio' ClientHeight = 692 - ClientWidth = 861 + ClientWidth = 857 OnClose = FormClose OnCreate = FormCreate LCLVersion = '2.3.0.0' object MainStatusBar: TStatusBar Left = 0 - Height = 18 - Top = 674 - Width = 861 + Height = 23 + Top = 669 + Width = 857 Panels = < item Text = 'file name with save status' Width = 200 end @@ -31,48 +31,48 @@ end object ExtendedNotebook1: TExtendedNotebook Left = 10 Height = 662 Top = 8 - Width = 841 + Width = 837 ActivePage = tsEdit Anchors = [akTop, akLeft, akRight, akBottom] Style = tsFlatButtons TabIndex = 0 TabOrder = 1 object tsEdit: TTabSheet Caption = 'edit a groff document' - ClientHeight = 632 - ClientWidth = 835 + ClientHeight = 631 + ClientWidth = 829 ParentFont = False object GroupBox1: TGroupBox Left = 10 - Height = 65 - Top = 562 - Width = 815 + Height = 74 + Top = 552 + Width = 809 Align = alBottom BorderSpacing.Left = 10 BorderSpacing.Right = 10 BorderSpacing.Bottom = 5 Caption = 'build' - ClientHeight = 46 + ClientHeight = 54 ClientWidth = 805 TabOrder = 0 object Label1: TLabel Left = 112 - Height = 16 + Height = 15 Top = -4 - Width = 83 + Width = 72 Caption = 'macro to use:' ParentColor = False end object cmbMacro: TComboBox Left = 112 - Height = 20 - Top = 14 + Height = 23 + Top = 20 Width = 100 - ItemHeight = 19 + ItemHeight = 15 Items.Strings = ( 'man' 'me' 'mm' 'mom' @@ -80,185 +80,195 @@ ) TabOrder = 0 Text = '[ select ]' end object Label2: TLabel - Left = 673 - Height = 16 + Left = 682 + Height = 15 Top = -4 - Width = 87 + Width = 78 Anchors = [akTop, akRight] Caption = 'output format:' ParentColor = False end object rdPs: TRadioButton - Left = 670 - Height = 18 - Top = 14 - Width = 85 + Left = 684 + Height = 19 + Top = 24 + Width = 71 Anchors = [akTop, akRight] Caption = 'PostScript' OnChange = rdPsChange TabOrder = 1 end object rdPdf: TRadioButton - Left = 753 - Height = 18 - Top = 14 - Width = 50 + Left = 764 + Height = 19 + Top = 24 + Width = 39 Anchors = [akTop, akRight] Caption = 'PDF' OnChange = rdPdfChange TabOrder = 2 end object Label3: TLabel - Left = 285 - Height = 16 + Left = 300 + Height = 15 Top = -4 - Width = 91 + Width = 76 Anchors = [akTop, akRight] Caption = 'preprocessors:' ParentColor = False end object chkEqn: TCheckBox - Left = 348 - Height = 18 - Top = 14 - Width = 48 + Left = 358 + Height = 19 + Top = 24 + Width = 38 Anchors = [akTop, akRight] Caption = 'eqn' TabOrder = 3 end object chkPic: TCheckBox - Left = 434 - Height = 18 - Top = 14 - Width = 44 + Left = 444 + Height = 19 + Top = 24 + Width = 34 Anchors = [akTop, akRight] Caption = 'pic' TabOrder = 4 end object chkTbl: TCheckBox - Left = 523 - Height = 18 - Top = 14 - Width = 41 + Left = 532 + Height = 19 + Top = 24 + Width = 32 Anchors = [akTop, akRight] Caption = 'tbl' TabOrder = 5 end object chkGrn: TCheckBox - Left = 392 - Height = 18 - Top = 14 - Width = 46 + Left = 402 + Height = 19 + Top = 24 + Width = 36 Anchors = [akTop, akRight] Caption = 'grn' TabOrder = 6 end object chkChem: TCheckBox - Left = 292 - Height = 18 - Top = 14 - Width = 58 + Left = 302 + Height = 19 + Top = 24 + Width = 48 Anchors = [akTop, akRight] Caption = 'chem' TabOrder = 7 end object chkRefer: TCheckBox - Left = 473 - Height = 18 - Top = 14 - Width = 53 + Left = 484 + Height = 19 + Top = 24 + Width = 42 Anchors = [akTop, akRight] Caption = 'refer' TabOrder = 8 end object Label4: TLabel - Left = 576 - Height = 16 + Left = 583 + Height = 15 Top = -4 - Width = 41 + Width = 34 Anchors = [akTop, akRight] Caption = 'extras:' ParentColor = False end object chkPdfMark: TCheckBox - Left = 574 - Height = 18 - Top = 14 - Width = 74 + Left = 585 + Height = 19 + Top = 24 + Width = 63 Anchors = [akTop, akRight] Caption = 'Pdfmark' Enabled = False TabOrder = 9 end object btnBuild: TButton - Left = 16 + Left = 1 Height = 29 - Top = 8 + Top = 0 Width = 75 Caption = 'build' Color = clLime Enabled = False Font.Style = [fsBold, fsItalic] OnClick = btnBuildClick ParentFont = False TabOrder = 10 end + object chkLogFile: TCheckBox + Left = 8 + Height = 19 + Hint = 'If enabled, a log file containing the groff output will be placed alongside the source document.' + Top = 32 + Width = 80 + Caption = 'with log file' + Enabled = False + TabOrder = 11 + end end object btnSaveGroff: TButton - Left = 750 + Left = 744 Height = 28 - Top = 531 + Top = 512 Width = 75 Anchors = [akRight, akBottom] Caption = 'save' Font.Style = [fsBold] OnClick = btnSaveGroffClick ParentFont = False TabOrder = 1 end object btnLoadGroff: TButton - Left = 669 + Left = 663 Height = 28 - Top = 531 + Top = 512 Width = 75 Anchors = [akRight, akBottom] Caption = 'load' Font.Style = [fsBold] OnClick = btnLoadGroffClick ParentFont = False TabOrder = 2 end object Label5: TLabel - Left = 142 - Height = 16 - Top = 543 - Width = 509 + Left = 207 + Height = 15 + Top = 525 + Width = 438 Anchors = [akRight, akBottom] Caption = 'note that everything build-related will be stored in the document''s storage directory' Font.Color = clBlue Font.Style = [fsItalic] ParentColor = False ParentFont = False end inline SynEdit1: TSynEdit Left = 10 - Height = 524 + Height = 507 Top = 0 - Width = 815 + Width = 809 Anchors = [akTop, akLeft, akRight, akBottom] Font.CharSet = 4 Font.Height = -13 Font.Name = 'Consolas' Font.Pitch = fpFixed Font.Quality = fqCleartypeNatural ParentColor = False ParentFont = False TabOrder = 3 - Gutter.Width = 67 + Gutter.Width = 55 Gutter.MouseActions = <> RightGutter.Width = 0 RightGutter.MouseActions = <> Keystrokes = < item @@ -712,11 +722,11 @@ object SynGutterMarks1: TSynGutterMarks Width = 24 MouseActions = <> end object SynGutterLineNumber1: TSynGutterLineNumber - Width = 27 + Width = 15 MouseActions = <> MarkupInfo.Background = clBtnFace MarkupInfo.Foreground = clNone DigitCount = 2 ShowOnlyLineNumbersMultiplesOf = 1 @@ -745,67 +755,67 @@ end end end object tsSettings: TTabSheet Caption = 'groffstudio settings' - ClientHeight = 632 - ClientWidth = 835 + ClientHeight = 631 + ClientWidth = 829 object chkAutoSaveBuildSettings: TCheckBox Left = 0 - Height = 18 + Height = 19 Top = 16 - Width = 342 + Width = 310 Caption = 'Save and restore the chosen build settings for next time' TabOrder = 0 end object btnSaveSettings: TButton - Left = 746 + Left = 740 Height = 25 - Top = 601 + Top = 600 Width = 91 Anchors = [akRight, akBottom] Caption = 'save settings' OnClick = btnSaveSettingsClick TabOrder = 1 end object Label14: TLabel Left = 0 - Height = 16 + Height = 15 Top = 48 - Width = 150 + Width = 129 Caption = 'Yes, that''s all for now. :-)' ParentColor = False end end object tsGroff: TTabSheet Caption = 'groff version' - ClientHeight = 632 - ClientWidth = 835 + ClientHeight = 631 + ClientWidth = 829 object GroupBox2: TGroupBox Left = 20 Height = 57 - Top = 567 - Width = 795 + Top = 566 + Width = 789 Align = alBottom BorderSpacing.Left = 20 BorderSpacing.Right = 20 BorderSpacing.Bottom = 8 Caption = 'groff for Windows' - ClientHeight = 38 + ClientHeight = 37 ClientWidth = 785 TabOrder = 0 object Label6: TLabel Left = 8 - Height = 16 + Height = 15 Top = 8 - Width = 125 + Width = 108 Caption = 'latest version online:' ParentColor = False end object edtOnlineGroffVersionWindows: TEdit Left = 136 - Height = 17 + Height = 15 Top = 8 Width = 552 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False @@ -823,42 +833,42 @@ TabOrder = 1 end end object Label7: TLabel Left = 8 - Height = 32 + Height = 30 Top = 8 - Width = 823 + Width = 817 Anchors = [akTop, akLeft, akRight] Caption = 'as you might guess, groffstudio requires a working installation of groff. this page performs the basic checks for you. note that on windows, everything is harder than it should. :-)' Constraints.MaxHeight = 582 ParentColor = False WordWrap = True end object Label9: TLabel Left = 8 - Height = 16 + Height = 15 Top = 56 - Width = 81 + Width = 70 Caption = 'groff version:' ParentColor = False end object edtGroffInstalledVersion: TEdit Left = 144 - Height = 17 + Height = 15 Top = 56 - Width = 687 + Width = 681 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False TabOrder = 1 end object lblTroffCommandNotFound: TLabel Left = 8 - Height = 48 + Height = 45 Top = 112 - Width = 822 + Width = 816 Anchors = [akTop, akLeft, akRight] Caption = 'groff was not found. in order to use groffstudio, you absolutely need groff in your PATH variable. on unix and unix-like systems, you''ll need to edit the $PATH variable. on windows, i warmly recommend the Rapid Environment Editor for that.'#13#10'please exit groffstudio at your nearest convenience and adjust your PATH variables. then try again.' Font.Color = clRed ParentColor = False ParentFont = False @@ -865,95 +875,95 @@ Visible = False WordWrap = True end object edtGroffstudioInstalledVersion: TEdit Left = 144 - Height = 17 + Height = 15 Top = 77 - Width = 687 + Width = 681 Anchors = [akTop, akLeft, akRight] BorderStyle = bsNone Enabled = False TabOrder = 2 end object Label10: TLabel Left = 8 - Height = 16 + Height = 15 Top = 77 - Width = 118 + Width = 103 Caption = 'groffstudio version:' ParentColor = False end end object tsAbout: TTabSheet Caption = 'about groffstudio' - ClientHeight = 632 - ClientWidth = 835 + ClientHeight = 631 + ClientWidth = 829 object lblAboutProductName: TLabel Left = 0 - Height = 53 + Height = 61 Top = 16 - Width = 297 + Width = 315 Caption = 'groffstudio x.y.z' Font.Color = clBlue Font.Height = -45 ParentColor = False ParentFont = False end object Label8: TLabel Left = 20 - Height = 16 + Height = 15 Top = 80 - Width = 246 + Width = 217 Caption = 'brought to you by tux0r and contributors' ParentColor = False end object Label11: TLabel Left = 0 - Height = 16 + Height = 15 Top = 128 - Width = 53 + Width = 45 Caption = 'Website:' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object Label12: TLabel Left = 0 - Height = 16 + Height = 15 Top = 152 - Width = 69 + Width = 57 Caption = 'Repository:' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object Label13: TLabel Left = 0 - Height = 16 + Height = 15 Top = 176 - Width = 119 + Width = 99 Caption = 'Repository (mirror):' Font.Style = [fsItalic] ParentColor = False ParentFont = False end object mLicense: TMemo Left = 0 Height = 418 Top = 216 - Width = 842 + Width = 836 Anchors = [akTop, akLeft, akRight] ScrollBars = ssAutoBoth TabOrder = 0 end object lblWebsite: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 128 - Width = 113 + Width = 99 Caption = 'groff.tuxproject.de' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False @@ -960,13 +970,13 @@ OnClick = lblWebsiteClick end object lblFossilRepo: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 152 - Width = 140 + Width = 121 Caption = 'code.rosaelefanten.org' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False @@ -973,13 +983,13 @@ OnClick = lblFossilRepoClick end object lblGithubRepo: TLabel Cursor = crHandPoint Left = 120 - Height = 16 + Height = 15 Top = 176 - Width = 68 + Width = 62 Caption = 'github.com' Font.Color = clBlue Font.Style = [fsUnderline] ParentColor = False ParentFont = False Index: src/unit1.pas ================================================================== --- src/unit1.pas +++ src/unit1.pas @@ -40,10 +40,11 @@ btnSaveGroff: TButton; btnLoadGroff: TButton; btnBuild: TButton; btnDownloadGroffWindows: TButton; btnSaveSettings: TButton; + chkLogFile: TCheckBox; chkAutoSaveBuildSettings: TCheckBox; chkPdfMark: TCheckBox; chkRefer: TCheckBox; chkChem: TCheckBox; chkGrn: TCheckBox; @@ -170,10 +171,11 @@ storeBuildSettings := iniStorage.ReadBoolean('AutoSaveBuildSettings', False); chkAutoSaveBuildSettings.Checked := storeBuildSettings; if storeBuildSettings then begin + chkLogFile.Checked := iniStorage.ReadBoolean('BuildLogFile', False); cmbMacro.Text := iniStorage.ReadString('BuildChosenMacro', '[ select ]'); chkChem.Checked := iniStorage.ReadBoolean('BuildUseChem', False); chkEqn.Checked := iniStorage.ReadBoolean('BuildUseEqn', False); chkGrn.Checked := iniStorage.ReadBoolean('BuildUseGrn', False); chkPic.Checked := iniStorage.ReadBoolean('BuildUsePic', False); @@ -210,13 +212,11 @@ if reGroffStudioVersion.Exec(OnlineVersionsFile) then begin // Compare the two versions - ours and the online one: GroffHelpers.VerStrCompare(reGroffStudioVersion.Match[1], FileVerInfo.VersionStrings.Values['FileVersion'], HasVersionUpdate); if HasVersionUpdate > 0 then - MainStatusBar.Panels[2].Text := 'update ' + reGroffStudioVersion.Match[1] + ' available' - else - MainStatusBar.Panels[2].Text := IntToStr(HasVersionUpdate); + MainStatusBar.Panels[2].Text := 'update ' + reGroffStudioVersion.Match[1] + ' available'; end else MainStatusBar.Panels[2].Text := ''; {$ELSE} // Non-Windows platforms won't need some of that. {$IFDEF DARWIN} // What's the latest available version? @@ -296,23 +296,24 @@ procedure TMainForm.btnBuildClick(Sender: TObject); var buildSuccess: Boolean; buildOpts: String; + logFileName: String; outputFileName: String; begin // Reset status display: MainStatusBar.Panels[1].Text := ''; BuildWindow := TBuildStatusWindow.Create(Application); - BuildWindow.ShowModal; + BuildWindow.Show; // Build the parameters: buildOpts := 'groff'; // - Macro: - buildOpts := buildOpts + ' -' + cmbMacro.SelText; + if cmbMacro.SelText <> '' then buildOpts := buildOpts + ' -' + cmbMacro.SelText; // - Enforce UTF-8: buildOpts := buildOpts + ' -Kutf8'; // - Preprocessors: @@ -333,12 +334,15 @@ // - Input file: buildOpts := buildOpts + ' ' + currentGroffFilePath; buildOpts := buildOpts + ' > ' + outputFileName; + // - Log file: + if chkLogFile.Checked then logFileName := currentGroffFilePath + '.log'; + // Build: - buildSuccess := BuildWindow.BuildDocument(buildOpts); + buildSuccess := BuildWindow.BuildDocument(buildOpts, logFileName); if buildSuccess then MainStatusBar.Panels[1].Text := 'build successful' else MainStatusBar.Panels[1].Text := 'build problem'; @@ -363,11 +367,15 @@ begin currentGroffFilePath := odOpenGroffFile.FileName; currentGroffFileName := ExtractFileName(odOpenGroffFile.FileName); SynEdit1.Lines.LoadFromFile(odOpenGroffFile.FileName); - if hasGroff then btnBuild.Enabled := True; + if hasGroff then + begin + btnBuild.Enabled := True; + chkLogFile.Enabled := True; + end; // Display the current file: MainStatusBar.Panels[0].Text := currentGroffFileName; end; end; @@ -382,11 +390,14 @@ begin currentGroffFilePath := sdSaveGroffFile.FileName; currentGroffFileName := ExtractFileName(currentGroffFilePath); SynEdit1.Lines.SaveToFile(sdSaveGroffFile.FileName); - if hasGroff then btnBuild.Enabled := True; + if hasGroff then begin + btnBuild.Enabled := True; + chkLogFile.Enabled := True; + end; end; // Remove the "Changed" mark: MainStatusBar.Panels[0].Text := currentGroffFileName; unsavedChanges := False; @@ -394,10 +405,11 @@ procedure TMainForm.btnSaveSettingsClick(Sender: TObject); begin // Store the build settings: iniStorage.WriteString('BuildChosenMacro', cmbMacro.Text); + iniStorage.WriteBoolean('BuildLogFile', chkLogFile.Checked); iniStorage.WriteBoolean('BuildUseChem', chkChem.Checked); iniStorage.WriteBoolean('BuildUseEqn', chkEqn.Checked); iniStorage.WriteBoolean('BuildUseGrn', chkGrn.Checked); iniStorage.WriteBoolean('BuildUsePic', chkPic.Checked); iniStorage.WriteBoolean('BuildUseRefer', chkRefer.Checked);