]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/mini/MiniTerminal.java
1 package org
.argeo
.cms
.desktop
.mini
;
3 import java
.io
.BufferedReader
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStreamReader
;
6 import java
.io
.OutputStream
;
7 import java
.net
.InetAddress
;
8 import java
.net
.UnknownHostException
;
9 import java
.nio
.charset
.Charset
;
10 import java
.nio
.charset
.StandardCharsets
;
11 import java
.nio
.file
.Files
;
12 import java
.nio
.file
.Path
;
13 import java
.nio
.file
.Paths
;
14 import java
.util
.ArrayList
;
15 import java
.util
.Arrays
;
16 import java
.util
.List
;
17 import java
.util
.StringTokenizer
;
19 import org
.eclipse
.swt
.SWT
;
20 import org
.eclipse
.swt
.events
.KeyEvent
;
21 import org
.eclipse
.swt
.events
.KeyListener
;
22 import org
.eclipse
.swt
.events
.PaintEvent
;
23 import org
.eclipse
.swt
.events
.PaintListener
;
24 import org
.eclipse
.swt
.graphics
.Font
;
25 import org
.eclipse
.swt
.graphics
.GC
;
26 import org
.eclipse
.swt
.graphics
.Point
;
27 import org
.eclipse
.swt
.layout
.GridData
;
28 import org
.eclipse
.swt
.layout
.GridLayout
;
29 import org
.eclipse
.swt
.widgets
.Canvas
;
30 import org
.eclipse
.swt
.widgets
.Caret
;
31 import org
.eclipse
.swt
.widgets
.Composite
;
32 import org
.eclipse
.swt
.widgets
.Display
;
33 import org
.eclipse
.swt
.widgets
.Shell
;
35 public class MiniTerminal
implements KeyListener
, PaintListener
{
40 private StringBuffer buf
= new StringBuffer("");
41 private StringBuffer userInput
= new StringBuffer("");
42 private List
<String
> history
= new ArrayList
<>();
44 private Point charExtent
= null;
45 private int charsPerLine
= 0;
46 private String
[] lines
= new String
[0];
47 private List
<String
> logicalLines
= new ArrayList
<>();
50 private Charset charset
;
52 private Path currentDir
;
54 private String host
= "localhost";
55 private String username
;
57 private boolean running
= false;
58 private OutputStream stdIn
= null;
60 public MiniTerminal(Composite parent
, int style
) {
61 charset
= StandardCharsets
.UTF_8
;
63 Display display
= parent
.getDisplay();
65 mono
= new Font(display
, "Monospace", 10, SWT
.NONE
);
67 parent
.setLayout(new GridLayout());
68 area
= new Canvas(parent
, SWT
.NONE
);
69 area
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
70 caret
= new Caret(area
, SWT
.NONE
);
73 area
.addKeyListener(this);
74 area
.addPaintListener(this);
76 username
= System
.getProperty("user.name");
78 host
= InetAddress
.getLocalHost().getHostName();
79 if (host
.indexOf('.') > 0)
80 host
= host
.substring(0, host
.indexOf('.'));
81 } catch (UnknownHostException e
) {
84 homeDir
= Paths
.get(System
.getProperty("user.home"));
87 buf
= new StringBuffer(prompt());
91 public void keyPressed(KeyEvent e
) {
95 public void keyReleased(KeyEvent e
) {
96 if (e
.keyLocation
!= 0)
97 return;// weird characters
98 // System.out.println(e.character);
99 if (e
.keyCode
== 0xd) {// return
103 // buf.append(prompt());
104 } else if (e
.keyCode
== 0x8) {// delete
105 if (userInput
.length() == 0)
107 userInput
.setLength(userInput
.length() - 1);
108 if (!running
&& buf
.length() > 0)
109 buf
.setLength(buf
.length() - 1);
112 buf
.append(e
.character
);
113 userInput
.append(e
.character
);
116 if (area
.isDisposed())
119 // System.out.println("Append " + e);
124 stdIn
.write(Character
.toString(e
.character
).getBytes(charset
));
125 } catch (IOException e1
) {
126 // TODO Auto-generated catch block
127 e1
.printStackTrace();
133 protected String
prompt() {
134 String fileName
= currentDir
.equals(homeDir
) ?
"~" : currentDir
.getFileName().toString();
135 String end
= username
.equals("root") ?
"]# " : "]$ ";
136 return "[" + username
+ "@" + host
+ " " + fileName
+ end
;
139 private void displayPrompt() {
140 buf
.append(prompt() + userInput
);
143 protected void markLogicalLine() {
144 String str
= buf
.toString().trim();
145 logicalLines
.add(str
);
146 buf
= new StringBuffer("");
149 private void processUserInput() {
150 String cmd
= userInput
.toString();
151 userInput
= new StringBuffer("");
152 processUserInput(cmd
);
156 protected void processUserInput(String input
) {
158 StringTokenizer st
= new StringTokenizer(input
);
159 List
<String
> args
= new ArrayList
<>();
160 while (st
.hasMoreTokens())
161 args
.add(st
.nextToken());
162 if (args
.size() == 0) {
168 if (args
.get(0).equals("cd")) {
169 if (args
.size() == 1) {
172 Path newPath
= currentDir
.resolve(args
.get(1));
173 if (!Files
.exists(newPath
) || !Files
.isDirectory(newPath
)) {
174 println(newPath
+ ": No such file or directory");
182 // show current directory
183 else if (args
.get(0).equals("pwd")) {
189 else if (args
.get(0).equals("exit")) {
191 area
.getShell().dispose();
195 ProcessBuilder pb
= new ProcessBuilder(args
);
196 pb
.redirectErrorStream(true);
197 pb
.directory(currentDir
.toFile());
198 // Process process = Runtime.getRuntime().exec(input, null, currentPath.toFile());
199 Process process
= pb
.start();
201 stdIn
= process
.getOutputStream();
202 Thread readOut
= new Thread("Read out") {
206 try (BufferedReader in
= new BufferedReader(
207 new InputStreamReader(process
.getInputStream(), charset
))) {
209 while ((line
= in
.readLine()) != null) {
212 } catch (IOException e
) {
213 println(e
.getMessage());
221 } catch (IOException e
) {
222 println(e
.getMessage());
227 protected int linesForLogicalLine(char[] line
) {
228 return line
.length
/ charsPerLine
+ 1;
231 protected void println(Object line
) {
236 protected void refreshLines(int charPerLine
, int nbrOfLines
) {
237 if (lines
.length
!= nbrOfLines
) {
238 lines
= new String
[nbrOfLines
];
239 Arrays
.fill(lines
, null);
241 if (this.charsPerLine
!= charPerLine
)
242 this.charsPerLine
= charPerLine
;
244 int currentLine
= nbrOfLines
- 1;
246 if (buf
.length() > 0) {
247 lines
[currentLine
] = buf
.toString();
249 lines
[currentLine
] = "";
253 logicalLines
: for (int i
= logicalLines
.size() - 1; i
>= 0; i
--) {
254 char[] logicalLine
= logicalLines
.get(i
).toCharArray();
255 int linesNeeded
= linesForLogicalLine(logicalLine
);
256 for (int j
= linesNeeded
- 1; j
>= 0; j
--) {
257 int from
= j
* charPerLine
;
258 int to
= j
== linesNeeded
- 1 ? from
+ charPerLine
: Math
.min(from
+ charPerLine
, logicalLine
.length
);
259 lines
[currentLine
] = new String(Arrays
.copyOfRange(logicalLine
, from
, to
));
260 // System.out.println("Set line " + currentLine + " to : " + lines[currentLine]);
269 public void paintControl(PaintEvent e
) {
272 if (charExtent
== null)
273 charExtent
= gc
.textExtent("a");
275 Point areaSize
= area
.getSize();
276 int charPerLine
= areaSize
.x
/ charExtent
.x
;
277 int nbrOfLines
= areaSize
.y
/ charExtent
.y
;
278 refreshLines(charPerLine
, nbrOfLines
);
280 for (int i
= 0; i
< lines
.length
; i
++) {
281 String line
= lines
[i
];
283 gc
.drawString(line
, 0, i
* charExtent
.y
);
285 // String toDraw = buf.toString();
286 // gc.drawString(toDraw, 0, 0);
287 // area.setCaret(caret);
290 public void setPath(String path
) {
291 this.currentDir
= Paths
.get(path
);
294 public void setPath(Path path
) {
295 this.currentDir
= path
;
298 public static void main(String
[] args
) {
299 Display display
= Display
.getCurrent() == null ?
new Display() : Display
.getCurrent();
300 Shell shell
= new Shell(display
, SWT
.SHELL_TRIM
);
302 MiniTerminal miniBrowser
= new MiniTerminal(shell
, SWT
.NONE
);
303 String url
= args
.length
> 0 ? args
[0] : System
.getProperty("user.home");
304 miniBrowser
.setPath(url
);
307 shell
.setSize(new Point(800, 480));
308 while (!shell
.isDisposed()) {
309 if (!display
.readAndDispatch())