Sign in Join
Wiki copytemporary

Console Mode Pascal: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Console-Mode Pascal Programming
22
33Many of us were writing [[Pascal]] [[Program|programs]] long before [[Graphical User Interface|Graphical User Interfaces]] (GUIs) and [[IDE|Integrated Development Environments (IDEs)]] became fashionable. Many others are beginners at Pascal programming and need to be able to try out the basic tools of the language. Still others need to write [[Command-line interface|console]]- or [[Text User Interface|text-mode]] applications in order to perform complex system control tasks.
44
55### Console mode programming without Lazarus
66
77Even though many prefer to use the [[Lazarus IDE]] to write console mode programs, you can also write them with any text editor and compile them yourself by calling the [[FPC]] [[Compiler|compiler]], e.g. this for a program in example.pas:
88
99``` bash
1010fpc example.pas
1111```
1212
1313Also, the text mode *fp* IDE (looks a bit like old [[Turbo Pascal]]) is available. In the next sections we will focus on programming with [[Lazarus]].
1414
1515### Console mode programming with Lazarus
1616
1717Lazarus provides an ideal environment for learning Pascal, and for developing text-mode programs. All the functionality of the Integrated Development Environment can be used, including the Source Editor with its [[Syntax highlighting|syntax highlighting]], access to the libraries, complex searching and code completion tools, and syntax checking. If you do not want a [[TForm|Form]] with its visual components, you do not need one, but the Lazarus Source Editor is still a great environment for program development. You can compile and run your program during development, without ever leaving the Editor.
1818
1919To start a console-mode program, go to the Main Menu and select Project -\> New Project and then select either **Program** or **Console Application**. The IDE will not generate all the extra files associated with a full graphic application, and will not open an Object Inspector box, but will open the Source Editor with a skeleton program structure and await your programming input.
2020
2121> **Note:** Under Windows a GUI application has no console and thus can not **writeln** or **readln**. You will get *File not open* errors. Disable under *Project Options / Compiler Options / Linking / Target specific options / Win32 GUI application* to create a console application. In Lazarus IDE 1.4, this is under *Project(menu) / Project Options / Compiler Options / Config and Target / Target specific options / Win32 GUI application*.
2222
2323> **Note:** Lazarus has some functionality for command line programs, such as [[CopyFile|copyfile]]. To use these, add a project requirement for LazUtils, which will not pull in the entire LCL. Then add the relevant unit to your uses clause.
2424
2525#### Project type: Console Application
2626
2727Selecting this project type in Lazarus creates a program with a new class derived from TCustomApplication. TCustomApplication provides a lot of the common things and makes programming command line utilities easy. For example checking command line options, writing help, checking [[Command line parameters and environment variables|environment variables]] and [[Exceptions|exception]] handling. All [[LCL]] programs use this automatically.
2828
2929#### Project type: Program
3030
3131As a demonstration, we will write a very minimalistic Pascal program. In the IDE, select the 'Program' project type and let the IDE helps you a bit. For example when you add another [[Unit|unit]] the IDE will automatically add the unitname to the program [[Uses|uses]] section. This behavior is defined in the project options. So you can go between 'Program' and 'Custom Program' at any time.
3232
3333An example for complete beginners:
3434
3535``` Pascal
3636program Project1;
3737{$mode objfpc}{$H+}
3838uses
3939 {$IFDEF UNIX}{$IFDEF UseCThreads}
4040 cthreads,
4141 {$ENDIF}{$ENDIF}
4242 Classes;
4343begin
4444 WriteLn('Hello World!');
4545 ReadLn;
4646end.
4747```
4848
4949### Pascal scripts
5050
5151Additionally, it is possible to write scripts that are dynamically compiled by [[InstantFPC]], a cross-platform solution to run (small) Pascal programs as scripts. The shebang
5252
5353 #!/usr/bin/env instantfpc
5454
5555permits to start the script like a stand-alone program.
5656
5757> **Note:** Though it is used to run Pascal scripts, InstantFPC uses regular Object Pascal, not the PascalScript script language. So "**PascalScript**" and **Pascal script** are not the same.
5858
5959## Running a Program
6060
6161#### Compile
6262
6363When you have finished your program (or program fragment) you can compile and run it by selecting Run -\> Build (or Quick Compile) from the Main Menu or clicking on the Green (Run) triangle symbol ![](/wiki-images/b/b8/Start.png) in the Button Bar. Any compiler messages (warnings, progress reports or error messages) will appear in the Message Box, and hopefully there will eventually be a message to say
6464
6565'Project "Project1" successfully built.:)'.
6666
6767But where is the program??!!
6868
6969If you have *not* yet saved the program, then the IDE put it into the *temporary* directory (e.g. /tmp under linux, C:\temp under windows, see Environment Options / Files / Directory for building test projects).
7070
7171If you already saved the project, then the program was created in the same directory, where you saved the project1.lpi file.
7272
7373#### Run in Console
7474
7575You can execute the program by going to a console (terminal) window, then use **cd** to change to the directory and typing the name of the program. On Unix/Linux, if it is in the current directory you will have to start with ./ as the program will probably not be found in the PATH.
7676
7777Example for Linux/Unix where a program is stored in /tmp:
7878
7979``` bash
8080cd /tmp
8181./Project1
8282```
8383
8484However, it can be very inconvenient to keep skipping out of the Lazarus Editor and into a terminal window and back again. Fortunately, there is a mechanism that allows a terminal window to be opened from within the Lazarus environment.
8585
8686#### Run in IDE
8787
8888In internal console: show in the terminal output window.
8989
9090In redirect output.
9191
9292From the Main Menu, select Run -\> Run Parameters, then check the box for "Use launching application". The first time you do this and try the Compile/Run sequence, you will probably get a rude message saying:
9393
94-`"xterm: Can't execvp /usr/share/lazarus//tools/runwait.sh: Permission denied".  `
94+```text
95+"xterm: Can't execvp /usr/share/lazarus//tools/runwait.sh: Permission denied".
96+```
9597
9698If this happens, you need to change the permissions on the appropriate file (for example using chmod +x filename, or using the Windows utility for changing permissions); you might have to do this as root. After this, each time you launch your program, a console box will appear and all your text I/O (readln, writeln etc) will appear in it.
9799
98100After your program has finished execution, a message "Press enter" appears on the screen. Thus any output your program generated will remain on the screen until you have had a chance to read it; after you press 'enter' the console window closes.
99101
100102On Linux, if the above message "xterm: Can't execvp /usr/share/lazarus//tools/runwait.sh: Permission denied" does not appear after checking the box for "Use launching application", type `/usr/bin/xterm $(TargetCmdLine)` and check `Use launching application` (xterm is installed on almost all Linux systems).
101103
102104Unfortunately, this method does not allow you to use the integrated debugger.
103105
104106#### Run in IDE with redirected output
105107
106108If you want to see what is written to stdout and want to use the integrated debugger as well, stdout can be redirected to a file with the following code:
107109
108110``` Pascal
109111uses
110112 baseunix;
111113
112114var
113115 OutputFile: text;
114116
115117begin
116118 Assign(OutputFile, 'Output.txt');
117119 if FileExists(Filename) then begin
118120 Append(OutputFile);
119121 end
120122 else begin
121123 Rewrite(OutputFile); { open file for writing, destroying contents, if any }
122124 end;
123125
124126 ResultCode := fpdup(OutputFile, output);
125127
126128 if ResultCode < 0 then begin
127129 raise Exception.CreateFmt('dup failed: %s', [ResultCode]);
128130 end;
129131 Close(OutputFile);
130132end.
131133```
132134
133135Output.txt can then be viewed with 'tail -f output.txt' or viewed with an editor if 'tail' is not available on your [[Operating System|os]].
134136
135137Alternatively, using Lazarus 0.9.31 or up (on Linux only): In the "View" menu, under "Debug Windows" there is an entry for a "console output" to view stdout
136138
137139## Unicode (UTF8) output
138140
139141If you want your console mode program to show Unicode ([[UTF-8|UTF8]]) output on Windows Vista and higher (and perhaps on earlier versions, too), you can use the **SetConsoleOutputCP** command to set the console to the UTF8 character set.
140142
141143> **Note:** you will need to make sure the font of the console can show the letters you want to output (e.g. Greek, Cyrillic, Korean).
142144
143145> **Note:** you will need to include the Windows unit.
144146
145147See [[LCL Unicode Support]] for more details on Unicode support in Lazarus and FPC.
146148
147149Example program:
148150
149151``` Pascal
150152program uniconsole;
151153
152154{$mode objfpc}{$H+}
153155{$APPTYPE CONSOLE}
154156
155157uses
156158 {$IFDEF UNIX}
157159 {$IFDEF UseCThreads}
158160 cthreads,
159161 {$ENDIF}
160162 {Widestring manager needed for widestring support}
161163 cwstring,
162164 {$ENDIF}
163165 {$IFDEF WINDOWS}
164166 Windows, {for setconsoleoutputcp}
165167 {$ENDIF}
166168 Classes
167169 ;
168170
169171var
170172UTF8TestString: string;
171173
172174begin
173175{$IFDEF WINDOWS}
174176SetConsoleOutputCP(CP_UTF8);
175177{$ENDIF}
176178UTF8TestString:= 'rosé, водка and ούζο';
177179writeln ('plain: ' + UTF8TestString);
178180{Apparently we do not need UTF8ToConsole for this
179181UTF8ToConsole did not do anything for me in fact.}
180182end.
181183```
182184
183185## Examples
184186
185187You can use the Lazarus editor to try out all the examples in the standard Pascal textbooks, or you can write your own. Some of the most useful procedures are those for executing system commands or for running other programs (whether written in Pascal, C or Perl, or shell or batch scripts).
186188
187189#### Execute shell command
188190
189191Here is an example for a *Custom Program* or *Program*... that is Linux/Unix/macOS specific though:
190192
191193``` Pascal
192194program TryShell;
193195uses
194196 Classes, Unix;
195197var
196198 S: LongInt;
197199begin
198200 S := fpsystem('/bin/ls -la *.p*'); //lists .pp, .pas, .php, .png etc in current directory
199201 WriteLn('Program exited with status : ', S)
200202end.
201203```
202204
203205#### Example: update FPC and Lazarus
204206
205207Rather more complex commands can be executed. For example, if you have already checked out the SVN repositories for FPC and Lazarus (see [[buildfaq]]) you could keep your FPC and Lazarus source files up-to-date by retrieval from the SVN repository with the following sequence of calls:
206208
207209``` Pascal
208210program LazUpdate;
209211uses
210212 Classes, Unix;
211213var
212214 S: LongInt;
213215begin
214216 S := fpsystem('cd /usr/local/src/fpc/devel/fpc ; make clean');
215217 S := fpsystem('cd /usr/local/src/fpc/devel/lazarus ; make clean');
216218 S := fpsystem('cd /usr/local/src/fpc/devel ; svn update fpc >& ~/cvscheckout.log');
217219 S := fpsystem('cd /usr/local/src/fpc/devel ; svn update lazarus >& ~/cvslaz.log' );
218220end.
219221```
220222
221223Note that issuing the command
222224
223225``` Pascal
224226fpsystem('cd /somedirectory');
225227```
226228
227229followed by
228230
229231``` Pascal
230232fpsystem ('do something in that subdirectory');
231233```
232234
233235does not work, because after each **fpsystem()** [[Function|function]] call the execution of the program returns to the directory it started in; so we need to include multiple statements per line within our calls to shell via **fpsystem()**. \[Rather: it always starts in . \]
234236
235237One does not have to enter every command as a separate line of Pascal; one could create a **bash** script file like this (from [[buildfaq]]):
236238
237239``` bash
238240#!/bin/sh
239241cd /usr/local/src/fpc/devel
240242cd fpc
241243make clean
242244cd ..
243245cd lazarus
244246make clean
245247cd ..
246248svn up fpc >& ~/cvscheckout.log
247249svn up lazarus >& ~/cvslaz.log
248250```
249251
250252Name it **updatelaz.sh**, and then instead of using **bash** to execute it directly, call it from a Pascal program thus:
251253
252254``` Pascal
253255(* This can be compiled or used as a Pascal script *)
254256program LazUpdate1;
255257uses
256258 Classes, Unix;
257259var
258260 S: LongInt;
259261begin
260262 S := fpsystem('updatelaz.sh')
261263end.
262264```
263265
264266## See also
265267
266268- [[Command line parameters and environment variables]]
267269- [[Executing External Programs]]
268270- [[Debugger Console App|Debugging console applications]]
269271- [[InstantFPC]]
270272
271273---
272274*From the Free Pascal wiki, page "Console Mode Pascal", as it stood on 2023-05-02 after a change by Thierrybo, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history