001/* 002 * Copyright (C) 2012 eXo Platform SAS. 003 * 004 * This is free software; you can redistribute it and/or modify it 005 * under the terms of the GNU Lesser General Public License as 006 * published by the Free Software Foundation; either version 2.1 of 007 * the License, or (at your option) any later version. 008 * 009 * This software is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public 015 * License along with this software; if not, write to the Free 016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 018 */ 019 020package org.crsh.processor.jline; 021 022import org.crsh.shell.ShellProcessContext; 023import org.crsh.shell.ShellResponse; 024import org.crsh.text.Chunk; 025import org.crsh.text.Style; 026import org.crsh.text.Text; 027 028import java.io.IOException; 029import java.util.concurrent.CountDownLatch; 030import java.util.concurrent.atomic.AtomicReference; 031 032class JLineProcessContext implements ShellProcessContext { 033 034 /** . */ 035 private static final Character NO_ECHO = (char)0; 036 037 /** . */ 038 final JLineProcessor processor; 039 040 /** . */ 041 final CountDownLatch latch = new CountDownLatch(1); 042 043 /** . */ 044 final AtomicReference<ShellResponse> resp = new AtomicReference<ShellResponse>(); 045 046 public JLineProcessContext(JLineProcessor processor) { 047 this.processor = processor; 048 } 049 050 public boolean takeAlternateBuffer() { 051 if (!processor.useAlternate) { 052 processor.useAlternate = true; 053 054 // To get those codes I captured the output of telnet running top 055 // on OSX: 056 // 1/ sudo /usr/libexec/telnetd -debug #run telnet 057 // 2/ telnet localhost >output.txt 058 // 3/ type username + enter 059 // 4/ type password + enter 060 // 5/ type top + enter 061 // 6/ ctrl-c 062 // 7/ type exit + enter 063 064 // Save screen and erase 065 processor.writer.print("\033[?47h"); // Switches to the alternate screen 066 // writer.print("\033[1;43r"); 067// processor.writer.print("\033[m"); // Reset to normal (Sets SGR parameters : 0 m == m) 068 // writer.print("\033[4l"); 069 // writer.print("\033[?1h"); 070 // writer.print("\033[="); 071// processor.writer.print("\033[H"); // Move the cursor to home 072// processor.writer.print("\033[2J"); // Clear screen 073// processor.writer.flush(); 074 } 075 return true; 076 } 077 078 public boolean releaseAlternateBuffer() { 079 if (processor.useAlternate) { 080 processor.useAlternate = false; 081 processor.writer.print("\033[?47l"); // Switches back to the normal screen 082 } 083 return true; 084 } 085 086 public int getWidth() { 087 return processor.reader.getTerminal().getWidth(); 088 } 089 090 public int getHeight() { 091 return processor.reader.getTerminal().getHeight(); 092 } 093 094 public String getProperty(String name) { 095 return null; 096 } 097 098 public String readLine(String msg, boolean echo) { 099 try { 100 if (echo) { 101 return processor.reader.readLine(msg); 102 } else { 103 return processor.reader.readLine(msg, NO_ECHO); 104 } 105 } 106 catch (IOException e) { 107 return null; 108 } 109 } 110 111 public Class<Chunk> getConsumedType() { 112 return Chunk.class; 113 } 114 115 public void write(Chunk chunk) throws IOException { 116 provide(chunk); 117 } 118 119 public void provide(Chunk element) throws IOException { 120 if (element instanceof Text) { 121 Text textChunk = (Text)element; 122 processor.writer.append(textChunk.getText()); 123 } else if (element instanceof Style) { 124 try { 125 ((Style)element).writeAnsiTo(processor.writer); 126 } 127 catch (IOException ignore) { 128 } 129 } else { 130 131 132 // Clear screen 133 processor.writer.print("\033[2J"); 134 processor.writer.print("\033[1;1H"); 135 } 136 } 137 138 public void flush() { 139 processor.writer.flush(); 140 } 141 142 public void end(ShellResponse response) { 143 try { 144 resp.set(response); 145 latch.countDown(); 146 } 147 finally { 148 // Release screen if it wasn't done 149 releaseAlternateBuffer(); 150 } 151 } 152}