View Javadoc

1   /*
2    * Copyright (c) 2002-2012, the original author or authors.
3    *
4    * This software is distributable under the BSD license. See the terms of the
5    * BSD license in the documentation provided with this software.
6    *
7    * http://www.opensource.org/licenses/bsd-license.php
8    */
9   package jline;
10  
11  import jline.internal.Log;
12  import jline.internal.TerminalLineSettings;
13  
14  /**
15   * Terminal that is used for unix platforms. Terminal initialization
16   * is handled by issuing the <em>stty</em> command against the
17   * <em>/dev/tty</em> file to disable character echoing and enable
18   * character input. All known unix systems (including
19   * Linux and Macintosh OS X) support the <em>stty</em>), so this
20   * implementation should work for an reasonable POSIX system.
21   *
22   * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
23   * @author <a href="mailto:dwkemp@gmail.com">Dale Kemp</a>
24   * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
25   * @author <a href="mailto:jbonofre@apache.org">Jean-Baptiste Onofré</a>
26   * @since 2.0
27   */
28  public class UnixTerminal
29      extends TerminalSupport
30  {
31      private final TerminalLineSettings settings = new TerminalLineSettings();
32  
33      public UnixTerminal() throws Exception {
34          super(true);
35      }
36  
37      protected TerminalLineSettings getSettings() {
38          return settings;
39      }
40  
41      /**
42       * Remove line-buffered input by invoking "stty -icanon min 1"
43       * against the current terminal.
44       */
45      @Override
46      public void init() throws Exception {
47          super.init();
48  
49          setAnsiSupported(true);
50  
51          // Set the console to be character-buffered instead of line-buffered.
52          // Make sure we're distinguishing carriage return from newline.
53          // Allow ctrl-s keypress to be used (as forward search)
54          settings.set("-icanon min 1 -icrnl -inlcr -ixon");
55          settings.set("dsusp undef");
56  
57          setEchoEnabled(false);
58      }
59  
60      /**
61       * Restore the original terminal configuration, which can be used when
62       * shutting down the console reader. The ConsoleReader cannot be
63       * used after calling this method.
64       */
65      @Override
66      public void restore() throws Exception {
67          settings.restore();
68          super.restore();
69      }
70  
71      /**
72       * Returns the value of <tt>stty columns</tt> param.
73       */
74      @Override
75      public int getWidth() {
76          int w = settings.getProperty("columns");
77          return w < 1 ? DEFAULT_WIDTH : w;
78      }
79  
80      /**
81       * Returns the value of <tt>stty rows>/tt> param.
82       */
83      @Override
84      public int getHeight() {
85          int h = settings.getProperty("rows");
86          return h < 1 ? DEFAULT_HEIGHT : h;
87      }
88  
89      @Override
90      public synchronized void setEchoEnabled(final boolean enabled) {
91          try {
92              if (enabled) {
93                  settings.set("echo");
94              }
95              else {
96                  settings.set("-echo");
97              }
98              super.setEchoEnabled(enabled);
99          }
100         catch (Exception e) {
101             if (e instanceof InterruptedException) {
102                 Thread.currentThread().interrupt();
103             }
104             Log.error("Failed to ", (enabled ? "enable" : "disable"), " echo", e);
105         }
106     }
107 
108     public void disableInterruptCharacter()
109     {
110         try {
111             settings.set("intr undef");
112         }
113         catch (Exception e) {
114             if (e instanceof InterruptedException) {
115                 Thread.currentThread().interrupt();
116             }
117             Log.error("Failed to disable interrupt character", e);
118         }
119     }
120 
121     public void enableInterruptCharacter()
122     {
123         try {
124             settings.set("intr ^C");
125         }
126         catch (Exception e) {
127             if (e instanceof InterruptedException) {
128                 Thread.currentThread().interrupt();
129             }
130             Log.error("Failed to enable interrupt character", e);
131         }
132     }
133 }