]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniTerminal.java
1 package org
.argeo
.minidesktop
;
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
;
58 private Process process
;
59 private boolean running
= false;
60 private OutputStream stdIn
= null;
62 private Thread readOut
;
64 public MiniTerminal(Composite parent
, String url
) {
69 public MiniTerminal(Composite parent
) {
70 charset
= StandardCharsets
.UTF_8
;
72 Display display
= parent
.getDisplay();
74 mono
= new Font(display
, "Monospace", 10, SWT
.NONE
);
76 parent
.setLayout(new GridLayout());
77 area
= new Canvas(parent
, SWT
.NONE
);
78 area
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
79 caret
= new Caret(area
, SWT
.NONE
);
82 area
.addKeyListener(this);
83 area
.addPaintListener(this);
85 username
= System
.getProperty("user.name");
87 host
= InetAddress
.getLocalHost().getHostName();
88 if (host
.indexOf('.') > 0)
89 host
= host
.substring(0, host
.indexOf('.'));
90 } catch (UnknownHostException e
) {
93 homeDir
= Paths
.get(System
.getProperty("user.home"));
96 buf
= new StringBuffer(prompt());
100 public void keyPressed(KeyEvent e
) {
104 public void keyReleased(KeyEvent e
) {
105 if (e
.keyLocation
!= 0)
106 return;// weird characters
107 // System.out.println(e.character);
108 if (e
.keyCode
== 0xd) {// return
112 // buf.append(prompt());
113 } else if (e
.keyCode
== 0x8) {// delete
114 if (userInput
.length() == 0)
116 userInput
.setLength(userInput
.length() - 1);
117 if (!running
&& buf
.length() > 0)
118 buf
.setLength(buf
.length() - 1);
119 } else if (e
.stateMask
== 0x40000 && e
.keyCode
== 0x63) {// Ctrl+C
122 } else if (e
.stateMask
== 0x40000 && e
.keyCode
== 0xdf) {// Ctrl+\
123 if (process
!= null) {
124 process
.destroyForcibly();
128 buf
.append(e
.character
);
129 userInput
.append(e
.character
);
132 if (area
.isDisposed())
135 // System.out.println("Append " + e);
140 stdIn
.write(Character
.toString(e
.character
).getBytes(charset
));
141 } catch (IOException e1
) {
142 // TODO Auto-generated catch block
143 e1
.printStackTrace();
149 protected String
prompt() {
150 String fileName
= currentDir
.equals(homeDir
) ?
"~" : currentDir
.getFileName().toString();
151 String end
= username
.equals("root") ?
"]# " : "]$ ";
152 return "[" + username
+ "@" + host
+ " " + fileName
+ end
;
155 private void displayPrompt() {
156 buf
.append(prompt() + userInput
);
159 protected void markLogicalLine() {
160 String str
= buf
.toString().trim();
161 logicalLines
.add(str
);
162 buf
= new StringBuffer("");
165 private void processUserInput() {
166 String cmd
= userInput
.toString();
167 userInput
= new StringBuffer("");
168 processUserInput(cmd
);
172 protected void processUserInput(String input
) {
174 StringTokenizer st
= new StringTokenizer(input
);
175 List
<String
> args
= new ArrayList
<>();
176 while (st
.hasMoreTokens())
177 args
.add(st
.nextToken());
178 if (args
.size() == 0) {
184 if (args
.get(0).equals("cd")) {
185 if (args
.size() == 1) {
188 Path newPath
= currentDir
.resolve(args
.get(1));
189 if (!Files
.exists(newPath
) || !Files
.isDirectory(newPath
)) {
190 println(newPath
+ ": No such file or directory");
198 // show current directory
199 else if (args
.get(0).equals("pwd")) {
205 else if (args
.get(0).equals("exit")) {
211 ProcessBuilder pb
= new ProcessBuilder(args
);
212 pb
.redirectErrorStream(true);
213 pb
.directory(currentDir
.toFile());
214 // Process process = Runtime.getRuntime().exec(input, null, currentPath.toFile());
215 process
= pb
.start();
217 stdIn
= process
.getOutputStream();
218 readOut
= new Thread("MiniTerminal read out") {
222 try (BufferedReader in
= new BufferedReader(
223 new InputStreamReader(process
.getInputStream(), charset
))) {
225 while ((line
= in
.readLine()) != null) {
228 } catch (IOException e
) {
229 println(e
.getMessage());
239 } catch (IOException e
) {
240 println(e
.getMessage());
245 protected int linesForLogicalLine(char[] line
) {
246 return line
.length
/ charsPerLine
+ 1;
249 protected void println(Object line
) {
254 protected void refreshLines(int charPerLine
, int nbrOfLines
) {
255 if (lines
.length
!= nbrOfLines
) {
256 lines
= new String
[nbrOfLines
];
257 Arrays
.fill(lines
, null);
259 if (this.charsPerLine
!= charPerLine
)
260 this.charsPerLine
= charPerLine
;
262 int currentLine
= nbrOfLines
- 1;
264 if (buf
.length() > 0) {
265 lines
[currentLine
] = buf
.toString();
267 lines
[currentLine
] = "";
271 logicalLines
: for (int i
= logicalLines
.size() - 1; i
>= 0; i
--) {
272 char[] logicalLine
= logicalLines
.get(i
).toCharArray();
273 int linesNeeded
= linesForLogicalLine(logicalLine
);
274 for (int j
= linesNeeded
- 1; j
>= 0; j
--) {
275 int from
= j
* charPerLine
;
276 int to
= j
== linesNeeded
- 1 ? from
+ charPerLine
: Math
.min(from
+ charPerLine
, logicalLine
.length
);
277 lines
[currentLine
] = new String(Arrays
.copyOfRange(logicalLine
, from
, to
));
278 // System.out.println("Set line " + currentLine + " to : " + lines[currentLine]);
287 public void paintControl(PaintEvent e
) {
290 if (charExtent
== null)
291 charExtent
= gc
.textExtent("a");
293 Point areaSize
= area
.getSize();
294 int charPerLine
= areaSize
.x
/ charExtent
.x
;
295 int nbrOfLines
= areaSize
.y
/ charExtent
.y
;
296 refreshLines(charPerLine
, nbrOfLines
);
298 for (int i
= 0; i
< lines
.length
; i
++) {
299 String line
= lines
[i
];
301 gc
.drawString(line
, 0, i
* charExtent
.y
);
303 // String toDraw = buf.toString();
304 // gc.drawString(toDraw, 0, 0);
305 // area.setCaret(caret);
308 protected void exitCalled() {
312 public void setPath(String path
) {
313 this.currentDir
= Paths
.get(path
);
316 public void setPath(Path path
) {
317 this.currentDir
= path
;
320 public static void main(String
[] args
) {
321 Display display
= Display
.getCurrent() == null ?
new Display() : Display
.getCurrent();
322 Shell shell
= new Shell(display
, SWT
.SHELL_TRIM
);
324 String url
= args
.length
> 0 ? args
[0] : System
.getProperty("user.home");
325 new MiniTerminal(shell
, url
) {
328 protected void exitCalled() {
335 shell
.setSize(new Point(800, 480));
336 while (!shell
.isDisposed()) {
337 if (!display
.readAndDispatch())