8327476: Upgrade JLine to 3.26.1
Reviewed-by: ihse, vromero
This commit is contained in:
parent
0a4eeeaa3c
commit
aaa90b3005
@ -120,6 +120,7 @@ NATIVE_ACCESS_MODULES= \
|
|||||||
jdk.dynalink \
|
jdk.dynalink \
|
||||||
jdk.httpserver \
|
jdk.httpserver \
|
||||||
jdk.incubator.vector \
|
jdk.incubator.vector \
|
||||||
|
jdk.internal.le \
|
||||||
jdk.internal.vm.ci \
|
jdk.internal.vm.ci \
|
||||||
jdk.jfr \
|
jdk.jfr \
|
||||||
jdk.jsobject \
|
jdk.jsobject \
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation. Oracle designates this
|
|
||||||
# particular file as subject to the "Classpath" exception as provided
|
|
||||||
# by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
|
|
||||||
include LibCommon.gmk
|
|
||||||
|
|
||||||
ifeq ($(call isTargetOs, aix), false)
|
|
||||||
##############################################################################
|
|
||||||
## Build lible
|
|
||||||
##############################################################################
|
|
||||||
|
|
||||||
$(eval $(call SetupJdkLibrary, BUILD_LIBLE, \
|
|
||||||
NAME := le, \
|
|
||||||
LINK_TYPE := C++, \
|
|
||||||
OPTIMIZATION := LOW, \
|
|
||||||
EXTRA_HEADER_DIRS := \
|
|
||||||
java.base:libjava \
|
|
||||||
java.base:libjvm, \
|
|
||||||
LD_SET_ORIGIN := false, \
|
|
||||||
LIBS_windows := user32.lib, \
|
|
||||||
))
|
|
||||||
|
|
||||||
TARGETS += $(BUILD_LIBLE)
|
|
||||||
endif
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
|
||||||
|
|
||||||
class JDKNativePty {
|
|
||||||
|
|
||||||
static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
|
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static JnaNativePty open(Attributes attr, Size size) throws IOException {
|
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isatty(int fd) {
|
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
static String ttyname(int fd) {
|
|
||||||
throw new UnsupportedOperationException("Not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
|
||||||
|
|
||||||
class JDKNativePty {
|
|
||||||
|
|
||||||
static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
|
|
||||||
return LinuxNativePty.current(console);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JnaNativePty open(Attributes attr, Size size) throws IOException {
|
|
||||||
return LinuxNativePty.open(attr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isatty(int fd) {
|
|
||||||
return LinuxNativePty.isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String ttyname(int fd) {
|
|
||||||
return LinuxNativePty.ttyname(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,389 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
|
||||||
*
|
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
|
||||||
* BSD license in the documentation provided with this software.
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.linux;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
//import com.sun.jna.LastErrorException;
|
|
||||||
//import com.sun.jna.Platform;
|
|
||||||
//import com.sun.jna.Structure;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.ControlFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.InputFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
|
|
||||||
public interface CLibrary {//extends com.sun.jna.Library {
|
|
||||||
|
|
||||||
void tcgetattr(int fd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
void ioctl(int fd, int cmd, winsize data) throws LastErrorException;
|
|
||||||
|
|
||||||
int isatty(int fd);
|
|
||||||
|
|
||||||
void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
|
|
||||||
|
|
||||||
class winsize { //extends Structure {
|
|
||||||
public short ws_row;
|
|
||||||
public short ws_col;
|
|
||||||
public short ws_xpixel;
|
|
||||||
public short ws_ypixel;
|
|
||||||
|
|
||||||
public winsize() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public winsize(Size ws) {
|
|
||||||
ws_row = (short) ws.getRows();
|
|
||||||
ws_col = (short) ws.getColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size toSize() {
|
|
||||||
return new Size(ws_col, ws_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected List<String> getFieldOrder() {
|
|
||||||
// return Arrays.asList(//
|
|
||||||
// "ws_row",//
|
|
||||||
// "ws_col",//
|
|
||||||
// "ws_xpixel",//
|
|
||||||
// "ws_ypixel"//
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class termios {// extends Structure {
|
|
||||||
|
|
||||||
public int c_iflag;
|
|
||||||
public int c_oflag;
|
|
||||||
public int c_cflag;
|
|
||||||
public int c_lflag;
|
|
||||||
public byte c_line;
|
|
||||||
public byte[] c_cc = new byte[32];
|
|
||||||
public int c_ispeed;
|
|
||||||
public int c_ospeed;
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected List<String> getFieldOrder() {
|
|
||||||
// return Arrays.asList(//
|
|
||||||
// "c_iflag",//
|
|
||||||
// "c_oflag",//
|
|
||||||
// "c_cflag",//
|
|
||||||
// "c_lflag",//
|
|
||||||
// "c_line",//
|
|
||||||
// "c_cc",//
|
|
||||||
// "c_ispeed",//
|
|
||||||
// "c_ospeed"//
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
public termios() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public termios(Attributes t) {
|
|
||||||
// Input flags
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag);
|
|
||||||
c_iflag = setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag);
|
|
||||||
// Output flags
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag);
|
|
||||||
c_oflag = setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag);
|
|
||||||
// Control flags
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag);
|
|
||||||
c_cflag = setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag);
|
|
||||||
// Local flags
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag);
|
|
||||||
c_lflag = setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag);
|
|
||||||
// Control chars
|
|
||||||
c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF);
|
|
||||||
c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL);
|
|
||||||
c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2);
|
|
||||||
c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE);
|
|
||||||
c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE);
|
|
||||||
c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL);
|
|
||||||
c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT);
|
|
||||||
c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR);
|
|
||||||
c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT);
|
|
||||||
c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP);
|
|
||||||
c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART);
|
|
||||||
c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP);
|
|
||||||
c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT);
|
|
||||||
c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD);
|
|
||||||
c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN);
|
|
||||||
c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int setFlag(boolean flag, int value, int org) {
|
|
||||||
return flag ? (org | value) : org;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Attributes toAttributes() {
|
|
||||||
Attributes attr = new Attributes();
|
|
||||||
// Input flags
|
|
||||||
EnumSet<InputFlag> iflag = attr.getInputFlags();
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IGNBRK, IGNBRK);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.BRKINT, BRKINT);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IGNPAR, IGNPAR);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.PARMRK, PARMRK);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.INPCK, INPCK);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.ISTRIP, ISTRIP);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.INLCR, INLCR);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IGNCR, IGNCR);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.ICRNL, ICRNL);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IXON, IXON);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IXOFF, IXOFF);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IXANY, IXANY);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IMAXBEL, IMAXBEL);
|
|
||||||
addFlag(c_iflag, iflag, InputFlag.IUTF8, IUTF8);
|
|
||||||
// Output flags
|
|
||||||
EnumSet<OutputFlag> oflag = attr.getOutputFlags();
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.OPOST, OPOST);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.ONLCR, ONLCR);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.OCRNL, OCRNL);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.ONOCR, ONOCR);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.ONLRET, ONLRET);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.OFILL, OFILL);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.NLDLY, NLDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.TABDLY, TABDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.CRDLY, CRDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.FFDLY, FFDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.BSDLY, BSDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.VTDLY, VTDLY);
|
|
||||||
addFlag(c_oflag, oflag, OutputFlag.OFDEL, OFDEL);
|
|
||||||
// Control flags
|
|
||||||
EnumSet<ControlFlag> cflag = attr.getControlFlags();
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CS5, CS5);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CS6, CS6);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CS7, CS7);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CS8, CS8);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CSTOPB, CSTOPB);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CREAD, CREAD);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.PARENB, PARENB);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.PARODD, PARODD);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.HUPCL, HUPCL);
|
|
||||||
addFlag(c_cflag, cflag, ControlFlag.CLOCAL, CLOCAL);
|
|
||||||
// Local flags
|
|
||||||
EnumSet<LocalFlag> lflag = attr.getLocalFlags();
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHOKE, ECHOKE);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHOE, ECHOE);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHOK, ECHOK);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHO, ECHO);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHONL, ECHONL);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHOPRT, ECHOPRT);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ECHOCTL, ECHOCTL);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ISIG, ISIG);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.ICANON, ICANON);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.EXTPROC, EXTPROC);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.TOSTOP, TOSTOP);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.FLUSHO, FLUSHO);
|
|
||||||
addFlag(c_lflag, lflag, LocalFlag.NOFLSH, NOFLSH);
|
|
||||||
// Control chars
|
|
||||||
EnumMap<ControlChar, Integer> cc = attr.getControlChars();
|
|
||||||
cc.put(ControlChar.VEOF, (int) c_cc[VEOF]);
|
|
||||||
cc.put(ControlChar.VEOL, (int) c_cc[VEOL]);
|
|
||||||
cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]);
|
|
||||||
cc.put(ControlChar.VERASE, (int) c_cc[VERASE]);
|
|
||||||
cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]);
|
|
||||||
cc.put(ControlChar.VKILL, (int) c_cc[VKILL]);
|
|
||||||
cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]);
|
|
||||||
cc.put(ControlChar.VINTR, (int) c_cc[VINTR]);
|
|
||||||
cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]);
|
|
||||||
cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]);
|
|
||||||
cc.put(ControlChar.VSTART, (int) c_cc[VSTART]);
|
|
||||||
cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]);
|
|
||||||
cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]);
|
|
||||||
cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]);
|
|
||||||
cc.put(ControlChar.VMIN, (int) c_cc[VMIN]);
|
|
||||||
cc.put(ControlChar.VTIME, (int) c_cc[VTIME]);
|
|
||||||
// Return
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends Enum<T>> void addFlag(int value, EnumSet<T> flags, T flag, int v) {
|
|
||||||
if ((value & v) != 0) {
|
|
||||||
flags.add(flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONSTANTS
|
|
||||||
|
|
||||||
int TIOCGWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x40087468 : */0x00005413;
|
|
||||||
int TIOCSWINSZ = /*Platform.isMIPS() || Platform.isPPC() || Platform.isSPARC() ? 0x80087467 : */0x00005414;
|
|
||||||
|
|
||||||
int VINTR = 0;
|
|
||||||
int VQUIT = 1;
|
|
||||||
int VERASE = 2;
|
|
||||||
int VKILL = 3;
|
|
||||||
int VEOF = 4;
|
|
||||||
int VTIME = 5;
|
|
||||||
int VMIN = 6;
|
|
||||||
int VSWTC = 7;
|
|
||||||
int VSTART = 8;
|
|
||||||
int VSTOP = 9;
|
|
||||||
int VSUSP = 10;
|
|
||||||
int VEOL = 11;
|
|
||||||
int VREPRINT = 12;
|
|
||||||
int VDISCARD = 13;
|
|
||||||
int VWERASE = 14;
|
|
||||||
int VLNEXT = 15;
|
|
||||||
int VEOL2 = 16;
|
|
||||||
|
|
||||||
int IGNBRK = 0x0000001;
|
|
||||||
int BRKINT = 0x0000002;
|
|
||||||
int IGNPAR = 0x0000004;
|
|
||||||
int PARMRK = 0x0000008;
|
|
||||||
int INPCK = 0x0000010;
|
|
||||||
int ISTRIP = 0x0000020;
|
|
||||||
int INLCR = 0x0000040;
|
|
||||||
int IGNCR = 0x0000080;
|
|
||||||
int ICRNL = 0x0000100;
|
|
||||||
int IUCLC = 0x0000200;
|
|
||||||
int IXON = 0x0000400;
|
|
||||||
int IXANY = 0x0000800;
|
|
||||||
int IXOFF = 0x0001000;
|
|
||||||
int IMAXBEL = 0x0002000;
|
|
||||||
int IUTF8 = 0x0004000;
|
|
||||||
|
|
||||||
int OPOST = 0x0000001;
|
|
||||||
int OLCUC = 0x0000002;
|
|
||||||
int ONLCR = 0x0000004;
|
|
||||||
int OCRNL = 0x0000008;
|
|
||||||
int ONOCR = 0x0000010;
|
|
||||||
int ONLRET = 0x0000020;
|
|
||||||
int OFILL = 0x0000040;
|
|
||||||
int OFDEL = 0x0000080;
|
|
||||||
int NLDLY = 0x0000100;
|
|
||||||
int NL0 = 0x0000000;
|
|
||||||
int NL1 = 0x0000100;
|
|
||||||
int CRDLY = 0x0000600;
|
|
||||||
int CR0 = 0x0000000;
|
|
||||||
int CR1 = 0x0000200;
|
|
||||||
int CR2 = 0x0000400;
|
|
||||||
int CR3 = 0x0000600;
|
|
||||||
int TABDLY = 0x0001800;
|
|
||||||
int TAB0 = 0x0000000;
|
|
||||||
int TAB1 = 0x0000800;
|
|
||||||
int TAB2 = 0x0001000;
|
|
||||||
int TAB3 = 0x0001800;
|
|
||||||
int XTABS = 0x0001800;
|
|
||||||
int BSDLY = 0x0002000;
|
|
||||||
int BS0 = 0x0000000;
|
|
||||||
int BS1 = 0x0002000;
|
|
||||||
int VTDLY = 0x0004000;
|
|
||||||
int VT0 = 0x0000000;
|
|
||||||
int VT1 = 0x0004000;
|
|
||||||
int FFDLY = 0x0008000;
|
|
||||||
int FF0 = 0x0000000;
|
|
||||||
int FF1 = 0x0008000;
|
|
||||||
|
|
||||||
int CBAUD = 0x000100f;
|
|
||||||
int B0 = 0x0000000;
|
|
||||||
int B50 = 0x0000001;
|
|
||||||
int B75 = 0x0000002;
|
|
||||||
int B110 = 0x0000003;
|
|
||||||
int B134 = 0x0000004;
|
|
||||||
int B150 = 0x0000005;
|
|
||||||
int B200 = 0x0000006;
|
|
||||||
int B300 = 0x0000007;
|
|
||||||
int B600 = 0x0000008;
|
|
||||||
int B1200 = 0x0000009;
|
|
||||||
int B1800 = 0x000000a;
|
|
||||||
int B2400 = 0x000000b;
|
|
||||||
int B4800 = 0x000000c;
|
|
||||||
int B9600 = 0x000000d;
|
|
||||||
int B19200 = 0x000000e;
|
|
||||||
int B38400 = 0x000000f;
|
|
||||||
int EXTA = B19200;
|
|
||||||
int EXTB = B38400;
|
|
||||||
int CSIZE = 0x0000030;
|
|
||||||
int CS5 = 0x0000000;
|
|
||||||
int CS6 = 0x0000010;
|
|
||||||
int CS7 = 0x0000020;
|
|
||||||
int CS8 = 0x0000030;
|
|
||||||
int CSTOPB = 0x0000040;
|
|
||||||
int CREAD = 0x0000080;
|
|
||||||
int PARENB = 0x0000100;
|
|
||||||
int PARODD = 0x0000200;
|
|
||||||
int HUPCL = 0x0000400;
|
|
||||||
int CLOCAL = 0x0000800;
|
|
||||||
|
|
||||||
int ISIG = 0x0000001;
|
|
||||||
int ICANON = 0x0000002;
|
|
||||||
int XCASE = 0x0000004;
|
|
||||||
int ECHO = 0x0000008;
|
|
||||||
int ECHOE = 0x0000010;
|
|
||||||
int ECHOK = 0x0000020;
|
|
||||||
int ECHONL = 0x0000040;
|
|
||||||
int NOFLSH = 0x0000080;
|
|
||||||
int TOSTOP = 0x0000100;
|
|
||||||
int ECHOCTL = 0x0000200;
|
|
||||||
int ECHOPRT = 0x0000400;
|
|
||||||
int ECHOKE = 0x0000800;
|
|
||||||
int FLUSHO = 0x0001000;
|
|
||||||
int PENDIN = 0x0002000;
|
|
||||||
int IEXTEN = 0x0008000;
|
|
||||||
int EXTPROC = 0x0010000;
|
|
||||||
|
|
||||||
int TCSANOW = 0x0;
|
|
||||||
int TCSADRAIN = 0x1;
|
|
||||||
int TCSAFLUSH = 0x2;
|
|
||||||
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.linux;
|
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
|
|
||||||
public final class CLibraryImpl implements CLibrary {
|
|
||||||
|
|
||||||
static {
|
|
||||||
System.loadLibrary("le");
|
|
||||||
initIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native void initIDs();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void tcgetattr(int fd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ioctl(int fd, int cmd, winsize data) throws LastErrorException {
|
|
||||||
if (cmd == CLibrary.TIOCGWINSZ || cmd == CLibrary.TIOCSWINSZ) {
|
|
||||||
ioctl0(fd, cmd, data);
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("Command: " + cmd + ", not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private native void ioctl0(int fd, int cmd, winsize data) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native int isatty(int fd);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
|
|
||||||
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
|
||||||
*
|
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
|
||||||
* BSD license in the documentation provided with this software.
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.linux;
|
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
//import com.sun.jna.LastErrorException;
|
|
||||||
//import com.sun.jna.Native;
|
|
||||||
//import com.sun.jna.Platform;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
|
||||||
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TCSADRAIN;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCGWINSZ;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.TIOCSWINSZ;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.termios;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.linux.CLibrary.winsize;
|
|
||||||
|
|
||||||
public class LinuxNativePty extends JnaNativePty {
|
|
||||||
|
|
||||||
// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
|
|
||||||
private static final CLibrary C_LIBRARY = new CLibraryImpl();
|
|
||||||
|
|
||||||
public interface UtilLibrary {// extends com.sun.jna.Library {
|
|
||||||
|
|
||||||
void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException;
|
|
||||||
|
|
||||||
// UtilLibrary INSTANCE = Native.load("util", UtilLibrary.class);
|
|
||||||
UtilLibrary INSTANCE = new UtilLibraryImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LinuxNativePty current(TerminalProvider.Stream consoleStream) throws IOException {
|
|
||||||
switch (consoleStream) {
|
|
||||||
case Output:
|
|
||||||
return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0));
|
|
||||||
case Error:
|
|
||||||
return new LinuxNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0));
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LinuxNativePty open(Attributes attr, Size size) throws IOException {
|
|
||||||
int[] master = new int[1];
|
|
||||||
int[] slave = new int[1];
|
|
||||||
byte[] buf = new byte[64];
|
|
||||||
UtilLibrary.INSTANCE.openpty(master, slave, buf,
|
|
||||||
attr != null ? new termios(attr) : null,
|
|
||||||
size != null ? new winsize(size) : null);
|
|
||||||
int len = 0;
|
|
||||||
while (buf[len] != 0) {
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
String name = new String(buf, 0, len);
|
|
||||||
return new LinuxNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
|
|
||||||
super(master, masterFD, slave, slaveFD, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LinuxNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
|
|
||||||
super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Attributes getAttr() throws IOException {
|
|
||||||
termios termios = new termios();
|
|
||||||
C_LIBRARY.tcgetattr(getSlave(), termios);
|
|
||||||
return termios.toAttributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doSetAttr(Attributes attr) throws IOException {
|
|
||||||
termios termios = new termios(attr);
|
|
||||||
termios org = new termios();
|
|
||||||
C_LIBRARY.tcgetattr(getSlave(), org);
|
|
||||||
org.c_iflag = termios.c_iflag;
|
|
||||||
org.c_oflag = termios.c_oflag;
|
|
||||||
org.c_lflag = termios.c_lflag;
|
|
||||||
System.arraycopy(termios.c_cc, 0, org.c_cc, 0, termios.c_cc.length);
|
|
||||||
C_LIBRARY.tcsetattr(getSlave(), TCSADRAIN, org);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Size getSize() throws IOException {
|
|
||||||
winsize sz = new winsize();
|
|
||||||
C_LIBRARY.ioctl(getSlave(), TIOCGWINSZ, sz);
|
|
||||||
return sz.toSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSize(Size size) throws IOException {
|
|
||||||
winsize sz = new winsize(size);
|
|
||||||
C_LIBRARY.ioctl(getSlave(), TIOCSWINSZ, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int isatty(int fd) {
|
|
||||||
return C_LIBRARY.isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String ttyname(int slave) {
|
|
||||||
byte[] buf = new byte[64];
|
|
||||||
C_LIBRARY.ttyname_r(slave, buf, buf.length);
|
|
||||||
int len = 0;
|
|
||||||
while (buf[len] != 0) {
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
return new String(buf, 0, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.linux;
|
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.linux.LinuxNativePty.UtilLibrary;
|
|
||||||
|
|
||||||
public final class UtilLibraryImpl implements UtilLibrary {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openpty(int[] master, int[] slave, byte[] name, CLibrary.termios t, CLibrary.winsize s) throws LastErrorException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,207 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jni.h"
|
|
||||||
#include "jni_util.h"
|
|
||||||
#include "jvm.h"
|
|
||||||
#include "jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
static jclass lastErrorExceptionClass;
|
|
||||||
static jmethodID lastErrorExceptionConstructor;
|
|
||||||
|
|
||||||
static jclass termios_j;
|
|
||||||
static jfieldID c_iflag;
|
|
||||||
static jfieldID c_oflag;
|
|
||||||
static jfieldID c_cflag;
|
|
||||||
static jfieldID c_lflag;
|
|
||||||
static jfieldID c_line;
|
|
||||||
static jfieldID c_cc;
|
|
||||||
static jfieldID c_ispeed;
|
|
||||||
static jfieldID c_ospeed;
|
|
||||||
|
|
||||||
static jclass winsize_j;
|
|
||||||
static jfieldID ws_row;
|
|
||||||
static jfieldID ws_col;
|
|
||||||
static jfieldID ws_xpixel;
|
|
||||||
static jfieldID ws_ypixel;
|
|
||||||
|
|
||||||
static void throw_errno(JNIEnv *env);
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_initIDs
|
|
||||||
(JNIEnv *env, jclass unused) {
|
|
||||||
jclass cls;
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
|
|
||||||
lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "<init>", "(J)V");
|
|
||||||
CHECK_NULL(lastErrorExceptionConstructor);
|
|
||||||
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$termios");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
termios_j = (jclass) env->NewGlobalRef(cls);
|
|
||||||
c_iflag = env->GetFieldID(termios_j, "c_iflag", "I");
|
|
||||||
CHECK_NULL(c_iflag);
|
|
||||||
c_oflag = env->GetFieldID(termios_j, "c_oflag", "I");
|
|
||||||
CHECK_NULL(c_oflag);
|
|
||||||
c_cflag = env->GetFieldID(termios_j, "c_cflag", "I");
|
|
||||||
CHECK_NULL(c_cflag);
|
|
||||||
c_lflag = env->GetFieldID(termios_j, "c_lflag", "I");
|
|
||||||
CHECK_NULL(c_lflag);
|
|
||||||
c_line = env->GetFieldID(termios_j, "c_line", "B");
|
|
||||||
CHECK_NULL(c_line);
|
|
||||||
c_cc = env->GetFieldID(termios_j, "c_cc", "[B");
|
|
||||||
CHECK_NULL(c_cc);
|
|
||||||
c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "I");
|
|
||||||
CHECK_NULL(c_ispeed);
|
|
||||||
c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "I");
|
|
||||||
CHECK_NULL(c_ospeed);
|
|
||||||
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/linux/CLibrary$winsize");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
winsize_j = (jclass) env->NewGlobalRef(cls);
|
|
||||||
ws_row = env->GetFieldID(winsize_j, "ws_row", "S");
|
|
||||||
CHECK_NULL(ws_row);
|
|
||||||
ws_col = env->GetFieldID(winsize_j, "ws_col", "S");
|
|
||||||
CHECK_NULL(ws_col);
|
|
||||||
ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S");
|
|
||||||
CHECK_NULL(ws_xpixel);
|
|
||||||
ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S");
|
|
||||||
CHECK_NULL(ws_ypixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcgetattr
|
|
||||||
(JNIEnv *env, jobject, jint fd, jobject result) {
|
|
||||||
termios data;
|
|
||||||
|
|
||||||
if (tcgetattr(fd, &data) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetIntField(result, c_iflag, data.c_iflag);
|
|
||||||
env->SetIntField(result, c_oflag, data.c_oflag);
|
|
||||||
env->SetIntField(result, c_cflag, data.c_cflag);
|
|
||||||
env->SetIntField(result, c_lflag, data.c_lflag);
|
|
||||||
env->SetIntField(result, c_line, data.c_line);
|
|
||||||
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc);
|
|
||||||
env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc);//TODO: cast?
|
|
||||||
env->SetIntField(result, c_ispeed, cfgetispeed(&data));
|
|
||||||
env->SetIntField(result, c_ospeed, cfgetospeed(&data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
|
|
||||||
* Method: tcsetattr
|
|
||||||
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/termios;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_tcsetattr
|
|
||||||
(JNIEnv *env, jobject, jint fd, jint cmd, jobject input) {
|
|
||||||
termios data;
|
|
||||||
|
|
||||||
data.c_iflag = env->GetIntField(input, c_iflag);
|
|
||||||
data.c_oflag = env->GetIntField(input, c_oflag);
|
|
||||||
data.c_cflag = env->GetIntField(input, c_cflag);
|
|
||||||
data.c_lflag = env->GetIntField(input, c_lflag);
|
|
||||||
data.c_line = env->GetIntField(input, c_line);
|
|
||||||
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc);
|
|
||||||
env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc);
|
|
||||||
cfsetispeed(&data, env->GetIntField(input, c_ispeed));
|
|
||||||
cfsetospeed(&data, env->GetIntField(input, c_ospeed));
|
|
||||||
|
|
||||||
if (tcsetattr(fd, cmd, &data) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
|
|
||||||
* Method: ioctl0
|
|
||||||
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/linux/CLibrary/winsize;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ioctl0
|
|
||||||
(JNIEnv *env, jobject, jint fd, jint cmd, jobject data) {
|
|
||||||
winsize ws;
|
|
||||||
|
|
||||||
ws.ws_row = env->GetShortField(data, ws_row);
|
|
||||||
ws.ws_col = env->GetShortField(data, ws_col);
|
|
||||||
ws.ws_xpixel = env->GetShortField(data, ws_xpixel);
|
|
||||||
ws.ws_ypixel = env->GetShortField(data, ws_ypixel);
|
|
||||||
|
|
||||||
if (ioctl(fd, cmd, &ws) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetShortField(data, ws_row, ws.ws_row);
|
|
||||||
env->SetShortField(data, ws_col, ws.ws_col);
|
|
||||||
env->SetShortField(data, ws_xpixel, ws.ws_xpixel);
|
|
||||||
env->SetShortField(data, ws_ypixel, ws.ws_ypixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
|
|
||||||
* Method: isatty
|
|
||||||
* Signature: (I)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_isatty
|
|
||||||
(JNIEnv *, jobject, jint fd) {
|
|
||||||
return isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl
|
|
||||||
* Method: ttyname_r
|
|
||||||
* Signature: (I[BI)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_linux_CLibraryImpl_ttyname_1r
|
|
||||||
(JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) {
|
|
||||||
char *data = new char[len];
|
|
||||||
int error = ttyname_r(fd, data, len);
|
|
||||||
|
|
||||||
if (error != 0) {
|
|
||||||
delete[] data;
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetByteArrayRegion(buf, 0, len, (jbyte *) data);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Throws LastErrorException based on the errno:
|
|
||||||
*/
|
|
||||||
static void throw_errno(JNIEnv *env) {
|
|
||||||
jobject exc = env->NewObject(lastErrorExceptionClass,
|
|
||||||
lastErrorExceptionConstructor,
|
|
||||||
errno);
|
|
||||||
env->Throw((jthrowable) exc);
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.osx.OsXNativePty;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
|
||||||
|
|
||||||
class JDKNativePty {
|
|
||||||
|
|
||||||
static JnaNativePty current(TerminalProvider.Stream console) throws IOException {
|
|
||||||
return OsXNativePty.current(console);
|
|
||||||
}
|
|
||||||
|
|
||||||
static JnaNativePty open(Attributes attr, Size size) throws IOException {
|
|
||||||
return OsXNativePty.open(attr, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int isatty(int fd) {
|
|
||||||
return OsXNativePty.isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String ttyname(int fd) {
|
|
||||||
return OsXNativePty.ttyname(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,394 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
|
||||||
*
|
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
|
||||||
* BSD license in the documentation provided with this software.
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.osx;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.EnumMap;
|
|
||||||
import java.util.EnumSet;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
//import com.sun.jna.LastErrorException;
|
|
||||||
//import com.sun.jna.NativeLong;
|
|
||||||
//import com.sun.jna.Structure;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.ControlFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.InputFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
|
|
||||||
public interface CLibrary {//extends com.sun.jna.Library {
|
|
||||||
|
|
||||||
void tcgetattr(int fd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException;
|
|
||||||
|
|
||||||
int isatty(int fd);
|
|
||||||
|
|
||||||
void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
|
|
||||||
|
|
||||||
void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException;
|
|
||||||
|
|
||||||
class winsize { //extends Structure {
|
|
||||||
public short ws_row;
|
|
||||||
public short ws_col;
|
|
||||||
public short ws_xpixel;
|
|
||||||
public short ws_ypixel;
|
|
||||||
|
|
||||||
public winsize() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public winsize(Size ws) {
|
|
||||||
ws_row = (short) ws.getRows();
|
|
||||||
ws_col = (short) ws.getColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Size toSize() {
|
|
||||||
return new Size(ws_col, ws_row);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected List<String> getFieldOrder() {
|
|
||||||
// return Arrays.asList(//
|
|
||||||
// "ws_row",//
|
|
||||||
// "ws_col",//
|
|
||||||
// "ws_xpixel",//
|
|
||||||
// "ws_ypixel"//
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class termios { //extends Structure {
|
|
||||||
|
|
||||||
public NativeLong c_iflag;
|
|
||||||
public NativeLong c_oflag;
|
|
||||||
public NativeLong c_cflag;
|
|
||||||
public NativeLong c_lflag;
|
|
||||||
public byte[] c_cc = new byte[20];
|
|
||||||
public NativeLong c_ispeed;
|
|
||||||
public NativeLong c_ospeed;
|
|
||||||
|
|
||||||
// @Override
|
|
||||||
// protected List<String> getFieldOrder() {
|
|
||||||
// return Arrays.asList(//
|
|
||||||
// "c_iflag",//
|
|
||||||
// "c_oflag",//
|
|
||||||
// "c_cflag",//
|
|
||||||
// "c_lflag",//
|
|
||||||
// "c_cc",//
|
|
||||||
// "c_ispeed",//
|
|
||||||
// "c_ospeed"//
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
{
|
|
||||||
c_iflag = new NativeLong(0);
|
|
||||||
c_oflag = new NativeLong(0);
|
|
||||||
c_cflag = new NativeLong(0);
|
|
||||||
c_lflag = new NativeLong(0);
|
|
||||||
c_ispeed = new NativeLong(0);
|
|
||||||
c_ospeed = new NativeLong(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public termios() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public termios(Attributes t) {
|
|
||||||
// Input flags
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IGNBRK), IGNBRK, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.BRKINT), BRKINT, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IGNPAR), IGNPAR, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.PARMRK), PARMRK, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.INPCK), INPCK, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.ISTRIP), ISTRIP, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.INLCR), INLCR, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IGNCR), IGNCR, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.ICRNL), ICRNL, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IXON), IXON, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IXOFF), IXOFF, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IXANY), IXANY, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IMAXBEL), IMAXBEL, c_iflag);
|
|
||||||
setFlag(t.getInputFlag(InputFlag.IUTF8), IUTF8, c_iflag);
|
|
||||||
// Output flags
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.OPOST), OPOST, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.ONLCR), ONLCR, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.OXTABS), OXTABS, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.ONOEOT), ONOEOT, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.OCRNL), OCRNL, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.ONOCR), ONOCR, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.ONLRET), ONLRET, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.OFILL), OFILL, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.NLDLY), NLDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.TABDLY), TABDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.CRDLY), CRDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.FFDLY), FFDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.BSDLY), BSDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.VTDLY), VTDLY, c_oflag);
|
|
||||||
setFlag(t.getOutputFlag(OutputFlag.OFDEL), OFDEL, c_oflag);
|
|
||||||
// Control flags
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CIGNORE), CIGNORE, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CS5), CS5, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CS6), CS6, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CS7), CS7, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CS8), CS8, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CSTOPB), CSTOPB, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CREAD), CREAD, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.PARENB), PARENB, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.PARODD), PARODD, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.HUPCL), HUPCL, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CLOCAL), CLOCAL, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CCTS_OFLOW), CCTS_OFLOW, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CRTS_IFLOW), CRTS_IFLOW, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CDTR_IFLOW), CDTR_IFLOW, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CDSR_OFLOW), CDSR_OFLOW, c_cflag);
|
|
||||||
setFlag(t.getControlFlag(ControlFlag.CCAR_OFLOW), CCAR_OFLOW, c_cflag);
|
|
||||||
// Local flags
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHOKE), ECHOKE, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHOE), ECHOE, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHOK), ECHOK, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHO), ECHO, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHONL), ECHONL, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHOPRT), ECHOPRT, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ECHOCTL), ECHOCTL, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ISIG), ISIG, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ICANON), ICANON, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.ALTWERASE), ALTWERASE, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.IEXTEN), IEXTEN, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.EXTPROC), EXTPROC, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.TOSTOP), TOSTOP, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.FLUSHO), FLUSHO, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.NOKERNINFO), NOKERNINFO, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.PENDIN), PENDIN, c_lflag);
|
|
||||||
setFlag(t.getLocalFlag(LocalFlag.NOFLSH), NOFLSH, c_lflag);
|
|
||||||
// Control chars
|
|
||||||
c_cc[VEOF] = (byte) t.getControlChar(ControlChar.VEOF);
|
|
||||||
c_cc[VEOL] = (byte) t.getControlChar(ControlChar.VEOL);
|
|
||||||
c_cc[VEOL2] = (byte) t.getControlChar(ControlChar.VEOL2);
|
|
||||||
c_cc[VERASE] = (byte) t.getControlChar(ControlChar.VERASE);
|
|
||||||
c_cc[VWERASE] = (byte) t.getControlChar(ControlChar.VWERASE);
|
|
||||||
c_cc[VKILL] = (byte) t.getControlChar(ControlChar.VKILL);
|
|
||||||
c_cc[VREPRINT] = (byte) t.getControlChar(ControlChar.VREPRINT);
|
|
||||||
c_cc[VINTR] = (byte) t.getControlChar(ControlChar.VINTR);
|
|
||||||
c_cc[VQUIT] = (byte) t.getControlChar(ControlChar.VQUIT);
|
|
||||||
c_cc[VSUSP] = (byte) t.getControlChar(ControlChar.VSUSP);
|
|
||||||
c_cc[VDSUSP] = (byte) t.getControlChar(ControlChar.VDSUSP);
|
|
||||||
c_cc[VSTART] = (byte) t.getControlChar(ControlChar.VSTART);
|
|
||||||
c_cc[VSTOP] = (byte) t.getControlChar(ControlChar.VSTOP);
|
|
||||||
c_cc[VLNEXT] = (byte) t.getControlChar(ControlChar.VLNEXT);
|
|
||||||
c_cc[VDISCARD] = (byte) t.getControlChar(ControlChar.VDISCARD);
|
|
||||||
c_cc[VMIN] = (byte) t.getControlChar(ControlChar.VMIN);
|
|
||||||
c_cc[VTIME] = (byte) t.getControlChar(ControlChar.VTIME);
|
|
||||||
c_cc[VSTATUS] = (byte) t.getControlChar(ControlChar.VSTATUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setFlag(boolean flag, long value, NativeLong org) {
|
|
||||||
org.setValue(flag ? org.longValue() | value : org.longValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Attributes toAttributes() {
|
|
||||||
Attributes attr = new Attributes();
|
|
||||||
// Input flags
|
|
||||||
EnumSet<InputFlag> iflag = attr.getInputFlags();
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNBRK, IGNBRK);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.BRKINT, BRKINT);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNPAR, IGNPAR);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.PARMRK, PARMRK);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.INPCK, INPCK);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.ISTRIP, ISTRIP);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.INLCR, INLCR);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IGNCR, IGNCR);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.ICRNL, ICRNL);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IXON, IXON);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IXOFF, IXOFF);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IXANY, IXANY);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IMAXBEL, IMAXBEL);
|
|
||||||
addFlag(c_iflag.longValue(), iflag, InputFlag.IUTF8, IUTF8);
|
|
||||||
// Output flags
|
|
||||||
EnumSet<OutputFlag> oflag = attr.getOutputFlags();
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.OPOST, OPOST);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLCR, ONLCR);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.OXTABS, OXTABS);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOEOT, ONOEOT);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.OCRNL, OCRNL);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONOCR, ONOCR);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.ONLRET, ONLRET);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.OFILL, OFILL);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.NLDLY, NLDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.TABDLY, TABDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.CRDLY, CRDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.FFDLY, FFDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.BSDLY, BSDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.VTDLY, VTDLY);
|
|
||||||
addFlag(c_oflag.longValue(), oflag, OutputFlag.OFDEL, OFDEL);
|
|
||||||
// Control flags
|
|
||||||
EnumSet<ControlFlag> cflag = attr.getControlFlags();
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CIGNORE, CIGNORE);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS5, CS5);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS6, CS6);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS7, CS7);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CS8, CS8);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CSTOPB, CSTOPB);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CREAD, CREAD);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.PARENB, PARENB);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.PARODD, PARODD);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.HUPCL, HUPCL);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CLOCAL, CLOCAL);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CCTS_OFLOW, CCTS_OFLOW);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CRTS_IFLOW, CRTS_IFLOW);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CDSR_OFLOW, CDSR_OFLOW);
|
|
||||||
addFlag(c_cflag.longValue(), cflag, ControlFlag.CCAR_OFLOW, CCAR_OFLOW);
|
|
||||||
// Local flags
|
|
||||||
EnumSet<LocalFlag> lflag = attr.getLocalFlags();
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOKE, ECHOKE);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOE, ECHOE);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOK, ECHOK);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHO, ECHO);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHONL, ECHONL);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOPRT, ECHOPRT);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ECHOCTL, ECHOCTL);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ISIG, ISIG);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ICANON, ICANON);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.ALTWERASE, ALTWERASE);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.IEXTEN, IEXTEN);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.EXTPROC, EXTPROC);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.TOSTOP, TOSTOP);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.FLUSHO, FLUSHO);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.NOKERNINFO, NOKERNINFO);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.PENDIN, PENDIN);
|
|
||||||
addFlag(c_lflag.longValue(), lflag, LocalFlag.NOFLSH, NOFLSH);
|
|
||||||
// Control chars
|
|
||||||
EnumMap<ControlChar, Integer> cc = attr.getControlChars();
|
|
||||||
cc.put(ControlChar.VEOF, (int) c_cc[VEOF]);
|
|
||||||
cc.put(ControlChar.VEOL, (int) c_cc[VEOL]);
|
|
||||||
cc.put(ControlChar.VEOL2, (int) c_cc[VEOL2]);
|
|
||||||
cc.put(ControlChar.VERASE, (int) c_cc[VERASE]);
|
|
||||||
cc.put(ControlChar.VWERASE, (int) c_cc[VWERASE]);
|
|
||||||
cc.put(ControlChar.VKILL, (int) c_cc[VKILL]);
|
|
||||||
cc.put(ControlChar.VREPRINT, (int) c_cc[VREPRINT]);
|
|
||||||
cc.put(ControlChar.VINTR, (int) c_cc[VINTR]);
|
|
||||||
cc.put(ControlChar.VQUIT, (int) c_cc[VQUIT]);
|
|
||||||
cc.put(ControlChar.VSUSP, (int) c_cc[VSUSP]);
|
|
||||||
cc.put(ControlChar.VDSUSP, (int) c_cc[VDSUSP]);
|
|
||||||
cc.put(ControlChar.VSTART, (int) c_cc[VSTART]);
|
|
||||||
cc.put(ControlChar.VSTOP, (int) c_cc[VSTOP]);
|
|
||||||
cc.put(ControlChar.VLNEXT, (int) c_cc[VLNEXT]);
|
|
||||||
cc.put(ControlChar.VDISCARD, (int) c_cc[VDISCARD]);
|
|
||||||
cc.put(ControlChar.VMIN, (int) c_cc[VMIN]);
|
|
||||||
cc.put(ControlChar.VTIME, (int) c_cc[VTIME]);
|
|
||||||
cc.put(ControlChar.VSTATUS, (int) c_cc[VSTATUS]);
|
|
||||||
// Return
|
|
||||||
return attr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T extends Enum<T>> void addFlag(long value, EnumSet<T> flags, T flag, int v) {
|
|
||||||
if ((value & v) != 0) {
|
|
||||||
flags.add(flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONSTANTS
|
|
||||||
|
|
||||||
long TIOCGWINSZ = 0x40087468L;
|
|
||||||
long TIOCSWINSZ = 0x80087467L;
|
|
||||||
|
|
||||||
int TCSANOW = 0x00000000;
|
|
||||||
|
|
||||||
int VEOF = 0;
|
|
||||||
int VEOL = 1;
|
|
||||||
int VEOL2 = 2;
|
|
||||||
int VERASE = 3;
|
|
||||||
int VWERASE = 4;
|
|
||||||
int VKILL = 5;
|
|
||||||
int VREPRINT = 6;
|
|
||||||
int VINTR = 8;
|
|
||||||
int VQUIT = 9;
|
|
||||||
int VSUSP = 10;
|
|
||||||
int VDSUSP = 11;
|
|
||||||
int VSTART = 12;
|
|
||||||
int VSTOP = 13;
|
|
||||||
int VLNEXT = 14;
|
|
||||||
int VDISCARD = 15;
|
|
||||||
int VMIN = 16;
|
|
||||||
int VTIME = 17;
|
|
||||||
int VSTATUS = 18;
|
|
||||||
|
|
||||||
int IGNBRK = 0x00000001;
|
|
||||||
int BRKINT = 0x00000002;
|
|
||||||
int IGNPAR = 0x00000004;
|
|
||||||
int PARMRK = 0x00000008;
|
|
||||||
int INPCK = 0x00000010;
|
|
||||||
int ISTRIP = 0x00000020;
|
|
||||||
int INLCR = 0x00000040;
|
|
||||||
int IGNCR = 0x00000080;
|
|
||||||
int ICRNL = 0x00000100;
|
|
||||||
int IXON = 0x00000200;
|
|
||||||
int IXOFF = 0x00000400;
|
|
||||||
int IXANY = 0x00000800;
|
|
||||||
int IMAXBEL = 0x00002000;
|
|
||||||
int IUTF8 = 0x00004000;
|
|
||||||
|
|
||||||
int OPOST = 0x00000001;
|
|
||||||
int ONLCR = 0x00000002;
|
|
||||||
int OXTABS = 0x00000004;
|
|
||||||
int ONOEOT = 0x00000008;
|
|
||||||
int OCRNL = 0x00000010;
|
|
||||||
int ONOCR = 0x00000020;
|
|
||||||
int ONLRET = 0x00000040;
|
|
||||||
int OFILL = 0x00000080;
|
|
||||||
int NLDLY = 0x00000300;
|
|
||||||
int TABDLY = 0x00000c04;
|
|
||||||
int CRDLY = 0x00003000;
|
|
||||||
int FFDLY = 0x00004000;
|
|
||||||
int BSDLY = 0x00008000;
|
|
||||||
int VTDLY = 0x00010000;
|
|
||||||
int OFDEL = 0x00020000;
|
|
||||||
|
|
||||||
int CIGNORE = 0x00000001;
|
|
||||||
int CS5 = 0x00000000;
|
|
||||||
int CS6 = 0x00000100;
|
|
||||||
int CS7 = 0x00000200;
|
|
||||||
int CS8 = 0x00000300;
|
|
||||||
int CSTOPB = 0x00000400;
|
|
||||||
int CREAD = 0x00000800;
|
|
||||||
int PARENB = 0x00001000;
|
|
||||||
int PARODD = 0x00002000;
|
|
||||||
int HUPCL = 0x00004000;
|
|
||||||
int CLOCAL = 0x00008000;
|
|
||||||
int CCTS_OFLOW = 0x00010000;
|
|
||||||
int CRTS_IFLOW = 0x00020000;
|
|
||||||
int CDTR_IFLOW = 0x00040000;
|
|
||||||
int CDSR_OFLOW = 0x00080000;
|
|
||||||
int CCAR_OFLOW = 0x00100000;
|
|
||||||
|
|
||||||
int ECHOKE = 0x00000001;
|
|
||||||
int ECHOE = 0x00000002;
|
|
||||||
int ECHOK = 0x00000004;
|
|
||||||
int ECHO = 0x00000008;
|
|
||||||
int ECHONL = 0x00000010;
|
|
||||||
int ECHOPRT = 0x00000020;
|
|
||||||
int ECHOCTL = 0x00000040;
|
|
||||||
int ISIG = 0x00000080;
|
|
||||||
int ICANON = 0x00000100;
|
|
||||||
int ALTWERASE = 0x00000200;
|
|
||||||
int IEXTEN = 0x00000400;
|
|
||||||
int EXTPROC = 0x00000800;
|
|
||||||
int TOSTOP = 0x00400000;
|
|
||||||
int FLUSHO = 0x00800000;
|
|
||||||
int NOKERNINFO = 0x02000000;
|
|
||||||
int PENDIN = 0x20000000;
|
|
||||||
int NOFLSH = 0x80000000;
|
|
||||||
|
|
||||||
}
|
|
@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.osx;
|
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.LastErrorException;
|
|
||||||
|
|
||||||
public final class CLibraryImpl implements CLibrary {
|
|
||||||
|
|
||||||
static {
|
|
||||||
System.loadLibrary("le");
|
|
||||||
initIDs();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static native void initIDs();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void tcgetattr(int fd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void tcsetattr(int fd, int cmd, termios termios) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void ioctl(int fd, NativeLong cmd, winsize data) throws LastErrorException {
|
|
||||||
if (cmd.longValue() == CLibrary.TIOCGWINSZ || cmd.longValue() == CLibrary.TIOCSWINSZ) {
|
|
||||||
ioctl0(fd, cmd.longValue(), data);
|
|
||||||
} else {
|
|
||||||
throw new UnsupportedOperationException("Command: " + cmd + ", not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private native void ioctl0(int fd, long cmd, winsize data) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native int isatty(int fd);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public native void ttyname_r(int fd, byte[] buf, int len) throws LastErrorException;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openpty(int[] master, int[] slave, byte[] name, termios t, winsize s) throws LastErrorException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.osx;
|
|
||||||
|
|
||||||
class NativeLong {
|
|
||||||
|
|
||||||
public long value;
|
|
||||||
|
|
||||||
public NativeLong(long value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(long value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long longValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
|
||||||
*
|
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
|
||||||
* BSD license in the documentation provided with this software.
|
|
||||||
*
|
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna.osx;
|
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
//import com.sun.jna.Native;
|
|
||||||
//import com.sun.jna.NativeLong;
|
|
||||||
//import com.sun.jna.Platform;
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.jna.JnaNativePty;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
|
||||||
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TCSANOW;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCGWINSZ;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.TIOCSWINSZ;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.termios;
|
|
||||||
import static jdk.internal.org.jline.terminal.impl.jna.osx.CLibrary.winsize;
|
|
||||||
|
|
||||||
public class OsXNativePty extends JnaNativePty {
|
|
||||||
|
|
||||||
// private static final CLibrary C_LIBRARY = Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
|
|
||||||
private static final CLibrary C_LIBRARY = new CLibraryImpl();//Native.load(Platform.C_LIBRARY_NAME, CLibrary.class);
|
|
||||||
|
|
||||||
public static OsXNativePty current(TerminalProvider.Stream consoleStream) throws IOException {
|
|
||||||
switch (consoleStream) {
|
|
||||||
case Output:
|
|
||||||
return new OsXNativePty(-1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(0));
|
|
||||||
case Error:
|
|
||||||
return new OsXNativePty(-1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(0));
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("Unsupport stream for console: " + consoleStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static OsXNativePty open(Attributes attr, Size size) throws IOException {
|
|
||||||
int[] master = new int[1];
|
|
||||||
int[] slave = new int[1];
|
|
||||||
byte[] buf = new byte[64];
|
|
||||||
C_LIBRARY.openpty(master, slave, buf,
|
|
||||||
attr != null ? new termios(attr) : null,
|
|
||||||
size != null ? new winsize(size) : null);
|
|
||||||
int len = 0;
|
|
||||||
while (buf[len] != 0) {
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
String name = new String(buf, 0, len);
|
|
||||||
return new OsXNativePty(master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, String name) {
|
|
||||||
super(master, masterFD, slave, slaveFD, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OsXNativePty(int master, FileDescriptor masterFD, int slave, FileDescriptor slaveFD, int slaveOut, FileDescriptor slaveOutFD, String name) {
|
|
||||||
super(master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Attributes getAttr() throws IOException {
|
|
||||||
termios termios = new termios();
|
|
||||||
C_LIBRARY.tcgetattr(getSlave(), termios);
|
|
||||||
return termios.toAttributes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doSetAttr(Attributes attr) throws IOException {
|
|
||||||
termios termios = new termios(attr);
|
|
||||||
C_LIBRARY.tcsetattr(getSlave(), TCSANOW, termios);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Size getSize() throws IOException {
|
|
||||||
winsize sz = new winsize();
|
|
||||||
C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCGWINSZ), sz);
|
|
||||||
return sz.toSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSize(Size size) throws IOException {
|
|
||||||
winsize sz = new winsize(size);
|
|
||||||
C_LIBRARY.ioctl(getSlave(), new NativeLong(TIOCSWINSZ), sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int isatty(int fd) {
|
|
||||||
return C_LIBRARY.isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String ttyname(int fd) {
|
|
||||||
byte[] buf = new byte[64];
|
|
||||||
C_LIBRARY.ttyname_r(fd, buf, buf.length);
|
|
||||||
int len = 0;
|
|
||||||
while (buf[len] != 0) {
|
|
||||||
len++;
|
|
||||||
}
|
|
||||||
return new String(buf, 0, len);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,211 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jni.h"
|
|
||||||
#include "jni_util.h"
|
|
||||||
#include "jvm.h"
|
|
||||||
#include "jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl.h"
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
|
|
||||||
static jclass lastErrorExceptionClass;
|
|
||||||
static jmethodID lastErrorExceptionConstructor;
|
|
||||||
|
|
||||||
static jclass termios_j;
|
|
||||||
static jfieldID c_iflag;
|
|
||||||
static jfieldID c_oflag;
|
|
||||||
static jfieldID c_cflag;
|
|
||||||
static jfieldID c_lflag;
|
|
||||||
static jfieldID c_cc;
|
|
||||||
static jfieldID c_ispeed;
|
|
||||||
static jfieldID c_ospeed;
|
|
||||||
|
|
||||||
static jclass winsize_j;
|
|
||||||
static jfieldID ws_row;
|
|
||||||
static jfieldID ws_col;
|
|
||||||
static jfieldID ws_xpixel;
|
|
||||||
static jfieldID ws_ypixel;
|
|
||||||
|
|
||||||
static jclass nativelong_j;
|
|
||||||
static jfieldID nativelong_value;
|
|
||||||
|
|
||||||
static void throw_errno(JNIEnv *env);
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_initIDs
|
|
||||||
(JNIEnv *env, jclass) {
|
|
||||||
jclass cls;
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/LastErrorException");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
lastErrorExceptionClass = (jclass) env->NewGlobalRef(cls);
|
|
||||||
lastErrorExceptionConstructor = env->GetMethodID(lastErrorExceptionClass, "<init>", "(J)V");
|
|
||||||
CHECK_NULL(lastErrorExceptionConstructor);
|
|
||||||
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$termios");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
termios_j = (jclass) env->NewGlobalRef(cls);
|
|
||||||
CHECK_NULL(termios_j);
|
|
||||||
c_iflag = env->GetFieldID(termios_j, "c_iflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_iflag);
|
|
||||||
c_oflag = env->GetFieldID(termios_j, "c_oflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_oflag);
|
|
||||||
c_cflag = env->GetFieldID(termios_j, "c_cflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_cflag);
|
|
||||||
c_lflag = env->GetFieldID(termios_j, "c_lflag", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_lflag);
|
|
||||||
c_cc = env->GetFieldID(termios_j, "c_cc", "[B");
|
|
||||||
CHECK_NULL(c_cc);
|
|
||||||
c_ispeed = env->GetFieldID(termios_j, "c_ispeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_ispeed);
|
|
||||||
c_ospeed = env->GetFieldID(termios_j, "c_ospeed", "Ljdk/internal/org/jline/terminal/impl/jna/osx/NativeLong;");
|
|
||||||
CHECK_NULL(c_ospeed);
|
|
||||||
|
|
||||||
cls = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/CLibrary$winsize");
|
|
||||||
CHECK_NULL(cls);
|
|
||||||
winsize_j = (jclass) env->NewGlobalRef(cls);
|
|
||||||
ws_row = env->GetFieldID(winsize_j, "ws_row", "S");
|
|
||||||
CHECK_NULL(ws_row);
|
|
||||||
ws_col = env->GetFieldID(winsize_j, "ws_col", "S");
|
|
||||||
CHECK_NULL(ws_col);
|
|
||||||
ws_xpixel= env->GetFieldID(winsize_j, "ws_xpixel", "S");
|
|
||||||
CHECK_NULL(ws_xpixel);
|
|
||||||
ws_ypixel= env->GetFieldID(winsize_j, "ws_ypixel", "S");
|
|
||||||
CHECK_NULL(ws_ypixel);
|
|
||||||
|
|
||||||
nativelong_j = env->FindClass("jdk/internal/org/jline/terminal/impl/jna/osx/NativeLong");
|
|
||||||
CHECK_NULL(nativelong_j);
|
|
||||||
nativelong_value = env->GetFieldID(nativelong_j, "value", "J");
|
|
||||||
CHECK_NULL(nativelong_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcgetattr
|
|
||||||
(JNIEnv *env, jobject, jint fd, jobject result) {
|
|
||||||
termios data;
|
|
||||||
|
|
||||||
if (tcgetattr(fd, &data) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_iflag), nativelong_value, data.c_iflag);
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_oflag), nativelong_value, data.c_oflag);
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_cflag), nativelong_value, data.c_cflag);
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_lflag), nativelong_value, data.c_lflag);
|
|
||||||
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(result, c_cc);
|
|
||||||
env->SetByteArrayRegion(c_ccValue, 0, NCCS, (signed char *) data.c_cc);
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_ispeed), nativelong_value, data.c_ispeed);
|
|
||||||
env->SetLongField(env->GetObjectField(result, c_ospeed), nativelong_value, data.c_ospeed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
|
|
||||||
* Method: tcsetattr
|
|
||||||
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/termios;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_tcsetattr
|
|
||||||
(JNIEnv *env, jobject, jint fd, jint cmd, jobject input) {
|
|
||||||
termios data;
|
|
||||||
|
|
||||||
data.c_iflag = env->GetLongField(env->GetObjectField(input, c_iflag), nativelong_value);
|
|
||||||
data.c_oflag = env->GetLongField(env->GetObjectField(input, c_oflag), nativelong_value);
|
|
||||||
data.c_cflag = env->GetLongField(env->GetObjectField(input, c_cflag), nativelong_value);
|
|
||||||
data.c_lflag = env->GetLongField(env->GetObjectField(input, c_lflag), nativelong_value);
|
|
||||||
jbyteArray c_ccValue = (jbyteArray) env->GetObjectField(input, c_cc);
|
|
||||||
env->GetByteArrayRegion(c_ccValue, 0, NCCS, (jbyte *) data.c_cc);
|
|
||||||
data.c_ispeed = env->GetLongField(env->GetObjectField(input, c_ispeed), nativelong_value);
|
|
||||||
data.c_ospeed = env->GetLongField(env->GetObjectField(input, c_ospeed), nativelong_value);
|
|
||||||
|
|
||||||
if (tcsetattr(fd, cmd, &data) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
|
|
||||||
* Method: ioctl0
|
|
||||||
* Signature: (IILjdk/internal/org/jline/terminal/impl/jna/osx/CLibrary/winsize;)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ioctl0
|
|
||||||
(JNIEnv *env, jobject, jint fd, jlong cmd, jobject data) {
|
|
||||||
winsize ws;
|
|
||||||
|
|
||||||
ws.ws_row = env->GetShortField(data, ws_row);
|
|
||||||
ws.ws_col = env->GetShortField(data, ws_col);
|
|
||||||
ws.ws_xpixel = env->GetShortField(data, ws_xpixel);
|
|
||||||
ws.ws_ypixel = env->GetShortField(data, ws_ypixel);
|
|
||||||
|
|
||||||
if (ioctl(fd, cmd, &ws) != 0) {
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetShortField(data, ws_row, ws.ws_row);
|
|
||||||
env->SetShortField(data, ws_col, ws.ws_col);
|
|
||||||
env->SetShortField(data, ws_xpixel, ws.ws_xpixel);
|
|
||||||
env->SetShortField(data, ws_ypixel, ws.ws_ypixel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
|
|
||||||
* Method: isatty
|
|
||||||
* Signature: (I)I
|
|
||||||
*/
|
|
||||||
JNIEXPORT jint JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_isatty
|
|
||||||
(JNIEnv *, jobject, jint fd) {
|
|
||||||
return isatty(fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Class: jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl
|
|
||||||
* Method: ttyname_r
|
|
||||||
* Signature: (I[BI)V
|
|
||||||
*/
|
|
||||||
JNIEXPORT void JNICALL Java_jdk_internal_org_jline_terminal_impl_jna_osx_CLibraryImpl_ttyname_1r
|
|
||||||
(JNIEnv *env, jobject, jint fd, jbyteArray buf, jint len) {
|
|
||||||
char *data = new char[len];
|
|
||||||
int error = ttyname_r(fd, data, len);
|
|
||||||
|
|
||||||
if (error != 0) {
|
|
||||||
delete[] data;
|
|
||||||
throw_errno(env);
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
|
|
||||||
env->SetByteArrayRegion(buf, 0, len, (jbyte *) data);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Throws LastErrorException based on the errno:
|
|
||||||
*/
|
|
||||||
static void throw_errno(JNIEnv *env) {
|
|
||||||
jobject exc = env->NewObject(lastErrorExceptionClass,
|
|
||||||
lastErrorExceptionConstructor,
|
|
||||||
errno);
|
|
||||||
env->Throw((jthrowable) exc);
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -66,7 +66,7 @@ public class BindingReader {
|
|||||||
T o = null;
|
T o = null;
|
||||||
int[] remaining = new int[1];
|
int[] remaining = new int[1];
|
||||||
boolean hasRead = false;
|
boolean hasRead = false;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (local != null) {
|
if (local != null) {
|
||||||
o = local.getBound(opBuffer, remaining);
|
o = local.getBound(opBuffer, remaining);
|
||||||
}
|
}
|
||||||
@ -78,8 +78,7 @@ public class BindingReader {
|
|||||||
if (remaining[0] >= 0) {
|
if (remaining[0] >= 0) {
|
||||||
runMacro(opBuffer.substring(opBuffer.length() - remaining[0]));
|
runMacro(opBuffer.substring(opBuffer.length() - remaining[0]));
|
||||||
opBuffer.setLength(opBuffer.length() - remaining[0]);
|
opBuffer.setLength(opBuffer.length() - remaining[0]);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
long ambiguousTimeout = keys.getAmbiguousTimeout();
|
long ambiguousTimeout = keys.getAmbiguousTimeout();
|
||||||
if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) {
|
if (ambiguousTimeout > 0 && peekCharacter(ambiguousTimeout) != NonBlockingReader.READ_EXPIRED) {
|
||||||
o = null;
|
o = null;
|
||||||
@ -234,5 +233,4 @@ public class BindingReader {
|
|||||||
public String getLastBinding() {
|
public String getLastBinding() {
|
||||||
return lastBinding;
|
return lastBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,8 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.keymap;
|
package jdk.internal.org.jline.keymap;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
@ -218,7 +216,6 @@ public class KeyMap<T> {
|
|||||||
return seqs;
|
return seqs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static String esc() {
|
public static String esc() {
|
||||||
return "\033";
|
return "\033";
|
||||||
}
|
}
|
||||||
@ -264,7 +261,6 @@ public class KeyMap<T> {
|
|||||||
// Methods
|
// Methods
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
public T getUnicode() {
|
public T getUnicode() {
|
||||||
return unicode;
|
return unicode;
|
||||||
}
|
}
|
||||||
@ -306,9 +302,7 @@ public class KeyMap<T> {
|
|||||||
}
|
}
|
||||||
for (int c = 0; c < keyMap.mapping.length; c++) {
|
for (int c = 0; c < keyMap.mapping.length; c++) {
|
||||||
if (keyMap.mapping[c] instanceof KeyMap) {
|
if (keyMap.mapping[c] instanceof KeyMap) {
|
||||||
doGetBoundKeys((KeyMap<T>) keyMap.mapping[c],
|
doGetBoundKeys((KeyMap<T>) keyMap.mapping[c], prefix + (char) (c), bound);
|
||||||
prefix + (char) (c),
|
|
||||||
bound);
|
|
||||||
} else if (keyMap.mapping[c] != null) {
|
} else if (keyMap.mapping[c] != null) {
|
||||||
bound.put(prefix + (char) (c), (T) keyMap.mapping[c]);
|
bound.put(prefix + (char) (c), (T) keyMap.mapping[c]);
|
||||||
}
|
}
|
||||||
@ -456,5 +450,4 @@ public class KeyMap<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -14,9 +14,8 @@ package jdk.internal.org.jline.reader;
|
|||||||
* @see Macro
|
* @see Macro
|
||||||
* @see Reference
|
* @see Reference
|
||||||
* @see Widget
|
* @see Widget
|
||||||
* @see jdk.internal.org.jline.keymap.KeyMap
|
* @see org.jline.keymap.KeyMap
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
|
* @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
|
||||||
*/
|
*/
|
||||||
public interface Binding {
|
public interface Binding {}
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2017, the original author or authors.
|
* Copyright (c) 2002-2017, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -84,8 +84,8 @@ public interface Buffer {
|
|||||||
|
|
||||||
void copyFrom(Buffer buffer);
|
void copyFrom(Buffer buffer);
|
||||||
|
|
||||||
// JDK specific modification
|
/**
|
||||||
default void zeroOut() {
|
* Clear any internal buffer.
|
||||||
throw new UnsupportedOperationException();
|
*/
|
||||||
}
|
void zeroOut();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2019, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -47,7 +47,15 @@ public class Candidate implements Comparable<Candidate> {
|
|||||||
* @param complete the complete flag
|
* @param complete the complete flag
|
||||||
* @param sort the sort flag
|
* @param sort the sort flag
|
||||||
*/
|
*/
|
||||||
public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete, int sort) {
|
public Candidate(
|
||||||
|
String value,
|
||||||
|
String displ,
|
||||||
|
String group,
|
||||||
|
String descr,
|
||||||
|
String suffix,
|
||||||
|
String key,
|
||||||
|
boolean complete,
|
||||||
|
int sort) {
|
||||||
this.value = Objects.requireNonNull(value);
|
this.value = Objects.requireNonNull(value);
|
||||||
this.displ = Objects.requireNonNull(displ);
|
this.displ = Objects.requireNonNull(displ);
|
||||||
this.group = group;
|
this.group = group;
|
||||||
@ -69,7 +77,8 @@ public class Candidate implements Comparable<Candidate> {
|
|||||||
* @param key the key
|
* @param key the key
|
||||||
* @param complete the complete flag
|
* @param complete the complete flag
|
||||||
*/
|
*/
|
||||||
public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
|
public Candidate(
|
||||||
|
String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
|
||||||
this(value, displ, group, descr, suffix, key, complete, 0);
|
this(value, displ, group, descr, suffix, key, complete, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,11 +168,10 @@ public class Candidate implements Comparable<Candidate> {
|
|||||||
return sort;
|
return sort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compareTo(Candidate o) {
|
public int compareTo(Candidate o) {
|
||||||
// If both candidates have same sort, use default behavior
|
// If both candidates have same sort, use default behavior
|
||||||
if( sort == o.sort() ) {
|
if (sort == o.sort()) {
|
||||||
return value.compareTo(o.value);
|
return value.compareTo(o.value);
|
||||||
} else {
|
} else {
|
||||||
return Integer.compare(sort, o.sort());
|
return Integer.compare(sort, o.sort());
|
||||||
@ -180,7 +188,7 @@ public class Candidate implements Comparable<Candidate> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(value);
|
return Objects.hashCode(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -18,8 +18,7 @@ import java.util.List;
|
|||||||
* @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
|
* @author <a href="mailto:gnodet@gmail.com">Guillaume Nodet</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public interface Completer
|
public interface Completer {
|
||||||
{
|
|
||||||
/**
|
/**
|
||||||
* Populates <i>candidates</i> with a list of possible completions for the <i>command line</i>.
|
* Populates <i>candidates</i> with a list of possible completions for the <i>command line</i>.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -10,7 +10,7 @@ package jdk.internal.org.jline.reader;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules
|
* An extension of {@link ParsedLine} that, being aware of the quoting and escaping rules
|
||||||
* of the {@link jdk.internal.org.jline.reader.Parser} that produced it, knows if and how a completion candidate
|
* of the {@link org.jline.reader.Parser} that produced it, knows if and how a completion candidate
|
||||||
* should be escaped/quoted.
|
* should be escaped/quoted.
|
||||||
*
|
*
|
||||||
* @author Eric Bottard
|
* @author Eric Bottard
|
||||||
@ -22,5 +22,4 @@ public interface CompletingParsedLine extends ParsedLine {
|
|||||||
int rawWordCursor();
|
int rawWordCursor();
|
||||||
|
|
||||||
int rawWordLength();
|
int rawWordLength();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -23,8 +23,13 @@ public interface CompletionMatcher {
|
|||||||
* @param errors number of errors accepted in matching
|
* @param errors number of errors accepted in matching
|
||||||
* @param originalGroupName value of JLineReader variable original-group-name
|
* @param originalGroupName value of JLineReader variable original-group-name
|
||||||
*/
|
*/
|
||||||
void compile(Map<LineReader.Option, Boolean> options, boolean prefix, CompletingParsedLine line
|
void compile(
|
||||||
, boolean caseInsensitive, int errors, String originalGroupName);
|
Map<LineReader.Option, Boolean> options,
|
||||||
|
boolean prefix,
|
||||||
|
CompletingParsedLine line,
|
||||||
|
boolean caseInsensitive,
|
||||||
|
int errors,
|
||||||
|
String originalGroupName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -44,5 +49,4 @@ public interface CompletionMatcher {
|
|||||||
* @return a common prefix of matched candidates
|
* @return a common prefix of matched candidates
|
||||||
*/
|
*/
|
||||||
String getCommonPrefix();
|
String getCommonPrefix();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
* Copyright (c) 2023, the original author(s).
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing,
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.reader;
|
package jdk.internal.org.jline.reader;
|
||||||
|
|
||||||
@ -45,7 +35,7 @@ public class EOFError extends SyntaxError {
|
|||||||
return missing;
|
return missing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOpenBrackets(){
|
public int getOpenBrackets() {
|
||||||
return openBrackets;
|
return openBrackets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2019, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -13,6 +13,8 @@ import java.util.List;
|
|||||||
|
|
||||||
public interface Editor {
|
public interface Editor {
|
||||||
public void open(List<String> files) throws IOException;
|
public void open(List<String> files) throws IOException;
|
||||||
|
|
||||||
public void run() throws IOException;
|
public void run() throws IOException;
|
||||||
|
|
||||||
public void setRestricted(boolean restricted);
|
public void setRestricted(boolean restricted);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -17,8 +17,7 @@ public class EndOfFileException extends RuntimeException {
|
|||||||
private static final long serialVersionUID = 528485360925144689L;
|
private static final long serialVersionUID = 528485360925144689L;
|
||||||
private String partialLine;
|
private String partialLine;
|
||||||
|
|
||||||
public EndOfFileException() {
|
public EndOfFileException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public EndOfFileException(String message) {
|
public EndOfFileException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -13,5 +13,4 @@ public interface Expander {
|
|||||||
String expandHistory(History history, String line);
|
String expandHistory(History history, String line);
|
||||||
|
|
||||||
String expandVar(String word);
|
String expandVar(String word);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -21,8 +21,7 @@ import java.util.ListIterator;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public interface History extends Iterable<History.Entry>
|
public interface History extends Iterable<History.Entry> {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the history for the given reader.
|
* Initialize the history for the given reader.
|
||||||
@ -75,7 +74,6 @@ public interface History extends Iterable<History.Entry>
|
|||||||
*/
|
*/
|
||||||
void purge() throws IOException;
|
void purge() throws IOException;
|
||||||
|
|
||||||
|
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
default boolean isEmpty() {
|
default boolean isEmpty() {
|
||||||
@ -110,8 +108,7 @@ public interface History extends Iterable<History.Entry>
|
|||||||
// Entries
|
// Entries
|
||||||
//
|
//
|
||||||
|
|
||||||
interface Entry
|
interface Entry {
|
||||||
{
|
|
||||||
int index();
|
int index();
|
||||||
|
|
||||||
Instant time();
|
Instant time();
|
||||||
@ -132,14 +129,17 @@ public interface History extends Iterable<History.Entry>
|
|||||||
default Iterator<Entry> reverseIterator(int index) {
|
default Iterator<Entry> reverseIterator(int index) {
|
||||||
return new Iterator<Entry>() {
|
return new Iterator<Entry>() {
|
||||||
private final ListIterator<Entry> it = iterator(index + 1);
|
private final ListIterator<Entry> it = iterator(index + 1);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return it.hasPrevious();
|
return it.hasPrevious();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Entry next() {
|
public Entry next() {
|
||||||
return it.previous();
|
return it.previous();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void remove() {
|
public void remove() {
|
||||||
it.remove();
|
it.remove();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2023, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -21,7 +21,7 @@ import jdk.internal.org.jline.utils.AttributedString;
|
|||||||
|
|
||||||
/** Read lines from the console, with input editing.
|
/** Read lines from the console, with input editing.
|
||||||
*
|
*
|
||||||
* <h3>Thread safety</h3>
|
* <h2>Thread safety</h2>
|
||||||
* The <code>LineReader</code> implementations are not thread safe,
|
* The <code>LineReader</code> implementations are not thread safe,
|
||||||
* thus you should not attempt to use a single reader in several threads.
|
* thus you should not attempt to use a single reader in several threads.
|
||||||
* Any attempt to call one of the <code>readLine</code> call while one is
|
* Any attempt to call one of the <code>readLine</code> call while one is
|
||||||
@ -31,7 +31,7 @@ import jdk.internal.org.jline.utils.AttributedString;
|
|||||||
* {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at
|
* {@link #printAbove(String)} or {@link #printAbove(AttributedString)} at
|
||||||
* any time to allow text to be printed above the current prompt.
|
* any time to allow text to be printed above the current prompt.
|
||||||
*
|
*
|
||||||
* <h3>Prompt strings</h3>
|
* <h2>Prompt strings</h2>
|
||||||
* It is traditional for an interactive console-based program
|
* It is traditional for an interactive console-based program
|
||||||
* to print a short prompt string to signal that the user is expected
|
* to print a short prompt string to signal that the user is expected
|
||||||
* to type a command. JLine supports 3 kinds of prompt string:
|
* to type a command. JLine supports 3 kinds of prompt string:
|
||||||
@ -81,7 +81,6 @@ import jdk.internal.org.jline.utils.AttributedString;
|
|||||||
* </dd>
|
* </dd>
|
||||||
* </dl>
|
* </dl>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public interface LineReader {
|
public interface LineReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -284,6 +283,7 @@ public interface LineReader {
|
|||||||
String MAIN = "main";
|
String MAIN = "main";
|
||||||
String EMACS = "emacs";
|
String EMACS = "emacs";
|
||||||
String SAFE = ".safe";
|
String SAFE = ".safe";
|
||||||
|
String DUMB = "dumb";
|
||||||
String MENU = "menu";
|
String MENU = "menu";
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -301,6 +301,7 @@ public interface LineReader {
|
|||||||
* they are displayed in a list below the field to be completed
|
* they are displayed in a list below the field to be completed
|
||||||
*/
|
*/
|
||||||
String MENU_LIST_MAX = "menu-list-max";
|
String MENU_LIST_MAX = "menu-list-max";
|
||||||
|
|
||||||
String DISABLE_HISTORY = "disable-history";
|
String DISABLE_HISTORY = "disable-history";
|
||||||
String DISABLE_COMPLETION = "disable-completion";
|
String DISABLE_COMPLETION = "disable-completion";
|
||||||
String EDITING_MODE = "editing-mode";
|
String EDITING_MODE = "editing-mode";
|
||||||
@ -317,18 +318,23 @@ public interface LineReader {
|
|||||||
String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME";
|
String ORIGINAL_GROUP_NAME = "ORIGINAL_GROUP_NAME";
|
||||||
/** Completion style for displaying groups name */
|
/** Completion style for displaying groups name */
|
||||||
String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP";
|
String COMPLETION_STYLE_GROUP = "COMPLETION_STYLE_GROUP";
|
||||||
|
|
||||||
String COMPLETION_STYLE_LIST_GROUP = "COMPLETION_STYLE_LIST_GROUP";
|
String COMPLETION_STYLE_LIST_GROUP = "COMPLETION_STYLE_LIST_GROUP";
|
||||||
/** Completion style for displaying the current selected item */
|
/** Completion style for displaying the current selected item */
|
||||||
String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION";
|
String COMPLETION_STYLE_SELECTION = "COMPLETION_STYLE_SELECTION";
|
||||||
|
|
||||||
String COMPLETION_STYLE_LIST_SELECTION = "COMPLETION_STYLE_LIST_SELECTION";
|
String COMPLETION_STYLE_LIST_SELECTION = "COMPLETION_STYLE_LIST_SELECTION";
|
||||||
/** Completion style for displaying the candidate description */
|
/** Completion style for displaying the candidate description */
|
||||||
String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION";
|
String COMPLETION_STYLE_DESCRIPTION = "COMPLETION_STYLE_DESCRIPTION";
|
||||||
|
|
||||||
String COMPLETION_STYLE_LIST_DESCRIPTION = "COMPLETION_STYLE_LIST_DESCRIPTION";
|
String COMPLETION_STYLE_LIST_DESCRIPTION = "COMPLETION_STYLE_LIST_DESCRIPTION";
|
||||||
/** Completion style for displaying the matching part of candidates */
|
/** Completion style for displaying the matching part of candidates */
|
||||||
String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING";
|
String COMPLETION_STYLE_STARTING = "COMPLETION_STYLE_STARTING";
|
||||||
|
|
||||||
String COMPLETION_STYLE_LIST_STARTING = "COMPLETION_STYLE_LIST_STARTING";
|
String COMPLETION_STYLE_LIST_STARTING = "COMPLETION_STYLE_LIST_STARTING";
|
||||||
/** Completion style for displaying the list */
|
/** Completion style for displaying the list */
|
||||||
String COMPLETION_STYLE_BACKGROUND = "COMPLETION_STYLE_BACKGROUND";
|
String COMPLETION_STYLE_BACKGROUND = "COMPLETION_STYLE_BACKGROUND";
|
||||||
|
|
||||||
String COMPLETION_STYLE_LIST_BACKGROUND = "COMPLETION_STYLE_LIST_BACKGROUND";
|
String COMPLETION_STYLE_LIST_BACKGROUND = "COMPLETION_STYLE_LIST_BACKGROUND";
|
||||||
/**
|
/**
|
||||||
* Set the template for prompts for secondary (continuation) lines.
|
* Set the template for prompts for secondary (continuation) lines.
|
||||||
@ -390,6 +396,26 @@ public interface LineReader {
|
|||||||
*/
|
*/
|
||||||
String SUGGESTIONS_MIN_BUFFER_SIZE = "suggestions-min-buffer-size";
|
String SUGGESTIONS_MIN_BUFFER_SIZE = "suggestions-min-buffer-size";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max number of times a command can be repeated.
|
||||||
|
*/
|
||||||
|
String MAX_REPEAT_COUNT = "max-repeat-count";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of spaces to display a tabulation, the default is 4.
|
||||||
|
*/
|
||||||
|
String TAB_WIDTH = "tab-width";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of inputrc to read at line reader creation time.
|
||||||
|
*/
|
||||||
|
String INPUT_RC_FILE_NAME = "input-rc-file-name";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefix to automatically delegate variables to system properties
|
||||||
|
*/
|
||||||
|
String SYSTEM_PROPERTY_PREFIX = "system-property-prefix";
|
||||||
|
|
||||||
Map<String, KeyMap<Binding>> defaultKeyMaps();
|
Map<String, KeyMap<Binding>> defaultKeyMaps();
|
||||||
|
|
||||||
enum Option {
|
enum Option {
|
||||||
@ -469,8 +495,7 @@ public interface LineReader {
|
|||||||
EMPTY_WORD_OPTIONS(true),
|
EMPTY_WORD_OPTIONS(true),
|
||||||
|
|
||||||
/** Disable the undo feature */
|
/** Disable the undo feature */
|
||||||
DISABLE_UNDO
|
DISABLE_UNDO;
|
||||||
;
|
|
||||||
|
|
||||||
private final boolean def;
|
private final boolean def;
|
||||||
|
|
||||||
@ -611,7 +636,8 @@ public interface LineReader {
|
|||||||
* @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
|
* @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
|
||||||
* @throws java.io.IOError in case of other i/o errors
|
* @throws java.io.IOError in case of other i/o errors
|
||||||
*/
|
*/
|
||||||
String readLine(String prompt, String rightPrompt, Character mask, String buffer) throws UserInterruptException, EndOfFileException;
|
String readLine(String prompt, String rightPrompt, Character mask, String buffer)
|
||||||
|
throws UserInterruptException, EndOfFileException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a line from the <i>in</i> {@link InputStream}, and return the line
|
* Read a line from the <i>in</i> {@link InputStream}, and return the line
|
||||||
@ -631,7 +657,8 @@ public interface LineReader {
|
|||||||
* @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
|
* @throws EndOfFileException if an EOF has been found (using Ctrl-D for example)
|
||||||
* @throws java.io.IOError in case of other i/o errors
|
* @throws java.io.IOError in case of other i/o errors
|
||||||
*/
|
*/
|
||||||
String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException;
|
String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer)
|
||||||
|
throws UserInterruptException, EndOfFileException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints a line above the prompt and redraw everything.
|
* Prints a line above the prompt and redraw everything.
|
||||||
@ -702,7 +729,7 @@ public interface LineReader {
|
|||||||
void runMacro(String macro);
|
void runMacro(String macro);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a mouse event when the {@link jdk.internal.org.jline.utils.InfoCmp.Capability#key_mouse} sequence
|
* Read a mouse event when the {@link org.jline.utils.InfoCmp.Capability#key_mouse} sequence
|
||||||
* has just been read on the input stream.
|
* has just been read on the input stream.
|
||||||
* Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys
|
* Compared to {@link Terminal#readMouseEvent()}, this method takes into account keys
|
||||||
* that have been pushed back using {@link #runMacro(String)}.
|
* that have been pushed back using {@link #runMacro(String)}.
|
||||||
@ -751,8 +778,8 @@ public interface LineReader {
|
|||||||
|
|
||||||
SuggestionType getAutosuggestion();
|
SuggestionType getAutosuggestion();
|
||||||
|
|
||||||
// JDK specific modification
|
/**
|
||||||
default void zeroOut() {
|
* Clear any internal buffers.
|
||||||
throw new UnsupportedOperationException();
|
*/
|
||||||
}
|
void zeroOut();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -38,8 +38,7 @@ public final class LineReaderBuilder {
|
|||||||
Expander expander;
|
Expander expander;
|
||||||
CompletionMatcher completionMatcher;
|
CompletionMatcher completionMatcher;
|
||||||
|
|
||||||
private LineReaderBuilder() {
|
private LineReaderBuilder() {}
|
||||||
}
|
|
||||||
|
|
||||||
public LineReaderBuilder terminal(Terminal terminal) {
|
public LineReaderBuilder terminal(Terminal terminal) {
|
||||||
this.terminal = terminal;
|
this.terminal = terminal;
|
||||||
@ -88,8 +87,9 @@ public final class LineReaderBuilder {
|
|||||||
try {
|
try {
|
||||||
if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE)
|
if (!Boolean.getBoolean(LineReader.PROP_SUPPORT_PARSEDLINE)
|
||||||
&& !(parser.parse("", 0) instanceof CompletingParsedLine)) {
|
&& !(parser.parse("", 0) instanceof CompletingParsedLine)) {
|
||||||
Log.warn("The Parser of class " + parser.getClass().getName() + " does not support the CompletingParsedLine interface. " +
|
Log.warn("The Parser of class " + parser.getClass().getName()
|
||||||
"Completion with escaped or quoted words won't work correctly.");
|
+ " does not support the CompletingParsedLine interface. "
|
||||||
|
+ "Completion with escaped or quoted words won't work correctly.");
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
// Ignore
|
// Ignore
|
||||||
@ -153,5 +153,4 @@ public final class LineReaderBuilder {
|
|||||||
}
|
}
|
||||||
return reader;
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -35,7 +35,6 @@ public class Macro implements Binding {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Macro[" +
|
return "Macro[" + sequence + ']';
|
||||||
sequence + ']';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -31,5 +31,4 @@ public interface MaskingCallback {
|
|||||||
* @return the modified line
|
* @return the modified line
|
||||||
*/
|
*/
|
||||||
String history(String line);
|
String history(String line);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -64,5 +64,4 @@ public interface ParsedLine {
|
|||||||
* @return the cursor position within the line
|
* @return the cursor position within the line
|
||||||
*/
|
*/
|
||||||
int cursor();
|
int cursor();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -38,7 +38,6 @@ public class Reference implements Binding {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Reference[" +
|
return "Reference[" + name + ']';
|
||||||
name + ']';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one
|
* Copyright (c) 2023, the original author(s).
|
||||||
* or more contributor license agreements. See the NOTICE file
|
|
||||||
* distributed with this work for additional information
|
|
||||||
* regarding copyright ownership. The ASF licenses this file
|
|
||||||
* to you under the Apache License, Version 2.0 (the
|
|
||||||
* "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing,
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.reader;
|
package jdk.internal.org.jline.reader;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -14,23 +14,19 @@ package jdk.internal.org.jline.reader;
|
|||||||
* interrupt character (ctrl-C). The partially entered line is
|
* interrupt character (ctrl-C). The partially entered line is
|
||||||
* available via the {@link #getPartialLine()} method.
|
* available via the {@link #getPartialLine()} method.
|
||||||
*/
|
*/
|
||||||
public class UserInterruptException
|
public class UserInterruptException extends RuntimeException {
|
||||||
extends RuntimeException
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 6172232572140736750L;
|
private static final long serialVersionUID = 6172232572140736750L;
|
||||||
|
|
||||||
private final String partialLine;
|
private final String partialLine;
|
||||||
|
|
||||||
public UserInterruptException(String partialLine)
|
public UserInterruptException(String partialLine) {
|
||||||
{
|
|
||||||
this.partialLine = partialLine;
|
this.partialLine = partialLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the partially entered line when ctrl-C was pressed
|
* @return the partially entered line when ctrl-C was pressed
|
||||||
*/
|
*/
|
||||||
public String getPartialLine()
|
public String getPartialLine() {
|
||||||
{
|
|
||||||
return partialLine;
|
return partialLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -15,5 +15,4 @@ package jdk.internal.org.jline.reader;
|
|||||||
public interface Widget extends Binding {
|
public interface Widget extends Binding {
|
||||||
|
|
||||||
boolean apply();
|
boolean apply();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2017, the original author or authors.
|
* Copyright (c) 2002-2017, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -20,8 +20,7 @@ import jdk.internal.org.jline.reader.Buffer;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public class BufferImpl implements Buffer
|
public class BufferImpl implements Buffer {
|
||||||
{
|
|
||||||
private int cursor = 0;
|
private int cursor = 0;
|
||||||
private int cursorCol = -1;
|
private int cursorCol = -1;
|
||||||
private int[] buffer;
|
private int[] buffer;
|
||||||
@ -46,7 +45,7 @@ public class BufferImpl implements Buffer
|
|||||||
this.g1 = buffer.g1;
|
this.g1 = buffer.g1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferImpl copy () {
|
public BufferImpl copy() {
|
||||||
return new BufferImpl(this);
|
return new BufferImpl(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +106,7 @@ public class BufferImpl implements Buffer
|
|||||||
* @param c the character to insert
|
* @param c the character to insert
|
||||||
*/
|
*/
|
||||||
public void write(int c) {
|
public void write(int c) {
|
||||||
write(new int[] { c });
|
write(new int[] {c});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,7 +120,7 @@ public class BufferImpl implements Buffer
|
|||||||
if (overTyping) {
|
if (overTyping) {
|
||||||
delete(1);
|
delete(1);
|
||||||
}
|
}
|
||||||
write(new int[] { c });
|
write(new int[] {c});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -224,8 +223,7 @@ public class BufferImpl implements Buffer
|
|||||||
|
|
||||||
if ((cursor + where) < 0) {
|
if ((cursor + where) < 0) {
|
||||||
where = -cursor;
|
where = -cursor;
|
||||||
}
|
} else if ((cursor + where) > length()) {
|
||||||
else if ((cursor + where) > length()) {
|
|
||||||
where = length() - cursor;
|
where = length() - cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +369,6 @@ public class BufferImpl implements Buffer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JDK specific modification
|
|
||||||
@Override
|
@Override
|
||||||
public void zeroOut() {
|
public void zeroOut() {
|
||||||
Arrays.fill(buffer, 0);
|
Arrays.fill(buffer, 0);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,26 +8,25 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.reader.impl;
|
package jdk.internal.org.jline.reader.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.reader.Candidate;
|
|
||||||
import jdk.internal.org.jline.reader.CompletingParsedLine;
|
|
||||||
import jdk.internal.org.jline.reader.CompletionMatcher;
|
|
||||||
import jdk.internal.org.jline.reader.LineReader;
|
|
||||||
import jdk.internal.org.jline.utils.AttributedString;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.reader.Candidate;
|
||||||
|
import jdk.internal.org.jline.reader.CompletingParsedLine;
|
||||||
|
import jdk.internal.org.jline.reader.CompletionMatcher;
|
||||||
|
import jdk.internal.org.jline.reader.LineReader;
|
||||||
|
import jdk.internal.org.jline.utils.AttributedString;
|
||||||
|
|
||||||
public class CompletionMatcherImpl implements CompletionMatcher {
|
public class CompletionMatcherImpl implements CompletionMatcher {
|
||||||
protected Predicate<String> exact;
|
protected Predicate<String> exact;
|
||||||
protected List<Function<Map<String, List<Candidate>>, Map<String, List<Candidate>>>> matchers;
|
protected List<Function<Map<String, List<Candidate>>, Map<String, List<Candidate>>>> matchers;
|
||||||
private Map<String, List<Candidate>> matching;
|
private Map<String, List<Candidate>> matching;
|
||||||
private boolean caseInsensitive;
|
private boolean caseInsensitive;
|
||||||
|
|
||||||
public CompletionMatcherImpl() {
|
public CompletionMatcherImpl() {}
|
||||||
}
|
|
||||||
|
|
||||||
protected void reset(boolean caseInsensitive) {
|
protected void reset(boolean caseInsensitive) {
|
||||||
this.caseInsensitive = caseInsensitive;
|
this.caseInsensitive = caseInsensitive;
|
||||||
@ -37,8 +36,13 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void compile(Map<LineReader.Option, Boolean> options, boolean prefix, CompletingParsedLine line
|
public void compile(
|
||||||
, boolean caseInsensitive, int errors, String originalGroupName) {
|
Map<LineReader.Option, Boolean> options,
|
||||||
|
boolean prefix,
|
||||||
|
CompletingParsedLine line,
|
||||||
|
boolean caseInsensitive,
|
||||||
|
int errors,
|
||||||
|
String originalGroupName) {
|
||||||
reset(caseInsensitive);
|
reset(caseInsensitive);
|
||||||
defaultMatchers(options, prefix, line, caseInsensitive, errors, originalGroupName);
|
defaultMatchers(options, prefix, line, caseInsensitive, errors, originalGroupName);
|
||||||
}
|
}
|
||||||
@ -47,14 +51,17 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
public List<Candidate> matches(List<Candidate> candidates) {
|
public List<Candidate> matches(List<Candidate> candidates) {
|
||||||
matching = Collections.emptyMap();
|
matching = Collections.emptyMap();
|
||||||
Map<String, List<Candidate>> sortedCandidates = sort(candidates);
|
Map<String, List<Candidate>> sortedCandidates = sort(candidates);
|
||||||
for (Function<Map<String, List<Candidate>>,
|
for (Function<Map<String, List<Candidate>>, Map<String, List<Candidate>>> matcher : matchers) {
|
||||||
Map<String, List<Candidate>>> matcher : matchers) {
|
|
||||||
matching = matcher.apply(sortedCandidates);
|
matching = matcher.apply(sortedCandidates);
|
||||||
if (!matching.isEmpty()) {
|
if (!matching.isEmpty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !matching.isEmpty() ? matching.entrySet().stream().flatMap(e -> e.getValue().stream()).distinct().collect(Collectors.toList())
|
return !matching.isEmpty()
|
||||||
|
? matching.entrySet().stream()
|
||||||
|
.flatMap(e -> e.getValue().stream())
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList())
|
||||||
: new ArrayList<>();
|
: new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,10 +70,12 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
if (matching == null) {
|
if (matching == null) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
return matching.values().stream().flatMap(Collection::stream)
|
return matching.values().stream()
|
||||||
|
.flatMap(Collection::stream)
|
||||||
.filter(Candidate::complete)
|
.filter(Candidate::complete)
|
||||||
.filter(c -> exact.test(c.value()))
|
.filter(c -> exact.test(c.value()))
|
||||||
.findFirst().orElse(null);
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -84,8 +93,13 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
/**
|
/**
|
||||||
* Default JLine matchers
|
* Default JLine matchers
|
||||||
*/
|
*/
|
||||||
protected void defaultMatchers(Map<LineReader.Option, Boolean> options, boolean prefix, CompletingParsedLine line
|
protected void defaultMatchers(
|
||||||
, boolean caseInsensitive, int errors, String originalGroupName) {
|
Map<LineReader.Option, Boolean> options,
|
||||||
|
boolean prefix,
|
||||||
|
CompletingParsedLine line,
|
||||||
|
boolean caseInsensitive,
|
||||||
|
int errors,
|
||||||
|
String originalGroupName) {
|
||||||
// Find matchers
|
// Find matchers
|
||||||
// TODO: glob completion
|
// TODO: glob completion
|
||||||
String wd = line.word();
|
String wd = line.word();
|
||||||
@ -94,8 +108,7 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
if (prefix) {
|
if (prefix) {
|
||||||
matchers = new ArrayList<>(Arrays.asList(
|
matchers = new ArrayList<>(Arrays.asList(
|
||||||
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)),
|
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wp)),
|
||||||
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp))
|
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wp))));
|
||||||
));
|
|
||||||
if (LineReader.Option.COMPLETE_MATCHER_TYPO.isSet(options)) {
|
if (LineReader.Option.COMPLETE_MATCHER_TYPO.isSet(options)) {
|
||||||
matchers.add(typoMatcher(wp, errors, caseInsensitive, originalGroupName));
|
matchers.add(typoMatcher(wp, errors, caseInsensitive, originalGroupName));
|
||||||
}
|
}
|
||||||
@ -109,14 +122,14 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
|
Pattern p1 = Pattern.compile(Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
|
||||||
Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
|
Pattern p2 = Pattern.compile(".*" + Pattern.quote(wp) + ".*" + Pattern.quote(ws) + ".*");
|
||||||
matchers = new ArrayList<>(Arrays.asList(
|
matchers = new ArrayList<>(Arrays.asList(
|
||||||
simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s).matches()),
|
simpleMatcher(s -> p1.matcher(caseInsensitive ? s.toLowerCase() : s)
|
||||||
simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s).matches())
|
.matches()),
|
||||||
));
|
simpleMatcher(s -> p2.matcher(caseInsensitive ? s.toLowerCase() : s)
|
||||||
|
.matches())));
|
||||||
} else {
|
} else {
|
||||||
matchers = new ArrayList<>(Arrays.asList(
|
matchers = new ArrayList<>(Arrays.asList(
|
||||||
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)),
|
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).startsWith(wdi)),
|
||||||
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi))
|
simpleMatcher(s -> (caseInsensitive ? s.toLowerCase() : s).contains(wdi))));
|
||||||
));
|
|
||||||
}
|
}
|
||||||
if (LineReader.Option.COMPLETE_MATCHER_CAMELCASE.isSet(options)) {
|
if (LineReader.Option.COMPLETE_MATCHER_CAMELCASE.isSet(options)) {
|
||||||
matchers.add(simpleMatcher(s -> camelMatch(wd, 0, s, 0)));
|
matchers.add(simpleMatcher(s -> camelMatch(wd, 0, s, 0)));
|
||||||
@ -128,18 +141,20 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Function<Map<String, List<Candidate>>,
|
protected Function<Map<String, List<Candidate>>, Map<String, List<Candidate>>> simpleMatcher(
|
||||||
Map<String, List<Candidate>>> simpleMatcher(Predicate<String> predicate) {
|
Predicate<String> predicate) {
|
||||||
return m -> m.entrySet().stream()
|
return m -> m.entrySet().stream()
|
||||||
.filter(e -> predicate.test(e.getKey()))
|
.filter(e -> predicate.test(e.getKey()))
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Function<Map<String, List<Candidate>>,
|
protected Function<Map<String, List<Candidate>>, Map<String, List<Candidate>>> typoMatcher(
|
||||||
Map<String, List<Candidate>>> typoMatcher(String word, int errors, boolean caseInsensitive, String originalGroupName) {
|
String word, int errors, boolean caseInsensitive, String originalGroupName) {
|
||||||
return m -> {
|
return m -> {
|
||||||
Map<String, List<Candidate>> map = m.entrySet().stream()
|
Map<String, List<Candidate>> map = m.entrySet().stream()
|
||||||
.filter(e -> ReaderUtils.distance(word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey()) < errors)
|
.filter(e -> ReaderUtils.distance(
|
||||||
|
word, caseInsensitive ? e.getKey().toLowerCase() : e.getKey())
|
||||||
|
< errors)
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
|
||||||
if (map.size() > 1) {
|
if (map.size() > 1) {
|
||||||
map.computeIfAbsent(word, w -> new ArrayList<>())
|
map.computeIfAbsent(word, w -> new ArrayList<>())
|
||||||
@ -178,7 +193,8 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
Map<String, List<Candidate>> sortedCandidates = new HashMap<>();
|
Map<String, List<Candidate>> sortedCandidates = new HashMap<>();
|
||||||
for (Candidate candidate : candidates) {
|
for (Candidate candidate : candidates) {
|
||||||
sortedCandidates
|
sortedCandidates
|
||||||
.computeIfAbsent(AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>())
|
.computeIfAbsent(
|
||||||
|
AttributedString.fromAnsi(candidate.value()).toString(), s -> new ArrayList<>())
|
||||||
.add(candidate);
|
.add(candidate);
|
||||||
}
|
}
|
||||||
return sortedCandidates;
|
return sortedCandidates;
|
||||||
@ -206,5 +222,4 @@ public class CompletionMatcherImpl implements CompletionMatcher {
|
|||||||
}
|
}
|
||||||
return new String(s1, 0, len);
|
return new String(s1, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -32,27 +32,25 @@ public class DefaultExpander implements Expander {
|
|||||||
if (unicode > 0) {
|
if (unicode > 0) {
|
||||||
escaped = (--unicode >= 0);
|
escaped = (--unicode >= 0);
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
} else if (escaped) {
|
||||||
else if (escaped) {
|
|
||||||
if (c == 'u') {
|
if (c == 'u') {
|
||||||
unicode = 4;
|
unicode = 4;
|
||||||
} else {
|
} else {
|
||||||
escaped = false;
|
escaped = false;
|
||||||
}
|
}
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
} else if (c == '\'') {
|
||||||
else if (c == '\'') {
|
|
||||||
inQuote = !inQuote;
|
inQuote = !inQuote;
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
} else if (inQuote) {
|
||||||
else if (inQuote) {
|
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\\':
|
case '\\':
|
||||||
// any '\!' should be considered an expansion escape, so skip expansion and strip the escape character
|
// any '\!' should be considered an expansion escape, so skip expansion and strip the escape
|
||||||
// a leading '\^' should be considered an expansion escape, so skip expansion and strip the escape character
|
// character
|
||||||
|
// a leading '\^' should be considered an expansion escape, so skip expansion and strip the
|
||||||
|
// escape character
|
||||||
// otherwise, add the escape
|
// otherwise, add the escape
|
||||||
escaped = true;
|
escaped = true;
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
@ -91,7 +89,8 @@ public class DefaultExpander implements Expander {
|
|||||||
if (history.size() == 0) {
|
if (history.size() == 0) {
|
||||||
throw new IllegalArgumentException("!$: event not found");
|
throw new IllegalArgumentException("!$: event not found");
|
||||||
}
|
}
|
||||||
String previous = history.get(history.index() - 1).trim();
|
String previous =
|
||||||
|
history.get(history.index() - 1).trim();
|
||||||
int lastSpace = previous.lastIndexOf(' ');
|
int lastSpace = previous.lastIndexOf(' ');
|
||||||
if (lastSpace != -1) {
|
if (lastSpace != -1) {
|
||||||
rep = previous.substring(lastSpace + 1);
|
rep = previous.substring(lastSpace + 1);
|
||||||
@ -128,14 +127,18 @@ public class DefaultExpander implements Expander {
|
|||||||
try {
|
try {
|
||||||
idx = Integer.parseInt(line.substring(i1, i));
|
idx = Integer.parseInt(line.substring(i1, i));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
|
throw new IllegalArgumentException(
|
||||||
|
(neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
|
||||||
}
|
}
|
||||||
if (neg && idx > 0 && idx <= history.size()) {
|
if (neg && idx > 0 && idx <= history.size()) {
|
||||||
rep = history.get(history.index() - idx);
|
rep = history.get(history.index() - idx);
|
||||||
} else if (!neg && idx > history.index() - history.size() && idx <= history.index()) {
|
} else if (!neg
|
||||||
|
&& idx > history.index() - history.size()
|
||||||
|
&& idx <= history.index()) {
|
||||||
rep = history.get(idx - 1);
|
rep = history.get(idx - 1);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException((neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
|
throw new IllegalArgumentException(
|
||||||
|
(neg ? "!-" : "!") + line.substring(i1, i) + ": event not found");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -10,9 +10,9 @@ package jdk.internal.org.jline.reader.impl;
|
|||||||
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.reader.Highlighter;
|
||||||
import jdk.internal.org.jline.reader.LineReader;
|
import jdk.internal.org.jline.reader.LineReader;
|
||||||
import jdk.internal.org.jline.reader.LineReader.RegionType;
|
import jdk.internal.org.jline.reader.LineReader.RegionType;
|
||||||
import jdk.internal.org.jline.reader.Highlighter;
|
|
||||||
import jdk.internal.org.jline.utils.AttributedString;
|
import jdk.internal.org.jline.utils.AttributedString;
|
||||||
import jdk.internal.org.jline.utils.AttributedStringBuilder;
|
import jdk.internal.org.jline.utils.AttributedStringBuilder;
|
||||||
import jdk.internal.org.jline.utils.AttributedStyle;
|
import jdk.internal.org.jline.utils.AttributedStyle;
|
||||||
@ -57,7 +57,8 @@ public class DefaultHighlighter implements Highlighter {
|
|||||||
while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') {
|
while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') {
|
||||||
negativeStart--;
|
negativeStart--;
|
||||||
}
|
}
|
||||||
while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') {
|
while (negativeEnd < reader.getBuffer().length() - 1
|
||||||
|
&& reader.getBuffer().atChar(negativeEnd + 1) != '\n') {
|
||||||
negativeEnd++;
|
negativeEnd++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,5 +105,4 @@ public class DefaultHighlighter implements Highlighter {
|
|||||||
}
|
}
|
||||||
return sb.toAttributedString();
|
return sb.toAttributedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -30,9 +30,9 @@ public class DefaultParser implements Parser {
|
|||||||
public static class BlockCommentDelims {
|
public static class BlockCommentDelims {
|
||||||
private final String start;
|
private final String start;
|
||||||
private final String end;
|
private final String end;
|
||||||
|
|
||||||
public BlockCommentDelims(String start, String end) {
|
public BlockCommentDelims(String start, String end) {
|
||||||
if (start == null || end == null
|
if (start == null || end == null || start.isEmpty() || end.isEmpty() || start.equals(end)) {
|
||||||
|| start.isEmpty() || end.isEmpty() || start.equals(end)) {
|
|
||||||
throw new IllegalArgumentException("Bad block comment delimiter!");
|
throw new IllegalArgumentException("Bad block comment delimiter!");
|
||||||
}
|
}
|
||||||
this.start = start;
|
this.start = start;
|
||||||
@ -229,7 +229,6 @@ public class DefaultParser implements Parser {
|
|||||||
return name != null && regexVariable != null && name.matches(regexVariable);
|
return name != null && regexVariable != null && name.matches(regexVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCommand(final String line) {
|
public String getCommand(final String line) {
|
||||||
String out = "";
|
String out = "";
|
||||||
@ -296,7 +295,7 @@ public class DefaultParser implements Parser {
|
|||||||
if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) {
|
if (quoteStart < 0 && isQuoteChar(line, i) && !lineCommented && !blockCommented) {
|
||||||
// Start a quote block
|
// Start a quote block
|
||||||
quoteStart = i;
|
quoteStart = i;
|
||||||
if (current.length()==0) {
|
if (current.length() == 0) {
|
||||||
quotedWord = true;
|
quotedWord = true;
|
||||||
if (context == ParseContext.SPLIT_LINE) {
|
if (context == ParseContext.SPLIT_LINE) {
|
||||||
current.append(line.charAt(i));
|
current.append(line.charAt(i));
|
||||||
@ -324,13 +323,15 @@ public class DefaultParser implements Parser {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Delimiter
|
// Delimiter
|
||||||
rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i);
|
rawWordLength = handleDelimiterAndGetRawWordLength(
|
||||||
|
current, words, rawWordStart, rawWordCursor, rawWordLength, i);
|
||||||
rawWordStart = i + 1;
|
rawWordStart = i + 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) {
|
if (quoteStart < 0 && !blockCommented && (lineCommented || isLineCommentStarted(line, i))) {
|
||||||
lineCommented = true;
|
lineCommented = true;
|
||||||
} else if (quoteStart < 0 && !lineCommented
|
} else if (quoteStart < 0
|
||||||
|
&& !lineCommented
|
||||||
&& (blockCommented || isCommentDelim(line, i, blockCommentStart))) {
|
&& (blockCommented || isCommentDelim(line, i, blockCommentStart))) {
|
||||||
if (blockCommented) {
|
if (blockCommented) {
|
||||||
if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) {
|
if (blockCommentEnd != null && isCommentDelim(line, i, blockCommentEnd)) {
|
||||||
@ -339,12 +340,12 @@ public class DefaultParser implements Parser {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blockCommented = true;
|
blockCommented = true;
|
||||||
rawWordLength = handleDelimiterAndGetRawWordLength(current, words, rawWordStart, rawWordCursor, rawWordLength, i);
|
rawWordLength = handleDelimiterAndGetRawWordLength(
|
||||||
|
current, words, rawWordStart, rawWordCursor, rawWordLength, i);
|
||||||
i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1;
|
i += blockCommentStart == null ? 0 : blockCommentStart.length() - 1;
|
||||||
rawWordStart = i + 1;
|
rawWordStart = i + 1;
|
||||||
}
|
}
|
||||||
} else if (quoteStart < 0 && !lineCommented
|
} else if (quoteStart < 0 && !lineCommented && isCommentDelim(line, i, blockCommentEnd)) {
|
||||||
&& isCommentDelim(line, i, blockCommentEnd)) {
|
|
||||||
current.append(line.charAt(i));
|
current.append(line.charAt(i));
|
||||||
blockCommentInRightOrder = false;
|
blockCommentInRightOrder = false;
|
||||||
} else if (!isEscapeChar(line, i)) {
|
} else if (!isEscapeChar(line, i)) {
|
||||||
@ -377,16 +378,14 @@ public class DefaultParser implements Parser {
|
|||||||
throw new EOFError(-1, -1, "Escaped new line", "newline");
|
throw new EOFError(-1, -1, "Escaped new line", "newline");
|
||||||
}
|
}
|
||||||
if (eofOnUnclosedQuote && quoteStart >= 0) {
|
if (eofOnUnclosedQuote && quoteStart >= 0) {
|
||||||
throw new EOFError(-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\''
|
throw new EOFError(
|
||||||
? "quote" : "dquote");
|
-1, -1, "Missing closing quote", line.charAt(quoteStart) == '\'' ? "quote" : "dquote");
|
||||||
}
|
}
|
||||||
if (blockCommented) {
|
if (blockCommented) {
|
||||||
throw new EOFError(-1, -1, "Missing closing block comment delimiter",
|
throw new EOFError(-1, -1, "Missing closing block comment delimiter", "add: " + blockCommentEnd);
|
||||||
"add: " + blockCommentEnd);
|
|
||||||
}
|
}
|
||||||
if (!blockCommentInRightOrder) {
|
if (!blockCommentInRightOrder) {
|
||||||
throw new EOFError(-1, -1, "Missing opening block comment delimiter",
|
throw new EOFError(-1, -1, "Missing opening block comment delimiter", "missing: " + blockCommentStart);
|
||||||
"missing: " + blockCommentStart);
|
|
||||||
}
|
}
|
||||||
if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) {
|
if (bracketChecker.isClosingBracketMissing() || bracketChecker.isOpeningBracketMissing()) {
|
||||||
String message = null;
|
String message = null;
|
||||||
@ -398,8 +397,13 @@ public class DefaultParser implements Parser {
|
|||||||
message = "Missing opening bracket";
|
message = "Missing opening bracket";
|
||||||
missing = "missing: " + bracketChecker.getMissingOpeningBracket();
|
missing = "missing: " + bracketChecker.getMissingOpeningBracket();
|
||||||
}
|
}
|
||||||
throw new EOFError(-1, -1, message, missing,
|
throw new EOFError(
|
||||||
bracketChecker.getOpenBrackets(), bracketChecker.getNextClosingBracket());
|
-1,
|
||||||
|
-1,
|
||||||
|
message,
|
||||||
|
missing,
|
||||||
|
bracketChecker.getOpenBrackets(),
|
||||||
|
bracketChecker.getNextClosingBracket());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +424,13 @@ public class DefaultParser implements Parser {
|
|||||||
return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
|
return !isQuoted(buffer, pos) && !isEscaped(buffer, pos) && isDelimiterChar(buffer, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int handleDelimiterAndGetRawWordLength(StringBuilder current, List<String> words, int rawWordStart, int rawWordCursor, int rawWordLength, int pos) {
|
private int handleDelimiterAndGetRawWordLength(
|
||||||
|
StringBuilder current,
|
||||||
|
List<String> words,
|
||||||
|
int rawWordStart,
|
||||||
|
int rawWordCursor,
|
||||||
|
int rawWordLength,
|
||||||
|
int pos) {
|
||||||
if (current.length() > 0) {
|
if (current.length() > 0) {
|
||||||
words.add(current.toString());
|
words.add(current.toString());
|
||||||
current.setLength(0); // reset the arg
|
current.setLength(0); // reset the arg
|
||||||
@ -470,7 +480,7 @@ public class DefaultParser implements Parser {
|
|||||||
|
|
||||||
public boolean isLineCommentStarted(final CharSequence buffer, final int pos) {
|
public boolean isLineCommentStarted(final CharSequence buffer, final int pos) {
|
||||||
if (lineCommentDelims != null) {
|
if (lineCommentDelims != null) {
|
||||||
for (String comment: lineCommentDelims) {
|
for (String comment : lineCommentDelims) {
|
||||||
if (isCommentDelim(buffer, pos, comment)) {
|
if (isCommentDelim(buffer, pos, comment)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -584,8 +594,8 @@ public class DefaultParser implements Parser {
|
|||||||
} else {
|
} else {
|
||||||
bid = bracketId(closingBrackets, buffer, pos);
|
bid = bracketId(closingBrackets, buffer, pos);
|
||||||
if (bid >= 0) {
|
if (bid >= 0) {
|
||||||
if (!nested.isEmpty() && bid == nested.get(nested.size()-1)) {
|
if (!nested.isEmpty() && bid == nested.get(nested.size() - 1)) {
|
||||||
nested.remove(nested.size()-1);
|
nested.remove(nested.size() - 1);
|
||||||
} else {
|
} else {
|
||||||
missingOpeningBracket = bid;
|
missingOpeningBracket = bid;
|
||||||
}
|
}
|
||||||
@ -634,7 +644,7 @@ public class DefaultParser implements Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int bracketId(final char[] brackets, final CharSequence buffer, final int pos) {
|
private int bracketId(final char[] brackets, final CharSequence buffer, final int pos) {
|
||||||
for (int i=0; i < brackets.length; i++) {
|
for (int i = 0; i < brackets.length; i++) {
|
||||||
if (buffer.charAt(pos) == brackets[i]) {
|
if (buffer.charAt(pos) == brackets[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -648,8 +658,7 @@ public class DefaultParser implements Parser {
|
|||||||
*
|
*
|
||||||
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
|
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
|
||||||
*/
|
*/
|
||||||
public class ArgumentList implements ParsedLine, CompletingParsedLine
|
public class ArgumentList implements ParsedLine, CompletingParsedLine {
|
||||||
{
|
|
||||||
private final String line;
|
private final String line;
|
||||||
|
|
||||||
private final List<String> words;
|
private final List<String> words;
|
||||||
@ -667,11 +676,21 @@ public class DefaultParser implements Parser {
|
|||||||
private final int rawWordLength;
|
private final int rawWordLength;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public ArgumentList(final String line, final List<String> words,
|
public ArgumentList(
|
||||||
final int wordIndex, final int wordCursor,
|
final String line,
|
||||||
|
final List<String> words,
|
||||||
|
final int wordIndex,
|
||||||
|
final int wordCursor,
|
||||||
final int cursor) {
|
final int cursor) {
|
||||||
this(line, words, wordIndex, wordCursor, cursor,
|
this(
|
||||||
null, wordCursor, words.get(wordIndex).length());
|
line,
|
||||||
|
words,
|
||||||
|
wordIndex,
|
||||||
|
wordCursor,
|
||||||
|
cursor,
|
||||||
|
null,
|
||||||
|
wordCursor,
|
||||||
|
words.get(wordIndex).length());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -685,10 +704,15 @@ public class DefaultParser implements Parser {
|
|||||||
* @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters)
|
* @param rawWordCursor the cursor position inside the raw word (i.e. including quotes and escape characters)
|
||||||
* @param rawWordLength the raw word length, including quotes and escape characters
|
* @param rawWordLength the raw word length, including quotes and escape characters
|
||||||
*/
|
*/
|
||||||
public ArgumentList(final String line, final List<String> words,
|
public ArgumentList(
|
||||||
final int wordIndex, final int wordCursor,
|
final String line,
|
||||||
final int cursor, final String openingQuote,
|
final List<String> words,
|
||||||
final int rawWordCursor, final int rawWordLength) {
|
final int wordIndex,
|
||||||
|
final int wordCursor,
|
||||||
|
final int cursor,
|
||||||
|
final String openingQuote,
|
||||||
|
final int rawWordCursor,
|
||||||
|
final int rawWordLength) {
|
||||||
this.line = line;
|
this.line = line;
|
||||||
this.words = Collections.unmodifiableList(Objects.requireNonNull(words));
|
this.words = Collections.unmodifiableList(Objects.requireNonNull(words));
|
||||||
this.wordIndex = wordIndex;
|
this.wordIndex = wordIndex;
|
||||||
@ -732,8 +756,8 @@ public class DefaultParser implements Parser {
|
|||||||
Predicate<Integer> needToBeEscaped;
|
Predicate<Integer> needToBeEscaped;
|
||||||
String quote = openingQuote;
|
String quote = openingQuote;
|
||||||
boolean middleQuotes = false;
|
boolean middleQuotes = false;
|
||||||
if (openingQuote==null) {
|
if (openingQuote == null) {
|
||||||
for (int i=0; i < sb.length(); i++) {
|
for (int i = 0; i < sb.length(); i++) {
|
||||||
if (isQuoteChar(sb, i)) {
|
if (isQuoteChar(sb, i)) {
|
||||||
middleQuotes = true;
|
middleQuotes = true;
|
||||||
break;
|
break;
|
||||||
@ -746,7 +770,8 @@ public class DefaultParser implements Parser {
|
|||||||
// Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does.
|
// Delimiters (spaces) don't need to be escaped, nor do other quotes, but everything else does.
|
||||||
// Also, close the quote at the end
|
// Also, close the quote at the end
|
||||||
if (openingQuote != null) {
|
if (openingQuote != null) {
|
||||||
needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i)) || String.valueOf(sb.charAt(i)).equals(openingQuote);
|
needToBeEscaped = i -> isRawEscapeChar(sb.charAt(i))
|
||||||
|
|| String.valueOf(sb.charAt(i)).equals(openingQuote);
|
||||||
}
|
}
|
||||||
// Completion is protected by middle quotes:
|
// Completion is protected by middle quotes:
|
||||||
// Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does.
|
// Delimiters (spaces) don't need to be escaped, nor do quotes, but everything else does.
|
||||||
@ -756,8 +781,8 @@ public class DefaultParser implements Parser {
|
|||||||
// No quote protection, need to escape everything: delimiter chars (spaces), quote chars
|
// No quote protection, need to escape everything: delimiter chars (spaces), quote chars
|
||||||
// and escapes themselves
|
// and escapes themselves
|
||||||
else {
|
else {
|
||||||
needToBeEscaped = i -> isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i))
|
needToBeEscaped = i ->
|
||||||
|| isRawQuoteChar(sb.charAt(i));
|
isDelimiterChar(sb, i) || isRawEscapeChar(sb.charAt(i)) || isRawQuoteChar(sb.charAt(i));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < sb.length(); i++) {
|
for (int i = 0; i < sb.length(); i++) {
|
||||||
if (needToBeEscaped.test(i)) {
|
if (needToBeEscaped.test(i)) {
|
||||||
@ -792,5 +817,4 @@ public class DefaultParser implements Parser {
|
|||||||
return rawWordLength;
|
return rawWordLength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,394 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.reader.impl;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.reader.LineReader;
|
||||||
|
import jdk.internal.org.jline.reader.Macro;
|
||||||
|
import jdk.internal.org.jline.reader.Reference;
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.utils.Log;
|
||||||
|
|
||||||
|
public final class InputRC {
|
||||||
|
|
||||||
|
public static void configure(LineReader reader, URL url) throws IOException {
|
||||||
|
try (InputStream is = url.openStream()) {
|
||||||
|
configure(reader, is);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void configure(LineReader reader, InputStream is) throws IOException {
|
||||||
|
try (InputStreamReader r = new InputStreamReader(is)) {
|
||||||
|
configure(reader, r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void configure(LineReader reader, Reader r) throws IOException {
|
||||||
|
BufferedReader br;
|
||||||
|
if (r instanceof BufferedReader) {
|
||||||
|
br = (BufferedReader) r;
|
||||||
|
} else {
|
||||||
|
br = new BufferedReader(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
Terminal terminal = reader.getTerminal();
|
||||||
|
|
||||||
|
if (Terminal.TYPE_DUMB.equals(terminal.getType()) || Terminal.TYPE_DUMB_COLOR.equals(terminal.getType())) {
|
||||||
|
reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "dumb");
|
||||||
|
} else {
|
||||||
|
reader.getVariables().putIfAbsent(LineReader.EDITING_MODE, "emacs");
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.setKeyMap(LineReader.MAIN);
|
||||||
|
new InputRC(reader).parse(br);
|
||||||
|
if ("vi".equals(reader.getVariable(LineReader.EDITING_MODE))) {
|
||||||
|
reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.VIINS));
|
||||||
|
} else if ("emacs".equals(reader.getVariable(LineReader.EDITING_MODE))) {
|
||||||
|
reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.EMACS));
|
||||||
|
} else if ("dumb".equals(reader.getVariable(LineReader.EDITING_MODE))) {
|
||||||
|
reader.getKeyMaps().put(LineReader.MAIN, reader.getKeyMaps().get(LineReader.DUMB));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final LineReader reader;
|
||||||
|
|
||||||
|
private InputRC(LineReader reader) {
|
||||||
|
this.reader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parse(BufferedReader br) throws IOException, IllegalArgumentException {
|
||||||
|
String line;
|
||||||
|
boolean parsing = true;
|
||||||
|
List<Boolean> ifsStack = new ArrayList<>();
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
try {
|
||||||
|
line = line.trim();
|
||||||
|
if (line.length() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.charAt(0) == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
if (line.charAt(i) == '$') {
|
||||||
|
String cmd;
|
||||||
|
String args;
|
||||||
|
++i;
|
||||||
|
while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int s = i;
|
||||||
|
while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
cmd = line.substring(s, i);
|
||||||
|
while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
s = i;
|
||||||
|
while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
args = line.substring(s, i);
|
||||||
|
if ("if".equalsIgnoreCase(cmd)) {
|
||||||
|
ifsStack.add(parsing);
|
||||||
|
if (!parsing) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (args.startsWith("term=")) {
|
||||||
|
// TODO
|
||||||
|
} else if (args.startsWith("mode=")) {
|
||||||
|
String mode = (String) reader.getVariable(LineReader.EDITING_MODE);
|
||||||
|
parsing = args.substring("mode=".length()).equalsIgnoreCase(mode);
|
||||||
|
} else {
|
||||||
|
parsing = args.equalsIgnoreCase(reader.getAppName());
|
||||||
|
}
|
||||||
|
} else if ("else".equalsIgnoreCase(cmd)) {
|
||||||
|
if (ifsStack.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("$else found without matching $if");
|
||||||
|
}
|
||||||
|
boolean invert = true;
|
||||||
|
for (boolean b : ifsStack) {
|
||||||
|
if (!b) {
|
||||||
|
invert = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (invert) {
|
||||||
|
parsing = !parsing;
|
||||||
|
}
|
||||||
|
} else if ("endif".equalsIgnoreCase(cmd)) {
|
||||||
|
if (ifsStack.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("endif found without matching $if");
|
||||||
|
}
|
||||||
|
parsing = ifsStack.remove(ifsStack.size() - 1);
|
||||||
|
} else if ("include".equalsIgnoreCase(cmd)) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!parsing) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (line.charAt(i++) == '"') {
|
||||||
|
boolean esc = false;
|
||||||
|
for (; ; i++) {
|
||||||
|
if (i >= line.length()) {
|
||||||
|
throw new IllegalArgumentException("Missing closing quote on line '" + line + "'");
|
||||||
|
}
|
||||||
|
if (esc) {
|
||||||
|
esc = false;
|
||||||
|
} else if (line.charAt(i) == '\\') {
|
||||||
|
esc = true;
|
||||||
|
} else if (line.charAt(i) == '"') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i < line.length() && line.charAt(i) != ':' && line.charAt(i) != ' ' && line.charAt(i) != '\t') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
String keySeq = line.substring(0, i);
|
||||||
|
boolean equivalency = i + 1 < line.length() && line.charAt(i) == ':' && line.charAt(i + 1) == '=';
|
||||||
|
i++;
|
||||||
|
if (equivalency) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (keySeq.equalsIgnoreCase("set")) {
|
||||||
|
String key;
|
||||||
|
String val;
|
||||||
|
while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int s = i;
|
||||||
|
while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
key = line.substring(s, i);
|
||||||
|
while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
s = i;
|
||||||
|
while (i < line.length() && (line.charAt(i) != ' ' && line.charAt(i) != '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
val = line.substring(s, i);
|
||||||
|
setVar(reader, key, val);
|
||||||
|
} else {
|
||||||
|
while (i < line.length() && (line.charAt(i) == ' ' || line.charAt(i) == '\t')) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
int start = i;
|
||||||
|
if (i < line.length() && (line.charAt(i) == '\'' || line.charAt(i) == '\"')) {
|
||||||
|
char delim = line.charAt(i++);
|
||||||
|
boolean esc = false;
|
||||||
|
for (; ; i++) {
|
||||||
|
if (i >= line.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (esc) {
|
||||||
|
esc = false;
|
||||||
|
} else if (line.charAt(i) == '\\') {
|
||||||
|
esc = true;
|
||||||
|
} else if (line.charAt(i) == delim) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; i < line.length() && line.charAt(i) != ' ' && line.charAt(i) != '\t'; i++)
|
||||||
|
;
|
||||||
|
String val = line.substring(Math.min(start, line.length()), Math.min(i, line.length()));
|
||||||
|
if (keySeq.charAt(0) == '"') {
|
||||||
|
keySeq = translateQuoted(keySeq);
|
||||||
|
} else {
|
||||||
|
// Bind key name
|
||||||
|
String keyName =
|
||||||
|
keySeq.lastIndexOf('-') > 0 ? keySeq.substring(keySeq.lastIndexOf('-') + 1) : keySeq;
|
||||||
|
char key = getKeyFromName(keyName);
|
||||||
|
keyName = keySeq.toLowerCase();
|
||||||
|
keySeq = "";
|
||||||
|
if (keyName.contains("meta-") || keyName.contains("m-")) {
|
||||||
|
keySeq += "\u001b";
|
||||||
|
}
|
||||||
|
if (keyName.contains("control-") || keyName.contains("c-") || keyName.contains("ctrl-")) {
|
||||||
|
key = (char) (Character.toUpperCase(key) & 0x1f);
|
||||||
|
}
|
||||||
|
keySeq += key;
|
||||||
|
}
|
||||||
|
if (val.length() > 0 && (val.charAt(0) == '\'' || val.charAt(0) == '\"')) {
|
||||||
|
reader.getKeys().bind(new Macro(translateQuoted(val)), keySeq);
|
||||||
|
} else {
|
||||||
|
reader.getKeys().bind(new Reference(val), keySeq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
Log.warn("Unable to parse user configuration: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String translateQuoted(String keySeq) {
|
||||||
|
int i;
|
||||||
|
String str = keySeq.substring(1, keySeq.length() - 1);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (i = 0; i < str.length(); i++) {
|
||||||
|
char c = str.charAt(i);
|
||||||
|
if (c == '\\') {
|
||||||
|
boolean ctrl = str.regionMatches(i, "\\C-", 0, 3) || str.regionMatches(i, "\\M-\\C-", 0, 6);
|
||||||
|
boolean meta = str.regionMatches(i, "\\M-", 0, 3) || str.regionMatches(i, "\\C-\\M-", 0, 6);
|
||||||
|
i += (meta ? 3 : 0) + (ctrl ? 3 : 0) + (!meta && !ctrl ? 1 : 0);
|
||||||
|
if (i >= str.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = str.charAt(i);
|
||||||
|
if (meta) {
|
||||||
|
sb.append("\u001b");
|
||||||
|
}
|
||||||
|
if (ctrl) {
|
||||||
|
c = c == '?' ? 0x7f : (char) (Character.toUpperCase(c) & 0x1f);
|
||||||
|
}
|
||||||
|
if (!meta && !ctrl) {
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
c = 0x07;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
c = '\b';
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
c = 0x7f;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
c = 0x1b;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
c = '\f';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
c = '\n';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
c = '\r';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\t';
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
c = 0x0b;
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
c = '\\';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7':
|
||||||
|
c = 0;
|
||||||
|
for (int j = 0; j < 3; j++, i++) {
|
||||||
|
if (i >= str.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int k = Character.digit(str.charAt(i), 8);
|
||||||
|
if (k < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = (char) (c * 8 + k);
|
||||||
|
}
|
||||||
|
c &= 0xFF;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
i++;
|
||||||
|
c = 0;
|
||||||
|
for (int j = 0; j < 2; j++, i++) {
|
||||||
|
if (i >= str.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int k = Character.digit(str.charAt(i), 16);
|
||||||
|
if (k < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = (char) (c * 16 + k);
|
||||||
|
}
|
||||||
|
c &= 0xFF;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
i++;
|
||||||
|
c = 0;
|
||||||
|
for (int j = 0; j < 4; j++, i++) {
|
||||||
|
if (i >= str.length()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int k = Character.digit(str.charAt(i), 16);
|
||||||
|
if (k < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = (char) (c * 16 + k);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(c);
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char getKeyFromName(String name) {
|
||||||
|
if ("DEL".equalsIgnoreCase(name) || "Rubout".equalsIgnoreCase(name)) {
|
||||||
|
return 0x7f;
|
||||||
|
} else if ("ESC".equalsIgnoreCase(name) || "Escape".equalsIgnoreCase(name)) {
|
||||||
|
return '\033';
|
||||||
|
} else if ("LFD".equalsIgnoreCase(name) || "NewLine".equalsIgnoreCase(name)) {
|
||||||
|
return '\n';
|
||||||
|
} else if ("RET".equalsIgnoreCase(name) || "Return".equalsIgnoreCase(name)) {
|
||||||
|
return '\r';
|
||||||
|
} else if ("SPC".equalsIgnoreCase(name) || "Space".equalsIgnoreCase(name)) {
|
||||||
|
return ' ';
|
||||||
|
} else if ("Tab".equalsIgnoreCase(name)) {
|
||||||
|
return '\t';
|
||||||
|
} else {
|
||||||
|
return name.charAt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setVar(LineReader reader, String key, String val) {
|
||||||
|
if (LineReader.KEYMAP.equalsIgnoreCase(key)) {
|
||||||
|
reader.setKeyMap(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (LineReader.Option option : LineReader.Option.values()) {
|
||||||
|
if (option.name().toLowerCase(Locale.ENGLISH).replace('_', '-').equals(val)) {
|
||||||
|
if ("on".equalsIgnoreCase(val)) {
|
||||||
|
reader.setOpt(option);
|
||||||
|
} else if ("off".equalsIgnoreCase(val)) {
|
||||||
|
reader.unsetOpt(option);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.setVariable(key, val);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -13,7 +13,7 @@ import jdk.internal.org.jline.utils.Levenshtein;
|
|||||||
|
|
||||||
public class ReaderUtils {
|
public class ReaderUtils {
|
||||||
|
|
||||||
private ReaderUtils() { }
|
private ReaderUtils() {}
|
||||||
|
|
||||||
public static boolean isSet(LineReader reader, LineReader.Option option) {
|
public static boolean isSet(LineReader reader, LineReader.Option option) {
|
||||||
return reader != null && reader.isSet(option);
|
return reader != null && reader.isSet(option);
|
||||||
@ -30,8 +30,7 @@ public class ReaderUtils {
|
|||||||
return (Boolean) v;
|
return (Boolean) v;
|
||||||
} else if (v != null) {
|
} else if (v != null) {
|
||||||
String s = v.toString();
|
String s = v.toString();
|
||||||
return s.isEmpty() || s.equalsIgnoreCase("on")
|
return s.isEmpty() || s.equalsIgnoreCase("on") || s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true");
|
||||||
|| s.equalsIgnoreCase("1") || s.equalsIgnoreCase("true");
|
|
||||||
}
|
}
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
@ -77,5 +76,4 @@ public class ReaderUtils {
|
|||||||
return Levenshtein.distance(word, cand);
|
return Levenshtein.distance(word, cand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2017, the original author or authors.
|
* Copyright (c) 2002-2017, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,10 +8,10 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.reader.impl;
|
package jdk.internal.org.jline.reader.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.reader.MaskingCallback;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.reader.MaskingCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask.
|
* Simple {@link MaskingCallback} that will replace all the characters in the line with the given mask.
|
||||||
* If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String.
|
* If the given mask is equal to {@link LineReaderImpl#NULL_MASK} then the line will be replaced with an empty String.
|
||||||
@ -29,7 +29,7 @@ public final class SimpleMaskingCallback implements MaskingCallback {
|
|||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
StringBuilder sb = new StringBuilder(line.length());
|
StringBuilder sb = new StringBuilder(line.length());
|
||||||
for (int i = line.length(); i-- > 0;) {
|
for (int i = line.length(); i-- > 0; ) {
|
||||||
sb.append((char) mask);
|
sb.append((char) mask);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@ -40,5 +40,4 @@ public final class SimpleMaskingCallback implements MaskingCallback {
|
|||||||
public String history(String line) {
|
public String history(String line) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -20,6 +20,7 @@ public class UndoTree<T> {
|
|||||||
private final Node parent;
|
private final Node parent;
|
||||||
private Node current;
|
private Node current;
|
||||||
|
|
||||||
|
@SuppressWarnings("this-escape")
|
||||||
public UndoTree(Consumer<T> s) {
|
public UndoTree(Consumer<T> s) {
|
||||||
state = s;
|
state = s;
|
||||||
parent = new Node(null);
|
parent = new Node(null);
|
||||||
@ -71,5 +72,4 @@ public class UndoTree<T> {
|
|||||||
state = s;
|
state = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -24,9 +24,7 @@ import jdk.internal.org.jline.reader.ParsedLine;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public class AggregateCompleter
|
public class AggregateCompleter implements Completer {
|
||||||
implements Completer
|
|
||||||
{
|
|
||||||
private final Collection<Completer> completers;
|
private final Collection<Completer> completers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,9 +76,6 @@ public class AggregateCompleter
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getSimpleName() + "{" +
|
return getClass().getSimpleName() + "{" + "completers=" + completers + '}';
|
||||||
"completers=" + completers +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2019, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -29,8 +29,7 @@ import jdk.internal.org.jline.reader.ParsedLine;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public class ArgumentCompleter implements Completer
|
public class ArgumentCompleter implements Completer {
|
||||||
{
|
|
||||||
private final List<Completer> completers = new ArrayList<>();
|
private final List<Completer> completers = new ArrayList<>();
|
||||||
|
|
||||||
private boolean strict = true;
|
private boolean strict = true;
|
||||||
@ -108,12 +107,12 @@ public class ArgumentCompleter implements Completer
|
|||||||
// if we are beyond the end of the completers, just use the last one
|
// if we are beyond the end of the completers, just use the last one
|
||||||
if (line.wordIndex() >= completers.size()) {
|
if (line.wordIndex() >= completers.size()) {
|
||||||
completer = completers.get(completers.size() - 1);
|
completer = completers.get(completers.size() - 1);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
completer = completers.get(line.wordIndex());
|
completer = completers.get(line.wordIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure that all the previous completers are successful before allowing this completer to pass (only if strict).
|
// ensure that all the previous completers are successful before allowing this completer to pass (only if
|
||||||
|
// strict).
|
||||||
for (int i = strictCommand ? 0 : 1; isStrict() && (i < line.wordIndex()); i++) {
|
for (int i = strictCommand ? 0 : 1; isStrict() && (i < line.wordIndex()); i++) {
|
||||||
int idx = i >= completers.size() ? (completers.size() - 1) : i;
|
int idx = i >= completers.size() ? (completers.size() - 1) : i;
|
||||||
if (idx == 0 && !strictCommand) {
|
if (idx == 0 && !strictCommand) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -19,8 +19,7 @@ import jdk.internal.org.jline.reader.Completer;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public class EnumCompleter extends StringsCompleter
|
public class EnumCompleter extends StringsCompleter {
|
||||||
{
|
|
||||||
public EnumCompleter(Class<? extends Enum<?>> source) {
|
public EnumCompleter(Class<? extends Enum<?>> source) {
|
||||||
Objects.requireNonNull(source);
|
Objects.requireNonNull(source);
|
||||||
for (Enum<?> n : source.getEnumConstants()) {
|
for (Enum<?> n : source.getEnumConstants()) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -9,6 +9,7 @@
|
|||||||
package jdk.internal.org.jline.reader.impl.completer;
|
package jdk.internal.org.jline.reader.impl.completer;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
@ -41,11 +42,10 @@ import jdk.internal.org.jline.utils.AttributedStyle;
|
|||||||
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
|
* @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
|
||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
* @deprecated use <code>jdk.internal.org.jline.builtins.Completers$FileNameCompleter</code> instead
|
* @deprecated use <code>org.jline.builtins.Completers$FileNameCompleter</code> instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public class FileNameCompleter implements Completer
|
public class FileNameCompleter implements Completer {
|
||||||
{
|
|
||||||
|
|
||||||
public void complete(LineReader reader, ParsedLine commandLine, final List<Candidate> candidates) {
|
public void complete(LineReader reader, ParsedLine commandLine, final List<Candidate> candidates) {
|
||||||
assert commandLine != null;
|
assert commandLine != null;
|
||||||
@ -72,20 +72,21 @@ public class FileNameCompleter implements Completer
|
|||||||
curBuf = "";
|
curBuf = "";
|
||||||
current = getUserDir();
|
current = getUserDir();
|
||||||
}
|
}
|
||||||
try {
|
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(current, this::accept)) {
|
||||||
Files.newDirectoryStream(current, this::accept).forEach(p -> {
|
directoryStream.forEach(p -> {
|
||||||
String value = curBuf + p.getFileName().toString();
|
String value = curBuf + p.getFileName().toString();
|
||||||
if (Files.isDirectory(p)) {
|
if (Files.isDirectory(p)) {
|
||||||
candidates.add(new Candidate(
|
candidates.add(new Candidate(
|
||||||
value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""),
|
value + (reader.isSet(Option.AUTO_PARAM_SLASH) ? sep : ""),
|
||||||
getDisplay(reader.getTerminal(), p),
|
getDisplay(reader.getTerminal(), p),
|
||||||
null, null,
|
null,
|
||||||
|
null,
|
||||||
reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null,
|
reader.isSet(Option.AUTO_REMOVE_SLASH) ? sep : null,
|
||||||
null,
|
null,
|
||||||
false));
|
false));
|
||||||
} else {
|
} else {
|
||||||
candidates.add(new Candidate(value, getDisplay(reader.getTerminal(), p),
|
candidates.add(
|
||||||
null, null, null, null, true));
|
new Candidate(value, getDisplay(reader.getTerminal(), p), null, null, null, null, true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -125,5 +126,4 @@ public class FileNameCompleter implements Completer
|
|||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -22,11 +22,8 @@ import jdk.internal.org.jline.reader.ParsedLine;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public final class NullCompleter
|
public final class NullCompleter implements Completer {
|
||||||
implements Completer
|
|
||||||
{
|
|
||||||
public static final NullCompleter INSTANCE = new NullCompleter();
|
public static final NullCompleter INSTANCE = new NullCompleter();
|
||||||
|
|
||||||
public void complete(LineReader reader, final ParsedLine line, final List<Candidate> candidates) {
|
public void complete(LineReader reader, final ParsedLine line, final List<Candidate> candidates) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2019, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -27,8 +27,7 @@ import jdk.internal.org.jline.utils.AttributedString;
|
|||||||
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
|
||||||
* @since 2.3
|
* @since 2.3
|
||||||
*/
|
*/
|
||||||
public class StringsCompleter implements Completer
|
public class StringsCompleter implements Completer {
|
||||||
{
|
|
||||||
protected Collection<Candidate> candidates;
|
protected Collection<Candidate> candidates;
|
||||||
protected Supplier<Collection<String>> stringsSupplier;
|
protected Supplier<Collection<String>> stringsSupplier;
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ public class StringsCompleter implements Completer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public StringsCompleter(Candidate ... candidates) {
|
public StringsCompleter(Candidate... candidates) {
|
||||||
this(Arrays.asList(candidates));
|
this(Arrays.asList(candidates));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2020, the original author or authors.
|
* Copyright (c) 2002-2020, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -22,8 +22,8 @@ import jdk.internal.org.jline.utils.AttributedString;
|
|||||||
* @author <a href="mailto:matti.rintanikkola@gmail.com">Matti Rinta-Nikkola</a>
|
* @author <a href="mailto:matti.rintanikkola@gmail.com">Matti Rinta-Nikkola</a>
|
||||||
*/
|
*/
|
||||||
public class SystemCompleter implements Completer {
|
public class SystemCompleter implements Completer {
|
||||||
private Map<String,List<Completer>> completers = new HashMap<>();
|
private Map<String, List<Completer>> completers = new HashMap<>();
|
||||||
private Map<String,String> aliasCommand = new HashMap<>();
|
private Map<String, String> aliasCommand = new HashMap<>();
|
||||||
private StringsCompleter commands;
|
private StringsCompleter commands;
|
||||||
private boolean compiled = false;
|
private boolean compiled = false;
|
||||||
|
|
||||||
@ -44,9 +44,9 @@ public class SystemCompleter implements Completer {
|
|||||||
commands.complete(reader, commandLine, candidates);
|
commands.complete(reader, commandLine, candidates);
|
||||||
} else if (reader.getParser().validVariableName(buffer.substring(0, eq))) {
|
} else if (reader.getParser().validVariableName(buffer.substring(0, eq))) {
|
||||||
String curBuf = buffer.substring(0, eq + 1);
|
String curBuf = buffer.substring(0, eq + 1);
|
||||||
for (String c: completers.keySet()) {
|
for (String c : completers.keySet()) {
|
||||||
candidates.add(new Candidate(AttributedString.stripAnsi(curBuf+c)
|
candidates.add(
|
||||||
, c, null, null, null, null, true));
|
new Candidate(AttributedString.stripAnsi(curBuf + c), c, null, null, null, null, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -81,7 +81,7 @@ public class SystemCompleter implements Completer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void add(List<String> commands, Completer completer) {
|
public void add(List<String> commands, Completer completer) {
|
||||||
for (String c: commands) {
|
for (String c : commands) {
|
||||||
add(c, completer);
|
add(c, completer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,22 +104,22 @@ public class SystemCompleter implements Completer {
|
|||||||
if (other.isCompiled()) {
|
if (other.isCompiled()) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, List<Completer>> entry: other.getCompleters().entrySet()) {
|
for (Map.Entry<String, List<Completer>> entry : other.getCompleters().entrySet()) {
|
||||||
for (Completer c: entry.getValue()) {
|
for (Completer c : entry.getValue()) {
|
||||||
add(entry.getKey(), c);
|
add(entry.getKey(), c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addAliases(other.getAliases());
|
addAliases(other.getAliases());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAliases(Map<String,String> aliasCommand) {
|
public void addAliases(Map<String, String> aliasCommand) {
|
||||||
if (compiled) {
|
if (compiled) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
this.aliasCommand.putAll(aliasCommand);
|
this.aliasCommand.putAll(aliasCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String,String> getAliases() {
|
private Map<String, String> getAliases() {
|
||||||
return aliasCommand;
|
return aliasCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ public class SystemCompleter implements Completer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Map<String, List<Completer>> compiledCompleters = new HashMap<>();
|
Map<String, List<Completer>> compiledCompleters = new HashMap<>();
|
||||||
for (Map.Entry<String, List<Completer>> entry: completers.entrySet()) {
|
for (Map.Entry<String, List<Completer>> entry : completers.entrySet()) {
|
||||||
if (entry.getValue().size() == 1) {
|
if (entry.getValue().size() == 1) {
|
||||||
compiledCompleters.put(entry.getKey(), entry.getValue());
|
compiledCompleters.put(entry.getKey(), entry.getValue());
|
||||||
} else {
|
} else {
|
||||||
@ -143,8 +143,7 @@ public class SystemCompleter implements Completer {
|
|||||||
compiled = true;
|
compiled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String,List<Completer>> getCompleters() {
|
public Map<String, List<Completer>> getCompleters() {
|
||||||
return completers;
|
return completers;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -41,9 +41,9 @@ public class DefaultHistory implements History {
|
|||||||
private int offset = 0;
|
private int offset = 0;
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|
||||||
public DefaultHistory() {
|
public DefaultHistory() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
@SuppressWarnings("this-escape")
|
||||||
public DefaultHistory(LineReader reader) {
|
public DefaultHistory(LineReader reader) {
|
||||||
attach(reader);
|
attach(reader);
|
||||||
}
|
}
|
||||||
@ -67,8 +67,7 @@ public class DefaultHistory implements History {
|
|||||||
this.reader = reader;
|
this.reader = reader;
|
||||||
try {
|
try {
|
||||||
load();
|
load();
|
||||||
}
|
} catch (IllegalArgumentException | IOException e) {
|
||||||
catch (IllegalArgumentException | IOException e) {
|
|
||||||
Log.warn("Failed to load history", e);
|
Log.warn("Failed to load history", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,13 +116,13 @@ public class DefaultHistory implements History {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String doHistoryFileDataKey (Path path){
|
private String doHistoryFileDataKey(Path path) {
|
||||||
return path != null ? path.toAbsolutePath().toString() : null;
|
return path != null ? path.toAbsolutePath().toString() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryFileData getHistoryFileData(Path path) {
|
private HistoryFileData getHistoryFileData(Path path) {
|
||||||
String key = doHistoryFileDataKey(path);
|
String key = doHistoryFileDataKey(path);
|
||||||
if (!historyFiles.containsKey(key)){
|
if (!historyFiles.containsKey(key)) {
|
||||||
historyFiles.put(key, new HistoryFileData());
|
historyFiles.put(key, new HistoryFileData());
|
||||||
}
|
}
|
||||||
return historyFiles.get(key);
|
return historyFiles.get(key);
|
||||||
@ -133,7 +132,7 @@ public class DefaultHistory implements History {
|
|||||||
historyFiles.put(doHistoryFileDataKey(path), historyFileData);
|
historyFiles.put(doHistoryFileDataKey(path), historyFileData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLineReaderHistory (Path path) throws IOException {
|
private boolean isLineReaderHistory(Path path) throws IOException {
|
||||||
Path lrp = getPath();
|
Path lrp = getPath();
|
||||||
if (lrp == null) {
|
if (lrp == null) {
|
||||||
return path == null;
|
return path == null;
|
||||||
@ -141,23 +140,23 @@ public class DefaultHistory implements History {
|
|||||||
return Files.isSameFile(lrp, path);
|
return Files.isSameFile(lrp, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLastLoaded(Path path, int lastloaded){
|
private void setLastLoaded(Path path, int lastloaded) {
|
||||||
getHistoryFileData(path).setLastLoaded(lastloaded);
|
getHistoryFileData(path).setLastLoaded(lastloaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setEntriesInFile(Path path, int entriesInFile){
|
private void setEntriesInFile(Path path, int entriesInFile) {
|
||||||
getHistoryFileData(path).setEntriesInFile(entriesInFile);
|
getHistoryFileData(path).setEntriesInFile(entriesInFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void incEntriesInFile(Path path, int amount){
|
private void incEntriesInFile(Path path, int amount) {
|
||||||
getHistoryFileData(path).incEntriesInFile(amount);
|
getHistoryFileData(path).incEntriesInFile(amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getLastLoaded(Path path){
|
private int getLastLoaded(Path path) {
|
||||||
return getHistoryFileData(path).getLastLoaded();
|
return getHistoryFileData(path).getLastLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getEntriesInFile(Path path){
|
private int getEntriesInFile(Path path) {
|
||||||
return getHistoryFileData(path).getEntriesInFile();
|
return getHistoryFileData(path).getEntriesInFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,9 +167,8 @@ public class DefaultHistory implements History {
|
|||||||
protected void addHistoryLine(Path path, String line, boolean checkDuplicates) {
|
protected void addHistoryLine(Path path, String line, boolean checkDuplicates) {
|
||||||
if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
|
if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
|
||||||
int idx = line.indexOf(':');
|
int idx = line.indexOf(':');
|
||||||
final String badHistoryFileSyntax = "Bad history file syntax! " +
|
final String badHistoryFileSyntax = "Bad history file syntax! " + "The history file `" + path
|
||||||
"The history file `" + path + "` may be an older history: " +
|
+ "` may be an older history: " + "please remove it or use a different history file.";
|
||||||
"please remove it or use a different history file.";
|
|
||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
throw new IllegalArgumentException(badHistoryFileSyntax);
|
throw new IllegalArgumentException(badHistoryFileSyntax);
|
||||||
}
|
}
|
||||||
@ -183,8 +181,7 @@ public class DefaultHistory implements History {
|
|||||||
|
|
||||||
String unescaped = unescape(line.substring(idx + 1));
|
String unescaped = unescape(line.substring(idx + 1));
|
||||||
internalAdd(time, unescaped, checkDuplicates);
|
internalAdd(time, unescaped, checkDuplicates);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
internalAdd(Instant.now(), unescape(line), checkDuplicates);
|
internalAdd(Instant.now(), unescape(line), checkDuplicates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,8 +207,7 @@ public class DefaultHistory implements History {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void append(Path file, boolean incremental) throws IOException {
|
public void append(Path file, boolean incremental) throws IOException {
|
||||||
internalWrite(file != null ? file : getPath(),
|
internalWrite(file != null ? file : getPath(), incremental ? getLastLoaded(file) : 0);
|
||||||
incremental ? getLastLoaded(file) : 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -227,8 +223,11 @@ public class DefaultHistory implements History {
|
|||||||
Files.createDirectories(parent);
|
Files.createDirectories(parent);
|
||||||
}
|
}
|
||||||
// Append new items to the history file
|
// Append new items to the history file
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(path.toAbsolutePath(),
|
try (BufferedWriter writer = Files.newBufferedWriter(
|
||||||
StandardOpenOption.WRITE, StandardOpenOption.APPEND, StandardOpenOption.CREATE)) {
|
path.toAbsolutePath(),
|
||||||
|
StandardOpenOption.WRITE,
|
||||||
|
StandardOpenOption.APPEND,
|
||||||
|
StandardOpenOption.CREATE)) {
|
||||||
for (Entry entry : items.subList(from, items.size())) {
|
for (Entry entry : items.subList(from, items.size())) {
|
||||||
if (isPersistable(entry)) {
|
if (isPersistable(entry)) {
|
||||||
writer.append(format(entry));
|
writer.append(format(entry));
|
||||||
@ -248,18 +247,23 @@ public class DefaultHistory implements History {
|
|||||||
Log.trace("Trimming history path: ", path);
|
Log.trace("Trimming history path: ", path);
|
||||||
// Load all history entries
|
// Load all history entries
|
||||||
LinkedList<Entry> allItems = new LinkedList<>();
|
LinkedList<Entry> allItems = new LinkedList<>();
|
||||||
try (BufferedReader reader = Files.newBufferedReader(path)) {
|
try (BufferedReader historyFileReader = Files.newBufferedReader(path)) {
|
||||||
reader.lines().forEach(l -> {
|
historyFileReader.lines().forEach(l -> {
|
||||||
|
if (reader.isSet(LineReader.Option.HISTORY_TIMESTAMPED)) {
|
||||||
int idx = l.indexOf(':');
|
int idx = l.indexOf(':');
|
||||||
Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx)));
|
Instant time = Instant.ofEpochMilli(Long.parseLong(l.substring(0, idx)));
|
||||||
String line = unescape(l.substring(idx + 1));
|
String line = unescape(l.substring(idx + 1));
|
||||||
allItems.add(createEntry(allItems.size(), time, line));
|
allItems.add(createEntry(allItems.size(), time, line));
|
||||||
|
} else {
|
||||||
|
allItems.add(createEntry(allItems.size(), Instant.now(), unescape(l)));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Remove duplicates
|
// Remove duplicates
|
||||||
List<Entry> trimmedItems = doTrimHistory(allItems, max);
|
List<Entry> trimmedItems = doTrimHistory(allItems, max);
|
||||||
// Write history
|
// Write history
|
||||||
Path temp = Files.createTempFile(path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp");
|
Path temp = Files.createTempFile(
|
||||||
|
path.toAbsolutePath().getParent(), path.getFileName().toString(), ".tmp");
|
||||||
try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) {
|
try (BufferedWriter writer = Files.newBufferedWriter(temp, StandardOpenOption.WRITE)) {
|
||||||
for (Entry entry : trimmedItems) {
|
for (Entry entry : trimmedItems) {
|
||||||
writer.append(format(entry));
|
writer.append(format(entry));
|
||||||
@ -351,7 +355,7 @@ public class DefaultHistory implements History {
|
|||||||
public String get(final int index) {
|
public String get(final int index) {
|
||||||
int idx = index - offset;
|
int idx = index - offset;
|
||||||
if (idx >= items.size() || idx < 0) {
|
if (idx >= items.size() || idx < 0) {
|
||||||
throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx +", Size:" + items.size());
|
throw new IllegalArgumentException("IndexOutOfBounds: Index:" + idx + ", Size:" + items.size());
|
||||||
}
|
}
|
||||||
return items.get(idx).line();
|
return items.get(idx).line();
|
||||||
}
|
}
|
||||||
@ -382,8 +386,7 @@ public class DefaultHistory implements History {
|
|||||||
if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) {
|
if (isSet(reader, LineReader.Option.HISTORY_INCREMENTAL)) {
|
||||||
try {
|
try {
|
||||||
save();
|
save();
|
||||||
}
|
} catch (IOException e) {
|
||||||
catch (IOException e) {
|
|
||||||
Log.warn("Failed to save history", e);
|
Log.warn("Failed to save history", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -417,7 +420,7 @@ public class DefaultHistory implements History {
|
|||||||
protected void internalAdd(Instant time, String line, boolean checkDuplicates) {
|
protected void internalAdd(Instant time, String line, boolean checkDuplicates) {
|
||||||
Entry entry = new EntryImpl(offset + items.size(), time, line);
|
Entry entry = new EntryImpl(offset + items.size(), time, line);
|
||||||
if (checkDuplicates) {
|
if (checkDuplicates) {
|
||||||
for (Entry e: items) {
|
for (Entry e : items) {
|
||||||
if (e.line().trim().equals(line.trim())) {
|
if (e.line().trim().equals(line.trim())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -430,7 +433,7 @@ public class DefaultHistory implements History {
|
|||||||
private void maybeResize() {
|
private void maybeResize() {
|
||||||
while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) {
|
while (size() > getInt(reader, LineReader.HISTORY_SIZE, DEFAULT_HISTORY_SIZE)) {
|
||||||
items.removeFirst();
|
items.removeFirst();
|
||||||
for (HistoryFileData hfd: historyFiles.values()) {
|
for (HistoryFileData hfd : historyFiles.values()) {
|
||||||
hfd.decLastLoaded();
|
hfd.decLastLoaded();
|
||||||
}
|
}
|
||||||
offset++;
|
offset++;
|
||||||
@ -633,8 +636,7 @@ public class DefaultHistory implements History {
|
|||||||
private int lastLoaded = 0;
|
private int lastLoaded = 0;
|
||||||
private int entriesInFile = 0;
|
private int entriesInFile = 0;
|
||||||
|
|
||||||
public HistoryFileData() {
|
public HistoryFileData() {}
|
||||||
}
|
|
||||||
|
|
||||||
public HistoryFileData(int lastLoaded, int entriesInFile) {
|
public HistoryFileData(int lastLoaded, int entriesInFile) {
|
||||||
this.lastLoaded = lastLoaded;
|
this.lastLoaded = lastLoaded;
|
||||||
@ -667,8 +669,5 @@ public class DefaultHistory implements History {
|
|||||||
public void incEntriesInFile(int amount) {
|
public void incEntriesInFile(int amount) {
|
||||||
entriesInFile = entriesInFile + amount;
|
entriesInFile = entriesInFile + amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -56,7 +56,9 @@ public class Attributes {
|
|||||||
IXOFF, /* enable input flow control */
|
IXOFF, /* enable input flow control */
|
||||||
IXANY, /* any char will restart after stop */
|
IXANY, /* any char will restart after stop */
|
||||||
IMAXBEL, /* ring bell on input queue full */
|
IMAXBEL, /* ring bell on input queue full */
|
||||||
IUTF8 /* maintain state for UTF-8 VERASE */
|
IUTF8, /* maintain state for UTF-8 VERASE */
|
||||||
|
|
||||||
|
INORMEOL /* normalize end-of-line */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -135,9 +137,9 @@ public class Attributes {
|
|||||||
final EnumSet<LocalFlag> lflag = EnumSet.noneOf(LocalFlag.class);
|
final EnumSet<LocalFlag> lflag = EnumSet.noneOf(LocalFlag.class);
|
||||||
final EnumMap<ControlChar, Integer> cchars = new EnumMap<>(ControlChar.class);
|
final EnumMap<ControlChar, Integer> cchars = new EnumMap<>(ControlChar.class);
|
||||||
|
|
||||||
public Attributes() {
|
public Attributes() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
@SuppressWarnings("this-escape")
|
||||||
public Attributes(Attributes attr) {
|
public Attributes(Attributes attr) {
|
||||||
copy(attr);
|
copy(attr);
|
||||||
}
|
}
|
||||||
@ -310,13 +312,12 @@ public class Attributes {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Attributes[" +
|
return "Attributes[" + "lflags: "
|
||||||
"lflags: " + append(lflag) + ", " +
|
+ append(lflag) + ", " + "iflags: "
|
||||||
"iflags: " + append(iflag) + ", " +
|
+ append(iflag) + ", " + "oflags: "
|
||||||
"oflags: " + append(oflag) + ", " +
|
+ append(oflag) + ", " + "cflags: "
|
||||||
"cflags: " + append(cflag) + ", " +
|
+ append(cflag) + ", " + "cchars: "
|
||||||
"cchars: " + append(EnumSet.allOf(ControlChar.class), this::display) +
|
+ append(EnumSet.allOf(ControlChar.class), this::display) + "]";
|
||||||
"]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String display(ControlChar c) {
|
private String display(ControlChar c) {
|
||||||
@ -345,5 +346,4 @@ public class Attributes {
|
|||||||
private <T extends Enum<T>> String append(EnumSet<T> set, Function<T, String> toString) {
|
private <T extends Enum<T>> String append(EnumSet<T> set, Function<T, String> toString) {
|
||||||
return set.stream().map(toString).collect(Collectors.joining(" "));
|
return set.stream().map(toString).collect(Collectors.joining(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -71,12 +71,11 @@ public class MouseEvent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MouseEvent[" +
|
return "MouseEvent[" + "type="
|
||||||
"type=" + type +
|
+ type + ", button="
|
||||||
", button=" + button +
|
+ button + ", modifiers="
|
||||||
", modifiers=" + modifiers +
|
+ modifiers + ", x="
|
||||||
", x=" + x +
|
+ x + ", y="
|
||||||
", y=" + y +
|
+ y + ']';
|
||||||
']';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -13,9 +13,9 @@ public class Size {
|
|||||||
private int rows;
|
private int rows;
|
||||||
private int cols;
|
private int cols;
|
||||||
|
|
||||||
public Size() {
|
public Size() {}
|
||||||
}
|
|
||||||
|
|
||||||
|
@SuppressWarnings("this-escape")
|
||||||
public Size(int columns, int rows) {
|
public Size(int columns, int rows) {
|
||||||
this();
|
this();
|
||||||
setColumns(columns);
|
setColumns(columns);
|
||||||
@ -50,7 +50,7 @@ public class Size {
|
|||||||
* @return the cursor position
|
* @return the cursor position
|
||||||
*/
|
*/
|
||||||
public int cursorPos(int row, int col) {
|
public int cursorPos(int row, int col) {
|
||||||
return row * (cols+1) + col;
|
return row * (cols + 1) + col;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copy(Size size) {
|
public void copy(Size size) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -34,6 +34,7 @@ public interface Terminal extends Closeable, Flushable {
|
|||||||
* Type used for dumb terminals.
|
* Type used for dumb terminals.
|
||||||
*/
|
*/
|
||||||
String TYPE_DUMB = "dumb";
|
String TYPE_DUMB = "dumb";
|
||||||
|
|
||||||
String TYPE_DUMB_COLOR = "dumb-color";
|
String TYPE_DUMB_COLOR = "dumb-color";
|
||||||
|
|
||||||
String getName();
|
String getName();
|
||||||
@ -42,6 +43,9 @@ public interface Terminal extends Closeable, Flushable {
|
|||||||
// Signal support
|
// Signal support
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types of signals.
|
||||||
|
*/
|
||||||
enum Signal {
|
enum Signal {
|
||||||
INT,
|
INT,
|
||||||
QUIT,
|
QUIT,
|
||||||
@ -51,16 +55,55 @@ public interface Terminal extends Closeable, Flushable {
|
|||||||
WINCH
|
WINCH
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SignalHandler defines the interface used to trap signals and perform specific behaviors.
|
||||||
|
* @see Terminal.Signal
|
||||||
|
* @see Terminal#handle(Signal, SignalHandler)
|
||||||
|
*/
|
||||||
interface SignalHandler {
|
interface SignalHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SIG_DFL} value can be used to specify that the JVM default behavior
|
||||||
|
* should be used to handle this signal.
|
||||||
|
*/
|
||||||
SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL;
|
SignalHandler SIG_DFL = NativeSignalHandler.SIG_DFL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code SIG_IGN} value can be used to ignore this signal and not perform
|
||||||
|
* any special processing.
|
||||||
|
*/
|
||||||
SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN;
|
SignalHandler SIG_IGN = NativeSignalHandler.SIG_IGN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the signal.
|
||||||
|
* @param signal the signal
|
||||||
|
*/
|
||||||
void handle(Signal signal);
|
void handle(Signal signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a handler for the given {@link Signal}.
|
||||||
|
* <p>
|
||||||
|
* Note that the JVM does not easily allow catching the {@link Signal#QUIT} signal, which causes a thread dump
|
||||||
|
* to be displayed. This signal is mainly used when connecting through an SSH socket to a virtual terminal.
|
||||||
|
*
|
||||||
|
* @param signal the signal to register a handler for
|
||||||
|
* @param handler the handler
|
||||||
|
* @return the previous signal handler
|
||||||
|
*/
|
||||||
SignalHandler handle(Signal signal, SignalHandler handler);
|
SignalHandler handle(Signal signal, SignalHandler handler);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raise the specific signal.
|
||||||
|
* This is not method usually called by non system terminals.
|
||||||
|
* When accessing a terminal through a SSH or Telnet connection, signals may be
|
||||||
|
* conveyed by the protocol and thus need to be raised when reaching the terminal code.
|
||||||
|
* The terminals do that automatically when the terminal input stream has a character
|
||||||
|
* mapped to {@link Attributes.ControlChar#VINTR}, {@link Attributes.ControlChar#VQUIT},
|
||||||
|
* or {@link Attributes.ControlChar#VSUSP}.
|
||||||
|
*
|
||||||
|
* @param signal the signal to raise
|
||||||
|
*/
|
||||||
void raise(Signal signal);
|
void raise(Signal signal);
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -180,8 +223,21 @@ public interface Terminal extends Closeable, Flushable {
|
|||||||
|
|
||||||
boolean echo(boolean echo);
|
boolean echo(boolean echo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the terminal attributes.
|
||||||
|
* The returned object can be safely modified
|
||||||
|
* further used in a call to {@link #setAttributes(Attributes)}.
|
||||||
|
*
|
||||||
|
* @return the terminal attributes.
|
||||||
|
*/
|
||||||
Attributes getAttributes();
|
Attributes getAttributes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the terminal attributes.
|
||||||
|
* The terminal will perform a copy of the given attributes.
|
||||||
|
*
|
||||||
|
* @param attr the new attributes
|
||||||
|
*/
|
||||||
void setAttributes(Attributes attr);
|
void setAttributes(Attributes attr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -334,5 +390,4 @@ public interface Terminal extends Closeable, Flushable {
|
|||||||
* Color support
|
* Color support
|
||||||
*/
|
*/
|
||||||
ColorPalette getPalette();
|
ColorPalette getPalette();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,9 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal;
|
package jdk.internal.org.jline.terminal;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -19,11 +16,16 @@ import java.nio.charset.Charset;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.charset.UnsupportedCharsetException;
|
import java.nio.charset.UnsupportedCharsetException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -31,8 +33,10 @@ import java.util.stream.Stream;
|
|||||||
|
|
||||||
import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal;
|
import jdk.internal.org.jline.terminal.impl.AbstractPosixTerminal;
|
||||||
import jdk.internal.org.jline.terminal.impl.AbstractTerminal;
|
import jdk.internal.org.jline.terminal.impl.AbstractTerminal;
|
||||||
import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
|
|
||||||
import jdk.internal.org.jline.terminal.impl.DumbTerminal;
|
import jdk.internal.org.jline.terminal.impl.DumbTerminal;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.DumbTerminalProvider;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalExt;
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.Log;
|
import jdk.internal.org.jline.utils.Log;
|
||||||
import jdk.internal.org.jline.utils.OSUtils;
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
@ -49,16 +53,30 @@ public final class TerminalBuilder {
|
|||||||
public static final String PROP_ENCODING = "org.jline.terminal.encoding";
|
public static final String PROP_ENCODING = "org.jline.terminal.encoding";
|
||||||
public static final String PROP_CODEPAGE = "org.jline.terminal.codepage";
|
public static final String PROP_CODEPAGE = "org.jline.terminal.codepage";
|
||||||
public static final String PROP_TYPE = "org.jline.terminal.type";
|
public static final String PROP_TYPE = "org.jline.terminal.type";
|
||||||
public static final String PROP_JNA = "org.jline.terminal.jna";
|
public static final String PROP_PROVIDER = "org.jline.terminal.provider";
|
||||||
public static final String PROP_JANSI = "org.jline.terminal.jansi";
|
public static final String PROP_PROVIDERS = "org.jline.terminal.providers";
|
||||||
public static final String PROP_EXEC = "org.jline.terminal.exec";
|
public static final String PROP_PROVIDER_FFM = "ffm";
|
||||||
public static final String PROP_DUMB = "org.jline.terminal.dumb";
|
public static final String PROP_PROVIDER_JNI = "jni";
|
||||||
|
public static final String PROP_PROVIDER_JANSI = "jansi";
|
||||||
|
public static final String PROP_PROVIDER_JNA = "jna";
|
||||||
|
public static final String PROP_PROVIDER_EXEC = "exec";
|
||||||
|
public static final String PROP_PROVIDER_DUMB = "dumb";
|
||||||
|
public static final String PROP_PROVIDERS_DEFAULT = String.join(
|
||||||
|
",", PROP_PROVIDER_FFM, PROP_PROVIDER_JNI, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC);
|
||||||
|
public static final String PROP_FFM = "org.jline.terminal." + PROP_PROVIDER_FFM;
|
||||||
|
public static final String PROP_JNI = "org.jline.terminal." + PROP_PROVIDER_JNI;
|
||||||
|
public static final String PROP_JANSI = "org.jline.terminal." + PROP_PROVIDER_JANSI;
|
||||||
|
public static final String PROP_JNA = "org.jline.terminal." + PROP_PROVIDER_JNA;
|
||||||
|
public static final String PROP_EXEC = "org.jline.terminal." + PROP_PROVIDER_EXEC;
|
||||||
|
public static final String PROP_DUMB = "org.jline.terminal." + PROP_PROVIDER_DUMB;
|
||||||
public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color";
|
public static final String PROP_DUMB_COLOR = "org.jline.terminal.dumb.color";
|
||||||
public static final String PROP_OUTPUT = "org.jline.terminal.output";
|
public static final String PROP_OUTPUT = "org.jline.terminal.output";
|
||||||
public static final String PROP_OUTPUT_OUT = "out";
|
public static final String PROP_OUTPUT_OUT = "out";
|
||||||
public static final String PROP_OUTPUT_ERR = "err";
|
public static final String PROP_OUTPUT_ERR = "err";
|
||||||
public static final String PROP_OUTPUT_OUT_ERR = "out-err";
|
public static final String PROP_OUTPUT_OUT_ERR = "out-err";
|
||||||
public static final String PROP_OUTPUT_ERR_OUT = "err-out";
|
public static final String PROP_OUTPUT_ERR_OUT = "err-out";
|
||||||
|
public static final String PROP_OUTPUT_FORCED_OUT = "forced-out";
|
||||||
|
public static final String PROP_OUTPUT_FORCED_ERR = "forced-err";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Other system properties controlling various jline parts
|
// Other system properties controlling various jline parts
|
||||||
@ -68,6 +86,32 @@ public final class TerminalBuilder {
|
|||||||
public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance";
|
public static final String PROP_COLOR_DISTANCE = "org.jline.utils.colorDistance";
|
||||||
public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset";
|
public static final String PROP_DISABLE_ALTERNATE_CHARSET = "org.jline.utils.disableAlternateCharset";
|
||||||
|
|
||||||
|
//
|
||||||
|
// System properties controlling how FileDescriptor are create.
|
||||||
|
// The value can be a comma separated list of defined mechanisms.
|
||||||
|
//
|
||||||
|
public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE = "org.jline.terminal.pty.fileDescriptorCreationMode";
|
||||||
|
public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE = "native";
|
||||||
|
public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION = "reflection";
|
||||||
|
public static final String PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT =
|
||||||
|
String.join(",", PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION, PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE);
|
||||||
|
|
||||||
|
//
|
||||||
|
// System properties controlling how RedirectPipe are created.
|
||||||
|
// The value can be a comma separated list of defined mechanisms.
|
||||||
|
//
|
||||||
|
public static final String PROP_REDIRECT_PIPE_CREATION_MODE = "org.jline.terminal.exec.redirectPipeCreationMode";
|
||||||
|
public static final String PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE = "native";
|
||||||
|
public static final String PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION = "reflection";
|
||||||
|
public static final String PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT =
|
||||||
|
String.join(",", PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION, PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE);
|
||||||
|
|
||||||
|
public static final Set<String> DEPRECATED_PROVIDERS =
|
||||||
|
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(PROP_PROVIDER_JNA, PROP_PROVIDER_JANSI)));
|
||||||
|
|
||||||
|
public static final String PROP_DISABLE_DEPRECATED_PROVIDER_WARNING =
|
||||||
|
"org.jline.terminal.disableDeprecatedProviderWarning";
|
||||||
|
|
||||||
//
|
//
|
||||||
// Terminal output control
|
// Terminal output control
|
||||||
//
|
//
|
||||||
@ -75,7 +119,9 @@ public final class TerminalBuilder {
|
|||||||
SysOut,
|
SysOut,
|
||||||
SysErr,
|
SysErr,
|
||||||
SysOutOrSysErr,
|
SysOutOrSysErr,
|
||||||
SysErrOrSysOut
|
SysErrOrSysOut,
|
||||||
|
ForcedSysOut,
|
||||||
|
ForcedSysErr
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,20 +161,23 @@ public final class TerminalBuilder {
|
|||||||
private int codepage;
|
private int codepage;
|
||||||
private Boolean system;
|
private Boolean system;
|
||||||
private SystemOutput systemOutput;
|
private SystemOutput systemOutput;
|
||||||
|
private String provider;
|
||||||
|
private String providers;
|
||||||
private Boolean jna;
|
private Boolean jna;
|
||||||
private Boolean jansi;
|
private Boolean jansi;
|
||||||
|
private Boolean jni;
|
||||||
private Boolean exec;
|
private Boolean exec;
|
||||||
|
private Boolean ffm;
|
||||||
private Boolean dumb;
|
private Boolean dumb;
|
||||||
private Boolean color;
|
private Boolean color;
|
||||||
private Attributes attributes;
|
private Attributes attributes;
|
||||||
private Size size;
|
private Size size;
|
||||||
private boolean nativeSignals = false;
|
private boolean nativeSignals = true;
|
||||||
private Function<InputStream, InputStream> inputStreamWrapper = in -> in;
|
private Function<InputStream, InputStream> inputStreamWrapper = in -> in;
|
||||||
private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL;
|
private Terminal.SignalHandler signalHandler = Terminal.SignalHandler.SIG_DFL;
|
||||||
private boolean paused = false;
|
private boolean paused = false;
|
||||||
|
|
||||||
private TerminalBuilder() {
|
private TerminalBuilder() {}
|
||||||
}
|
|
||||||
|
|
||||||
public TerminalBuilder name(String name) {
|
public TerminalBuilder name(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -160,6 +209,16 @@ public final class TerminalBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TerminalBuilder provider(String provider) {
|
||||||
|
this.provider = provider;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TerminalBuilder providers(String providers) {
|
||||||
|
this.providers = providers;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TerminalBuilder jna(boolean jna) {
|
public TerminalBuilder jna(boolean jna) {
|
||||||
this.jna = jna;
|
this.jna = jna;
|
||||||
return this;
|
return this;
|
||||||
@ -170,11 +229,21 @@ public final class TerminalBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TerminalBuilder jni(boolean jni) {
|
||||||
|
this.jni = jni;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TerminalBuilder exec(boolean exec) {
|
public TerminalBuilder exec(boolean exec) {
|
||||||
this.exec = exec;
|
this.exec = exec;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TerminalBuilder ffm(boolean ffm) {
|
||||||
|
this.ffm = ffm;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TerminalBuilder dumb(boolean dumb) {
|
public TerminalBuilder dumb(boolean dumb) {
|
||||||
this.dumb = dumb;
|
this.dumb = dumb;
|
||||||
return this;
|
return this;
|
||||||
@ -280,6 +349,12 @@ public final class TerminalBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines the default value for signal handlers.
|
||||||
|
* All signals will be mapped to the given handler.
|
||||||
|
* @param signalHandler the default signal handler
|
||||||
|
* @return The builder
|
||||||
|
*/
|
||||||
public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) {
|
public TerminalBuilder signalHandler(Terminal.SignalHandler signalHandler) {
|
||||||
this.signalHandler = signalHandler;
|
this.signalHandler = signalHandler;
|
||||||
return this;
|
return this;
|
||||||
@ -305,6 +380,11 @@ public final class TerminalBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the terminal.
|
||||||
|
* @return the newly created terminal, never {@code null}
|
||||||
|
* @throws IOException if an error occurs
|
||||||
|
*/
|
||||||
public Terminal build() throws IOException {
|
public Terminal build() throws IOException {
|
||||||
Terminal override = TERMINAL_OVERRIDE.get();
|
Terminal override = TERMINAL_OVERRIDE.get();
|
||||||
Terminal terminal = override != null ? override : doBuild();
|
Terminal terminal = override != null ? override : doBuild();
|
||||||
@ -313,7 +393,8 @@ public final class TerminalBuilder {
|
|||||||
}
|
}
|
||||||
Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName());
|
Log.debug(() -> "Using terminal " + terminal.getClass().getSimpleName());
|
||||||
if (terminal instanceof AbstractPosixTerminal) {
|
if (terminal instanceof AbstractPosixTerminal) {
|
||||||
Log.debug(() -> "Using pty " + ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName());
|
Log.debug(() -> "Using pty "
|
||||||
|
+ ((AbstractPosixTerminal) terminal).getPty().getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
return terminal;
|
return terminal;
|
||||||
}
|
}
|
||||||
@ -323,6 +404,242 @@ public final class TerminalBuilder {
|
|||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = "JLine terminal";
|
name = "JLine terminal";
|
||||||
}
|
}
|
||||||
|
Charset encoding = computeEncoding();
|
||||||
|
String type = computeType();
|
||||||
|
|
||||||
|
String provider = this.provider;
|
||||||
|
if (provider == null) {
|
||||||
|
provider = System.getProperty(PROP_PROVIDER, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean forceDumb =
|
||||||
|
(DumbTerminal.TYPE_DUMB.equals(type) || type != null && type.startsWith(DumbTerminal.TYPE_DUMB_COLOR))
|
||||||
|
|| (provider != null && provider.equals(PROP_PROVIDER_DUMB));
|
||||||
|
Boolean dumb = this.dumb;
|
||||||
|
if (dumb == null) {
|
||||||
|
dumb = getBoolean(PROP_DUMB, null);
|
||||||
|
}
|
||||||
|
IllegalStateException exception = new IllegalStateException("Unable to create a terminal");
|
||||||
|
List<TerminalProvider> providers = getProviders(provider, exception);
|
||||||
|
Terminal terminal = null;
|
||||||
|
if ((system != null && system) || (system == null && in == null && out == null)) {
|
||||||
|
if (system != null
|
||||||
|
&& ((in != null && !in.equals(System.in))
|
||||||
|
|| (out != null && !out.equals(System.out) && !out.equals(System.err)))) {
|
||||||
|
throw new IllegalArgumentException("Cannot create a system terminal using non System streams");
|
||||||
|
}
|
||||||
|
if (attributes != null || size != null) {
|
||||||
|
Log.warn("Attributes and size fields are ignored when creating a system terminal");
|
||||||
|
}
|
||||||
|
SystemOutput systemOutput = computeSystemOutput();
|
||||||
|
Map<SystemStream, Boolean> system = Stream.of(SystemStream.values())
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream))));
|
||||||
|
SystemStream systemStream = select(system, systemOutput);
|
||||||
|
|
||||||
|
if (!forceDumb && system.get(SystemStream.Input) && systemStream != null) {
|
||||||
|
if (attributes != null || size != null) {
|
||||||
|
Log.warn("Attributes and size fields are ignored when creating a system terminal");
|
||||||
|
}
|
||||||
|
boolean ansiPassThrough = OSUtils.IS_CONEMU;
|
||||||
|
// Cygwin defaults to XTERM, but actually supports 256 colors,
|
||||||
|
// so if the value comes from the environment, change it to xterm-256color
|
||||||
|
if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM)
|
||||||
|
&& "xterm".equals(type)
|
||||||
|
&& this.type == null
|
||||||
|
&& System.getProperty(PROP_TYPE) == null) {
|
||||||
|
type = "xterm-256color";
|
||||||
|
}
|
||||||
|
for (TerminalProvider prov : providers) {
|
||||||
|
if (terminal == null) {
|
||||||
|
try {
|
||||||
|
terminal = prov.sysTerminal(
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
ansiPassThrough,
|
||||||
|
encoding,
|
||||||
|
nativeSignals,
|
||||||
|
signalHandler,
|
||||||
|
paused,
|
||||||
|
systemStream,
|
||||||
|
inputStreamWrapper);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t);
|
||||||
|
exception.addSuppressed(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (terminal == null && OSUtils.IS_WINDOWS && providers.isEmpty() && (dumb == null || !dumb)) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Unable to create a system terminal. On Windows, either JLine's native libraries, JNA "
|
||||||
|
+ "or Jansi library is required. Make sure to add one of those in the classpath.",
|
||||||
|
exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (terminal instanceof AbstractTerminal) {
|
||||||
|
AbstractTerminal t = (AbstractTerminal) terminal;
|
||||||
|
if (SYSTEM_TERMINAL.compareAndSet(null, t)) {
|
||||||
|
t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null));
|
||||||
|
} else {
|
||||||
|
exception.addSuppressed(new IllegalStateException("A system terminal is already running. "
|
||||||
|
+ "Make sure to use the created system Terminal on the LineReaderBuilder if you're using one "
|
||||||
|
+ "or that previously created system Terminals have been correctly closed."));
|
||||||
|
terminal.close();
|
||||||
|
terminal = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (terminal == null && (forceDumb || dumb == null || dumb)) {
|
||||||
|
if (!forceDumb && dumb == null) {
|
||||||
|
if (Log.isDebugEnabled()) {
|
||||||
|
Log.warn("input is tty: " + system.get(SystemStream.Input));
|
||||||
|
Log.warn("output is tty: " + system.get(SystemStream.Output));
|
||||||
|
Log.warn("error is tty: " + system.get(SystemStream.Error));
|
||||||
|
Log.warn("Creating a dumb terminal", exception);
|
||||||
|
} else {
|
||||||
|
Log.warn(
|
||||||
|
"Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = getDumbTerminalType(dumb, systemStream);
|
||||||
|
terminal = new DumbTerminalProvider()
|
||||||
|
.sysTerminal(name, type, false, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper);
|
||||||
|
if (OSUtils.IS_WINDOWS) {
|
||||||
|
Attributes attr = terminal.getAttributes();
|
||||||
|
attr.setInputFlag(Attributes.InputFlag.IGNCR, true);
|
||||||
|
terminal.setAttributes(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (TerminalProvider prov : providers) {
|
||||||
|
if (terminal == null) {
|
||||||
|
try {
|
||||||
|
terminal = prov.newTerminal(
|
||||||
|
name, type, in, out, encoding, signalHandler, paused, attributes, size);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
Log.debug("Error creating " + prov.name() + " based terminal: ", t.getMessage(), t);
|
||||||
|
exception.addSuppressed(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (terminal == null) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
if (terminal instanceof TerminalExt) {
|
||||||
|
TerminalExt te = (TerminalExt) terminal;
|
||||||
|
if (DEPRECATED_PROVIDERS.contains(te.getProvider().name())
|
||||||
|
&& !getBoolean(PROP_DISABLE_DEPRECATED_PROVIDER_WARNING, false)) {
|
||||||
|
Log.warn("The terminal provider " + te.getProvider().name()
|
||||||
|
+ " has been deprecated, check your configuration. This warning can be disabled by setting the system property "
|
||||||
|
+ PROP_DISABLE_DEPRECATED_PROVIDER_WARNING + " to true.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return terminal;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDumbTerminalType(Boolean dumb, SystemStream systemStream) {
|
||||||
|
// forced colored dumb terminal
|
||||||
|
Boolean color = this.color;
|
||||||
|
if (color == null) {
|
||||||
|
color = getBoolean(PROP_DUMB_COLOR, null);
|
||||||
|
}
|
||||||
|
if (dumb == null) {
|
||||||
|
// detect emacs using the env variable
|
||||||
|
if (color == null) {
|
||||||
|
String emacs = System.getenv("INSIDE_EMACS");
|
||||||
|
if (emacs != null && emacs.contains("comint")) {
|
||||||
|
color = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Intellij Idea
|
||||||
|
if (color == null) {
|
||||||
|
// using the env variable on windows
|
||||||
|
String ideHome = System.getenv("IDE_HOME");
|
||||||
|
if (ideHome != null) {
|
||||||
|
color = true;
|
||||||
|
} else {
|
||||||
|
// using the parent process command on unix/mac
|
||||||
|
String command = getParentProcessCommand();
|
||||||
|
if (command != null && command.endsWith("/idea")) {
|
||||||
|
color = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (color == null) {
|
||||||
|
color = systemStream != null && System.getenv("TERM") != null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (color == null) {
|
||||||
|
color = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SystemOutput computeSystemOutput() {
|
||||||
|
SystemOutput systemOutput = null;
|
||||||
|
if (out != null) {
|
||||||
|
if (out.equals(System.out)) {
|
||||||
|
systemOutput = SystemOutput.SysOut;
|
||||||
|
} else if (out.equals(System.err)) {
|
||||||
|
systemOutput = SystemOutput.SysErr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (systemOutput == null) {
|
||||||
|
systemOutput = this.systemOutput;
|
||||||
|
}
|
||||||
|
if (systemOutput == null) {
|
||||||
|
String str = System.getProperty(PROP_OUTPUT);
|
||||||
|
if (str != null) {
|
||||||
|
switch (str.trim().toLowerCase(Locale.ROOT)) {
|
||||||
|
case PROP_OUTPUT_OUT:
|
||||||
|
systemOutput = SystemOutput.SysOut;
|
||||||
|
break;
|
||||||
|
case PROP_OUTPUT_ERR:
|
||||||
|
systemOutput = SystemOutput.SysErr;
|
||||||
|
break;
|
||||||
|
case PROP_OUTPUT_OUT_ERR:
|
||||||
|
systemOutput = SystemOutput.SysOutOrSysErr;
|
||||||
|
break;
|
||||||
|
case PROP_OUTPUT_ERR_OUT:
|
||||||
|
systemOutput = SystemOutput.SysErrOrSysOut;
|
||||||
|
break;
|
||||||
|
case PROP_OUTPUT_FORCED_OUT:
|
||||||
|
systemOutput = SystemOutput.ForcedSysOut;
|
||||||
|
break;
|
||||||
|
case PROP_OUTPUT_FORCED_ERR:
|
||||||
|
systemOutput = SystemOutput.ForcedSysErr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: "
|
||||||
|
+ String.join(
|
||||||
|
", ",
|
||||||
|
PROP_OUTPUT_OUT,
|
||||||
|
PROP_OUTPUT_ERR,
|
||||||
|
PROP_OUTPUT_OUT_ERR,
|
||||||
|
PROP_OUTPUT_ERR_OUT)
|
||||||
|
+ ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (systemOutput == null) {
|
||||||
|
systemOutput = SystemOutput.SysOutOrSysErr;
|
||||||
|
}
|
||||||
|
return systemOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String computeType() {
|
||||||
|
String type = this.type;
|
||||||
|
if (type == null) {
|
||||||
|
type = System.getProperty(PROP_TYPE);
|
||||||
|
}
|
||||||
|
if (type == null) {
|
||||||
|
type = System.getenv("TERM");
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Charset computeEncoding() {
|
||||||
Charset encoding = this.encoding;
|
Charset encoding = this.encoding;
|
||||||
if (encoding == null) {
|
if (encoding == null) {
|
||||||
String charsetName = System.getProperty(PROP_ENCODING);
|
String charsetName = System.getProperty(PROP_ENCODING);
|
||||||
@ -344,206 +661,84 @@ public final class TerminalBuilder {
|
|||||||
encoding = StandardCharsets.UTF_8;
|
encoding = StandardCharsets.UTF_8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String type = this.type;
|
return encoding;
|
||||||
if (type == null) {
|
|
||||||
type = System.getProperty(PROP_TYPE);
|
|
||||||
}
|
}
|
||||||
if (type == null) {
|
|
||||||
type = System.getenv("TERM");
|
/**
|
||||||
}
|
* Get the list of available terminal providers.
|
||||||
Boolean jna = this.jna;
|
* This list is sorted according to the {@link #PROP_PROVIDERS} system property.
|
||||||
if (jna == null) {
|
* @param provider if not {@code null}, only this provider will be checked
|
||||||
jna = getBoolean(PROP_JNA, true);
|
* @param exception if a provider throws an exception, it will be added to this exception as a suppressed exception
|
||||||
}
|
* @return a list of terminal providers
|
||||||
Boolean jansi = this.jansi;
|
*/
|
||||||
if (jansi == null) {
|
public List<TerminalProvider> getProviders(String provider, IllegalStateException exception) {
|
||||||
jansi = getBoolean(PROP_JANSI, true);
|
|
||||||
}
|
|
||||||
Boolean exec = this.exec;
|
|
||||||
if (exec == null) {
|
|
||||||
exec = getBoolean(PROP_EXEC, true);
|
|
||||||
}
|
|
||||||
Boolean dumb = this.dumb;
|
|
||||||
if (dumb == null) {
|
|
||||||
dumb = getBoolean(PROP_DUMB, null);
|
|
||||||
}
|
|
||||||
IllegalStateException exception = new IllegalStateException("Unable to create a terminal");
|
|
||||||
List<TerminalProvider> providers = new ArrayList<>();
|
List<TerminalProvider> providers = new ArrayList<>();
|
||||||
if (jna) {
|
// Check ffm provider
|
||||||
|
checkProvider(provider, exception, providers, ffm, PROP_FFM, PROP_PROVIDER_FFM);
|
||||||
|
// Check jni provider
|
||||||
|
checkProvider(provider, exception, providers, jni, PROP_JNI, PROP_PROVIDER_JNI);
|
||||||
|
// Check jansi provider
|
||||||
|
checkProvider(provider, exception, providers, jansi, PROP_JANSI, PROP_PROVIDER_JANSI);
|
||||||
|
// Check jna provider
|
||||||
|
checkProvider(provider, exception, providers, jna, PROP_JNA, PROP_PROVIDER_JNA);
|
||||||
|
// Check exec provider
|
||||||
|
checkProvider(provider, exception, providers, exec, PROP_EXEC, PROP_PROVIDER_EXEC);
|
||||||
|
// Order providers
|
||||||
|
List<String> order = Arrays.asList(
|
||||||
|
(this.providers != null ? this.providers : System.getProperty(PROP_PROVIDERS, PROP_PROVIDERS_DEFAULT))
|
||||||
|
.split(","));
|
||||||
|
providers.sort(Comparator.comparing(l -> {
|
||||||
|
int idx = order.indexOf(l.name());
|
||||||
|
return idx >= 0 ? idx : Integer.MAX_VALUE;
|
||||||
|
}));
|
||||||
|
String names = providers.stream().map(TerminalProvider::name).collect(Collectors.joining(", "));
|
||||||
|
Log.debug("Available providers: " + names);
|
||||||
|
return providers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkProvider(
|
||||||
|
String provider,
|
||||||
|
IllegalStateException exception,
|
||||||
|
List<TerminalProvider> providers,
|
||||||
|
Boolean load,
|
||||||
|
String property,
|
||||||
|
String name) {
|
||||||
|
Boolean doLoad = provider != null ? (Boolean) name.equals(provider) : load;
|
||||||
|
if (doLoad == null) {
|
||||||
|
doLoad = getBoolean(property, true);
|
||||||
|
}
|
||||||
|
if (doLoad) {
|
||||||
try {
|
try {
|
||||||
TerminalProvider provider = TerminalProvider.load("jna");
|
TerminalProvider prov = TerminalProvider.load(name);
|
||||||
providers.add(provider);
|
prov.isSystemStream(SystemStream.Output);
|
||||||
|
providers.add(prov);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
Log.debug("Unable to load JNA support: ", t);
|
Log.debug("Unable to load " + name + " provider: ", t);
|
||||||
exception.addSuppressed(t);
|
exception.addSuppressed(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (jansi) {
|
|
||||||
try {
|
|
||||||
TerminalProvider provider = TerminalProvider.load("jansi");
|
|
||||||
providers.add(provider);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.debug("Unable to load JANSI support: ", t);
|
|
||||||
exception.addSuppressed(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exec)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
TerminalProvider provider = TerminalProvider.load("exec");
|
|
||||||
providers.add(provider);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.debug("Unable to load EXEC support: ", t);
|
|
||||||
exception.addSuppressed(t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Terminal terminal = null;
|
private SystemStream select(Map<SystemStream, Boolean> system, SystemOutput systemOutput) {
|
||||||
if ((system != null && system) || (system == null && in == null && out == null)) {
|
|
||||||
if (system != null && ((in != null && !in.equals(System.in)) ||
|
|
||||||
(out != null && !out.equals(System.out) && !out.equals(System.err)))) {
|
|
||||||
throw new IllegalArgumentException("Cannot create a system terminal using non System streams");
|
|
||||||
}
|
|
||||||
if (attributes != null || size != null) {
|
|
||||||
Log.warn("Attributes and size fields are ignored when creating a system terminal");
|
|
||||||
}
|
|
||||||
if (out != null) {
|
|
||||||
if (out.equals(System.out)) {
|
|
||||||
systemOutput = SystemOutput.SysOut;
|
|
||||||
} else if (out.equals(System.err)) {
|
|
||||||
systemOutput = SystemOutput.SysErr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (systemOutput == null) {
|
|
||||||
String str = System.getProperty(PROP_OUTPUT);
|
|
||||||
if (str != null) {
|
|
||||||
switch (str.trim().toLowerCase(Locale.ROOT)) {
|
|
||||||
case PROP_OUTPUT_OUT: systemOutput = SystemOutput.SysOut; break;
|
|
||||||
case PROP_OUTPUT_ERR: systemOutput = SystemOutput.SysErr; break;
|
|
||||||
case PROP_OUTPUT_OUT_ERR: systemOutput = SystemOutput.SysOutOrSysErr; break;
|
|
||||||
case PROP_OUTPUT_ERR_OUT: systemOutput = SystemOutput.SysErrOrSysOut; break;
|
|
||||||
default:
|
|
||||||
Log.debug("Unsupported value for " + PROP_OUTPUT + ": " + str + ". Supported values are: "
|
|
||||||
+ String.join(", ", PROP_OUTPUT_OUT, PROP_OUTPUT_ERR, PROP_OUTPUT_OUT_ERR,PROP_OUTPUT_ERR_OUT)
|
|
||||||
+ ".");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (systemOutput == null) {
|
|
||||||
systemOutput = SystemOutput.SysOutOrSysErr;
|
|
||||||
}
|
|
||||||
Map<TerminalProvider.Stream, Boolean> system = Stream.of(TerminalProvider.Stream.values())
|
|
||||||
.collect(Collectors.toMap(stream -> stream, stream -> providers.stream().anyMatch(p -> p.isSystemStream(stream))));
|
|
||||||
TerminalProvider.Stream console = select(system, systemOutput);
|
|
||||||
|
|
||||||
if (system.get(TerminalProvider.Stream.Input) && console != null) {
|
|
||||||
if (attributes != null || size != null) {
|
|
||||||
Log.warn("Attributes and size fields are ignored when creating a system terminal");
|
|
||||||
}
|
|
||||||
boolean ansiPassThrough = OSUtils.IS_CONEMU;
|
|
||||||
// Cygwin defaults to XTERM, but actually supports 256 colors,
|
|
||||||
// so if the value comes from the environment, change it to xterm-256color
|
|
||||||
if ((OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) && "xterm".equals(type)
|
|
||||||
&& this.type == null && System.getProperty(PROP_TYPE) == null) {
|
|
||||||
type = "xterm-256color";
|
|
||||||
}
|
|
||||||
for ( TerminalProvider provider : providers) {
|
|
||||||
if (terminal == null) {
|
|
||||||
try {
|
|
||||||
terminal = provider.sysTerminal(name, type, ansiPassThrough, encoding,
|
|
||||||
nativeSignals, signalHandler, paused, console, inputStreamWrapper);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t);
|
|
||||||
exception.addSuppressed(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) {
|
|
||||||
throw new IllegalStateException("Unable to create a system terminal. On windows, either "
|
|
||||||
+ "JNA or JANSI library is required. Make sure to add one of those in the classpath.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (terminal instanceof AbstractTerminal) {
|
|
||||||
AbstractTerminal t = (AbstractTerminal) terminal;
|
|
||||||
if (SYSTEM_TERMINAL.compareAndSet(null, t)) {
|
|
||||||
t.setOnClose(() -> SYSTEM_TERMINAL.compareAndSet(t, null));
|
|
||||||
} else {
|
|
||||||
exception.addSuppressed(new IllegalStateException("A system terminal is already running. " +
|
|
||||||
"Make sure to use the created system Terminal on the LineReaderBuilder if you're using one " +
|
|
||||||
"or that previously created system Terminals have been correctly closed."));
|
|
||||||
terminal.close();
|
|
||||||
terminal = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (terminal == null && (dumb == null || dumb)) {
|
|
||||||
// forced colored dumb terminal
|
|
||||||
Boolean color = this.color;
|
|
||||||
if (color == null) {
|
|
||||||
color = getBoolean(PROP_DUMB_COLOR, false);
|
|
||||||
// detect emacs using the env variable
|
|
||||||
if (!color) {
|
|
||||||
String emacs = System.getenv("INSIDE_EMACS");
|
|
||||||
color = emacs != null && emacs.contains("comint");
|
|
||||||
}
|
|
||||||
// detect Intellij Idea
|
|
||||||
if (!color) {
|
|
||||||
String command = getParentProcessCommand();
|
|
||||||
color = command != null && command.contains("idea");
|
|
||||||
}
|
|
||||||
if (!color) {
|
|
||||||
color = system.get(TerminalProvider.Stream.Output) && System.getenv("TERM") != null;
|
|
||||||
}
|
|
||||||
if (!color && dumb == null) {
|
|
||||||
if (Log.isDebugEnabled()) {
|
|
||||||
Log.warn("input is tty: {}", system.get(TerminalProvider.Stream.Input));
|
|
||||||
Log.warn("output is tty: {}", system.get(TerminalProvider.Stream.Output));
|
|
||||||
Log.warn("error is tty: {}", system.get(TerminalProvider.Stream.Error));
|
|
||||||
Log.warn("Creating a dumb terminal", exception);
|
|
||||||
} else {
|
|
||||||
Log.warn("Unable to create a system terminal, creating a dumb terminal (enable debug logging for more information)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
terminal = new DumbTerminal(name, color ? Terminal.TYPE_DUMB_COLOR : Terminal.TYPE_DUMB,
|
|
||||||
new FileInputStream(FileDescriptor.in),
|
|
||||||
//JDK change: always write into stdout:
|
|
||||||
new FileOutputStream(FileDescriptor.out),
|
|
||||||
encoding, signalHandler);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for ( TerminalProvider provider : providers) {
|
|
||||||
if (terminal == null) {
|
|
||||||
try {
|
|
||||||
terminal = provider.newTerminal(name, type, inputStreamWrapper.apply(in), out, encoding, signalHandler, paused, attributes, size);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Log.debug("Error creating " + provider.name() + " based terminal: ", t.getMessage(), t);
|
|
||||||
exception.addSuppressed(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (terminal == null) {
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
return terminal;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TerminalProvider.Stream select(Map<TerminalProvider.Stream, Boolean> system, SystemOutput systemOutput) {
|
|
||||||
switch (systemOutput) {
|
switch (systemOutput) {
|
||||||
case SysOut:
|
case SysOut:
|
||||||
return select(system, TerminalProvider.Stream.Output);
|
return select(system, SystemStream.Output);
|
||||||
case SysErr:
|
case SysErr:
|
||||||
return select(system, TerminalProvider.Stream.Error);
|
return select(system, SystemStream.Error);
|
||||||
case SysOutOrSysErr:
|
case SysOutOrSysErr:
|
||||||
return select(system, TerminalProvider.Stream.Output, TerminalProvider.Stream.Error);
|
return select(system, SystemStream.Output, SystemStream.Error);
|
||||||
case SysErrOrSysOut:
|
case SysErrOrSysOut:
|
||||||
return select(system, TerminalProvider.Stream.Error, TerminalProvider.Stream.Output);
|
return select(system, SystemStream.Error, SystemStream.Output);
|
||||||
|
case ForcedSysOut:
|
||||||
|
return SystemStream.Output;
|
||||||
|
case ForcedSysErr:
|
||||||
|
return SystemStream.Error;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TerminalProvider.Stream select(Map<TerminalProvider.Stream, Boolean> system, TerminalProvider.Stream... streams) {
|
private static SystemStream select(Map<SystemStream, Boolean> system, SystemStream... streams) {
|
||||||
for (TerminalProvider.Stream s : streams) {
|
for (SystemStream s : streams) {
|
||||||
if (system.get(s)) {
|
if (system.get(s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -558,7 +753,9 @@ public final class TerminalBuilder {
|
|||||||
Object parent = ((Optional<?>) phClass.getMethod("parent").invoke(current)).orElse(null);
|
Object parent = ((Optional<?>) phClass.getMethod("parent").invoke(current)).orElse(null);
|
||||||
Method infoMethod = phClass.getMethod("info");
|
Method infoMethod = phClass.getMethod("info");
|
||||||
Object info = infoMethod.invoke(parent);
|
Object info = infoMethod.invoke(parent);
|
||||||
Object command = ((Optional<?>) infoMethod.getReturnType().getMethod("command").invoke(info)).orElse(null);
|
Object command = ((Optional<?>)
|
||||||
|
infoMethod.getReturnType().getMethod("command").invoke(info))
|
||||||
|
.orElse(null);
|
||||||
return (String) command;
|
return (String) command;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
return null;
|
return null;
|
||||||
@ -583,7 +780,7 @@ public final class TerminalBuilder {
|
|||||||
private static final int UTF8_CODE_PAGE = 65001;
|
private static final int UTF8_CODE_PAGE = 65001;
|
||||||
|
|
||||||
private static Charset getCodepageCharset(int codepage) {
|
private static Charset getCodepageCharset(int codepage) {
|
||||||
//http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
|
// http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
|
||||||
if (codepage == UTF8_CODE_PAGE) {
|
if (codepage == UTF8_CODE_PAGE) {
|
||||||
return StandardCharsets.UTF_8;
|
return StandardCharsets.UTF_8;
|
||||||
}
|
}
|
||||||
@ -630,5 +827,4 @@ public final class TerminalBuilder {
|
|||||||
public static void setTerminalOverride(final Terminal terminal) {
|
public static void setTerminalOverride(final Terminal terminal) {
|
||||||
TERMINAL_OVERRIDE.set(terminal);
|
TERMINAL_OVERRIDE.set(terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -18,6 +18,8 @@ import jdk.internal.org.jline.terminal.Attributes;
|
|||||||
import jdk.internal.org.jline.terminal.Cursor;
|
import jdk.internal.org.jline.terminal.Cursor;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
import jdk.internal.org.jline.terminal.spi.Pty;
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
|
||||||
public abstract class AbstractPosixTerminal extends AbstractTerminal {
|
public abstract class AbstractPosixTerminal extends AbstractTerminal {
|
||||||
|
|
||||||
@ -28,7 +30,8 @@ public abstract class AbstractPosixTerminal extends AbstractTerminal {
|
|||||||
this(name, type, pty, null, SignalHandler.SIG_DFL);
|
this(name, type, pty, null, SignalHandler.SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler) throws IOException {
|
public AbstractPosixTerminal(String name, String type, Pty pty, Charset encoding, SignalHandler signalHandler)
|
||||||
|
throws IOException {
|
||||||
super(name, type, encoding, signalHandler);
|
super(name, type, encoding, signalHandler);
|
||||||
Objects.requireNonNull(pty);
|
Objects.requireNonNull(pty);
|
||||||
this.pty = pty;
|
this.pty = pty;
|
||||||
@ -82,4 +85,13 @@ public abstract class AbstractPosixTerminal extends AbstractTerminal {
|
|||||||
return CursorSupport.getCursorPosition(this, discarded);
|
return CursorSupport.getCursorPosition(this, discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return getPty().getProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemStream getSystemStream() {
|
||||||
|
return getPty().getSystemStream();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2019, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,20 +8,39 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import java.io.FileDescriptor;
|
||||||
import jdk.internal.org.jline.terminal.spi.Pty;
|
import java.io.FilterInputStream;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
|
||||||
|
|
||||||
import java.io.IOError;
|
import java.io.IOError;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InterruptedIOException;
|
import java.io.InterruptedIOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
//import jdk.internal.org.jline.nativ.JLineLibrary;
|
||||||
|
//import jdk.internal.org.jline.nativ.JLineNativeLoader;
|
||||||
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
||||||
|
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE;
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT;
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE;
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION;
|
||||||
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS;
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_NON_BLOCKING_READS;
|
||||||
|
|
||||||
public abstract class AbstractPty implements Pty {
|
public abstract class AbstractPty implements Pty {
|
||||||
|
|
||||||
|
protected final TerminalProvider provider;
|
||||||
|
protected final SystemStream systemStream;
|
||||||
private Attributes current;
|
private Attributes current;
|
||||||
|
private boolean skipNextLf;
|
||||||
|
|
||||||
|
public AbstractPty(TerminalProvider provider, SystemStream systemStream) {
|
||||||
|
this.provider = provider;
|
||||||
|
this.systemStream = systemStream;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAttr(Attributes attr) throws IOException {
|
public void setAttr(Attributes attr) throws IOException {
|
||||||
@ -32,10 +51,32 @@ public abstract class AbstractPty implements Pty {
|
|||||||
@Override
|
@Override
|
||||||
public InputStream getSlaveInput() throws IOException {
|
public InputStream getSlaveInput() throws IOException {
|
||||||
InputStream si = doGetSlaveInput();
|
InputStream si = doGetSlaveInput();
|
||||||
if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) {
|
InputStream nsi = new FilterInputStream(si) {
|
||||||
return new PtyInputStream(si);
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
for (; ; ) {
|
||||||
|
int c = super.read();
|
||||||
|
if (current.getInputFlag(Attributes.InputFlag.INORMEOL)) {
|
||||||
|
if (c == '\r') {
|
||||||
|
skipNextLf = true;
|
||||||
|
c = '\n';
|
||||||
|
} else if (c == '\n') {
|
||||||
|
if (skipNextLf) {
|
||||||
|
skipNextLf = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return si;
|
skipNextLf = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (Boolean.parseBoolean(System.getProperty(PROP_NON_BLOCKING_READS, "true"))) {
|
||||||
|
return new PtyInputStream(nsi);
|
||||||
|
} else {
|
||||||
|
return nsi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +90,16 @@ public abstract class AbstractPty implements Pty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemStream getSystemStream() {
|
||||||
|
return systemStream;
|
||||||
|
}
|
||||||
|
|
||||||
class PtyInputStream extends NonBlockingInputStream {
|
class PtyInputStream extends NonBlockingInputStream {
|
||||||
final InputStream in;
|
final InputStream in;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
@ -102,4 +153,103 @@ public abstract class AbstractPty implements Pty {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static FileDescriptorCreator fileDescriptorCreator;
|
||||||
|
|
||||||
|
protected static FileDescriptor newDescriptor(int fd) {
|
||||||
|
if (fileDescriptorCreator == null) {
|
||||||
|
String str =
|
||||||
|
System.getProperty(PROP_FILE_DESCRIPTOR_CREATION_MODE, PROP_FILE_DESCRIPTOR_CREATION_MODE_DEFAULT);
|
||||||
|
String[] modes = str.split(",");
|
||||||
|
IllegalStateException ise = new IllegalStateException("Unable to create FileDescriptor");
|
||||||
|
for (String mode : modes) {
|
||||||
|
try {
|
||||||
|
switch (mode) {
|
||||||
|
case PROP_FILE_DESCRIPTOR_CREATION_MODE_NATIVE:
|
||||||
|
fileDescriptorCreator = null;//new NativeFileDescriptorCreator();
|
||||||
|
break;
|
||||||
|
case PROP_FILE_DESCRIPTOR_CREATION_MODE_REFLECTION:
|
||||||
|
fileDescriptorCreator = new ReflectionFileDescriptorCreator();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// ignore
|
||||||
|
ise.addSuppressed(t);
|
||||||
|
}
|
||||||
|
if (fileDescriptorCreator != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileDescriptorCreator == null) {
|
||||||
|
throw ise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileDescriptorCreator.newDescriptor(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FileDescriptorCreator {
|
||||||
|
FileDescriptor newDescriptor(int fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class that could be used on OpenJDK 17. However, it requires the following JVM option
|
||||||
|
* --add-exports java.base/jdk.internal.access=ALL-UNNAMED
|
||||||
|
* so the benefit does not seem important enough to warrant the problems caused
|
||||||
|
* by access the jdk.internal.access package at compile time, which itself requires
|
||||||
|
* custom compiler options and a different maven module, or at least a different compile
|
||||||
|
* phase with a JDK 17 compiler.
|
||||||
|
* So, just keep the ReflectionFileDescriptorCreator for now.
|
||||||
|
*
|
||||||
|
static class Jdk17FileDescriptorCreator implements FileDescriptorCreator {
|
||||||
|
private final jdk.internal.access.JavaIOFileDescriptorAccess fdAccess;
|
||||||
|
Jdk17FileDescriptorCreator() {
|
||||||
|
fdAccess = jdk.internal.access.SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileDescriptor newDescriptor(int fd) {
|
||||||
|
FileDescriptor descriptor = new FileDescriptor();
|
||||||
|
fdAccess.set(descriptor, fd);
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflection based file descriptor creator.
|
||||||
|
* This requires the following option
|
||||||
|
* --add-opens java.base/java.io=ALL-UNNAMED
|
||||||
|
*/
|
||||||
|
static class ReflectionFileDescriptorCreator implements FileDescriptorCreator {
|
||||||
|
private final Field fileDescriptorField;
|
||||||
|
|
||||||
|
ReflectionFileDescriptorCreator() throws Exception {
|
||||||
|
Field field = FileDescriptor.class.getDeclaredField("fd");
|
||||||
|
field.setAccessible(true);
|
||||||
|
fileDescriptorField = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileDescriptor newDescriptor(int fd) {
|
||||||
|
FileDescriptor descriptor = new FileDescriptor();
|
||||||
|
try {
|
||||||
|
fileDescriptorField.set(descriptor, fd);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
// This should not happen as the field has been set accessible
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
return descriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static class NativeFileDescriptorCreator implements FileDescriptorCreator {
|
||||||
|
// NativeFileDescriptorCreator() {
|
||||||
|
// // Force load the library
|
||||||
|
// JLineNativeLoader.initialize();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public FileDescriptor newDescriptor(int fd) {
|
||||||
|
// return JLineLibrary.newFileDescriptor(fd);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -27,7 +27,7 @@ import jdk.internal.org.jline.terminal.Attributes.InputFlag;
|
|||||||
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
||||||
import jdk.internal.org.jline.terminal.Cursor;
|
import jdk.internal.org.jline.terminal.Cursor;
|
||||||
import jdk.internal.org.jline.terminal.MouseEvent;
|
import jdk.internal.org.jline.terminal.MouseEvent;
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
import jdk.internal.org.jline.terminal.spi.TerminalExt;
|
||||||
import jdk.internal.org.jline.utils.ColorPalette;
|
import jdk.internal.org.jline.utils.ColorPalette;
|
||||||
import jdk.internal.org.jline.utils.Curses;
|
import jdk.internal.org.jline.utils.Curses;
|
||||||
import jdk.internal.org.jline.utils.InfoCmp;
|
import jdk.internal.org.jline.utils.InfoCmp;
|
||||||
@ -35,7 +35,7 @@ import jdk.internal.org.jline.utils.InfoCmp.Capability;
|
|||||||
import jdk.internal.org.jline.utils.Log;
|
import jdk.internal.org.jline.utils.Log;
|
||||||
import jdk.internal.org.jline.utils.Status;
|
import jdk.internal.org.jline.utils.Status;
|
||||||
|
|
||||||
public abstract class AbstractTerminal implements Terminal {
|
public abstract class AbstractTerminal implements TerminalExt {
|
||||||
|
|
||||||
protected final String name;
|
protected final String name;
|
||||||
protected final String type;
|
protected final String type;
|
||||||
@ -44,7 +44,7 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
protected final Set<Capability> bools = new HashSet<>();
|
protected final Set<Capability> bools = new HashSet<>();
|
||||||
protected final Map<Capability, Integer> ints = new HashMap<>();
|
protected final Map<Capability, Integer> ints = new HashMap<>();
|
||||||
protected final Map<Capability, String> strings = new HashMap<>();
|
protected final Map<Capability, String> strings = new HashMap<>();
|
||||||
protected final ColorPalette palette = new ColorPalette(this);
|
protected final ColorPalette palette;
|
||||||
protected Status status;
|
protected Status status;
|
||||||
protected Runnable onClose;
|
protected Runnable onClose;
|
||||||
|
|
||||||
@ -52,10 +52,13 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
this(name, type, null, SignalHandler.SIG_DFL);
|
this(name, type, null, SignalHandler.SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler) throws IOException {
|
@SuppressWarnings("this-escape")
|
||||||
|
public AbstractTerminal(String name, String type, Charset encoding, SignalHandler signalHandler)
|
||||||
|
throws IOException {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.type = type != null ? type : "ansi";
|
this.type = type != null ? type : "ansi";
|
||||||
this.encoding = encoding != null ? encoding : System.out.charset();
|
this.encoding = encoding != null ? encoding : System.out.charset();
|
||||||
|
this.palette = new ColorPalette(this);
|
||||||
for (Signal signal : Signal.values()) {
|
for (Signal signal : Signal.values()) {
|
||||||
handlers.put(signal, signalHandler);
|
handlers.put(signal, signalHandler);
|
||||||
}
|
}
|
||||||
@ -85,12 +88,13 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
public void raise(Signal signal) {
|
public void raise(Signal signal) {
|
||||||
Objects.requireNonNull(signal);
|
Objects.requireNonNull(signal);
|
||||||
SignalHandler handler = handlers.get(signal);
|
SignalHandler handler = handlers.get(signal);
|
||||||
if (handler != SignalHandler.SIG_DFL && handler != SignalHandler.SIG_IGN) {
|
if (handler == SignalHandler.SIG_DFL) {
|
||||||
handler.handle(signal);
|
|
||||||
}
|
|
||||||
if (status != null && signal == Signal.WINCH) {
|
if (status != null && signal == Signal.WINCH) {
|
||||||
status.resize();
|
status.resize();
|
||||||
}
|
}
|
||||||
|
} else if (handler != SignalHandler.SIG_IGN) {
|
||||||
|
handler.handle(signal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void close() throws IOException {
|
public final void close() throws IOException {
|
||||||
@ -105,8 +109,7 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
|
|
||||||
protected void doClose() throws IOException {
|
protected void doClose() throws IOException {
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
status.update(null);
|
status.close();
|
||||||
flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +129,7 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
if (cc != null) {
|
if (cc != null) {
|
||||||
int vcc = getAttributes().getControlChar(cc);
|
int vcc = getAttributes().getControlChar(cc);
|
||||||
if (vcc > 0 && vcc < 32) {
|
if (vcc > 0 && vcc < 32) {
|
||||||
writer().write(new char[]{'^', (char) (vcc + '@')}, 0, 2);
|
writer().write(new char[] {'^', (char) (vcc + '@')}, 0, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,8 +220,7 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MouseEvent lastMouseEvent = new MouseEvent(
|
private MouseEvent lastMouseEvent = new MouseEvent(
|
||||||
MouseEvent.Type.Moved, MouseEvent.Button.NoButton,
|
MouseEvent.Type.Moved, MouseEvent.Button.NoButton, EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0);
|
||||||
EnumSet.noneOf(MouseEvent.Modifier.class), 0, 0);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasMouseSupport() {
|
public boolean hasMouseSupport() {
|
||||||
@ -268,16 +270,13 @@ public abstract class AbstractTerminal implements Terminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause() {
|
public void pause() {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pause(boolean wait) throws InterruptedException {
|
public void pause(boolean wait) throws InterruptedException {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume() {
|
public void resume() {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean paused() {
|
public boolean paused() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2017, the original author or authors.
|
* Copyright (c) 2002-2017, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -29,11 +29,8 @@ public abstract class AbstractWindowsConsoleWriter extends Writer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2019, the original author or authors.
|
* Copyright (c) 2002-2023, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,8 +8,20 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.Curses;
|
import jdk.internal.org.jline.utils.Curses;
|
||||||
import jdk.internal.org.jline.utils.InfoCmp;
|
import jdk.internal.org.jline.utils.InfoCmp;
|
||||||
import jdk.internal.org.jline.utils.Log;
|
import jdk.internal.org.jline.utils.Log;
|
||||||
@ -21,17 +33,6 @@ import jdk.internal.org.jline.utils.ShutdownHooks;
|
|||||||
import jdk.internal.org.jline.utils.Signals;
|
import jdk.internal.org.jline.utils.Signals;
|
||||||
import jdk.internal.org.jline.utils.WriterOutputStream;
|
import jdk.internal.org.jline.utils.WriterOutputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AbstractWindowsTerminal is used as the base class for windows terminal.
|
* The AbstractWindowsTerminal is used as the base class for windows terminal.
|
||||||
* Due to windows limitations, mostly the missing support for ansi sequences,
|
* Due to windows limitations, mostly the missing support for ansi sequences,
|
||||||
@ -44,7 +45,7 @@ import java.util.function.Function;
|
|||||||
* the writer() becomes the primary output, while the output() is bridged
|
* the writer() becomes the primary output, while the output() is bridged
|
||||||
* to the writer() using a WriterOutputStream wrapper.
|
* to the writer() using a WriterOutputStream wrapper.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
public abstract class AbstractWindowsTerminal<Console> extends AbstractTerminal {
|
||||||
|
|
||||||
public static final String TYPE_WINDOWS = "windows";
|
public static final String TYPE_WINDOWS = "windows";
|
||||||
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
|
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
|
||||||
@ -62,6 +63,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
protected static final int ENABLE_MOUSE_INPUT = 0x0010;
|
protected static final int ENABLE_MOUSE_INPUT = 0x0010;
|
||||||
protected static final int ENABLE_INSERT_MODE = 0x0020;
|
protected static final int ENABLE_INSERT_MODE = 0x0020;
|
||||||
protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040;
|
protected static final int ENABLE_QUICK_EDIT_MODE = 0x0040;
|
||||||
|
protected static final int ENABLE_EXTENDED_FLAGS = 0x0080;
|
||||||
|
|
||||||
protected final Writer slaveInputPipe;
|
protected final Writer slaveInputPipe;
|
||||||
protected final InputStream input;
|
protected final InputStream input;
|
||||||
@ -71,7 +73,12 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
|
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
|
||||||
protected final ShutdownHooks.Task closer;
|
protected final ShutdownHooks.Task closer;
|
||||||
protected final Attributes attributes = new Attributes();
|
protected final Attributes attributes = new Attributes();
|
||||||
protected final int originalConsoleMode;
|
protected final Console inConsole;
|
||||||
|
protected final Console outConsole;
|
||||||
|
protected final int originalInConsoleMode;
|
||||||
|
protected final int originalOutConsoleMode;
|
||||||
|
private final TerminalProvider provider;
|
||||||
|
private final SystemStream systemStream;
|
||||||
|
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
protected boolean paused = true;
|
protected boolean paused = true;
|
||||||
@ -80,18 +87,39 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
protected MouseTracking tracking = MouseTracking.Off;
|
protected MouseTracking tracking = MouseTracking.Off;
|
||||||
protected boolean focusTracking = false;
|
protected boolean focusTracking = false;
|
||||||
private volatile boolean closing;
|
private volatile boolean closing;
|
||||||
|
protected boolean skipNextLf;
|
||||||
|
|
||||||
public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
|
@SuppressWarnings("this-escape")
|
||||||
|
public AbstractWindowsTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Writer writer,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
SignalHandler signalHandler,
|
||||||
|
Console inConsole,
|
||||||
|
int inConsoleMode,
|
||||||
|
Console outConsole,
|
||||||
|
int outConsoleMode,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
super(name, type, encoding, signalHandler);
|
super(name, type, encoding, signalHandler);
|
||||||
|
this.provider = provider;
|
||||||
|
this.systemStream = systemStream;
|
||||||
NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
|
NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
|
||||||
this.slaveInputPipe = reader.getWriter();
|
this.slaveInputPipe = reader.getWriter();
|
||||||
this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding()));
|
this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding()));
|
||||||
this.reader = NonBlocking.nonBlocking(name, input, encoding());
|
this.reader = NonBlocking.nonBlocking(name, input, encoding());
|
||||||
this.writer = new PrintWriter(writer);
|
this.writer = new PrintWriter(writer);
|
||||||
this.output = new WriterOutputStream(writer, encoding());
|
this.output = new WriterOutputStream(writer, encoding());
|
||||||
|
this.inConsole = inConsole;
|
||||||
|
this.outConsole = outConsole;
|
||||||
parseInfoCmp();
|
parseInfoCmp();
|
||||||
// Attributes
|
// Attributes
|
||||||
originalConsoleMode = getConsoleMode();
|
this.originalInConsoleMode = inConsoleMode;
|
||||||
|
this.originalOutConsoleMode = outConsoleMode;
|
||||||
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
|
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
|
||||||
attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C'));
|
attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C'));
|
||||||
attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D'));
|
attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D'));
|
||||||
@ -148,7 +176,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Attributes getAttributes() {
|
public Attributes getAttributes() {
|
||||||
int mode = getConsoleMode();
|
int mode = getConsoleMode(inConsole);
|
||||||
if ((mode & ENABLE_ECHO_INPUT) != 0) {
|
if ((mode & ENABLE_ECHO_INPUT) != 0) {
|
||||||
attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true);
|
attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true);
|
||||||
}
|
}
|
||||||
@ -173,8 +201,11 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
if (tracking != MouseTracking.Off) {
|
if (tracking != MouseTracking.Off) {
|
||||||
mode |= ENABLE_MOUSE_INPUT;
|
mode |= ENABLE_MOUSE_INPUT;
|
||||||
|
// mouse events not send with quick edit mode
|
||||||
|
// to disable ENABLE_QUICK_EDIT_MODE just set extended flag
|
||||||
|
mode |= ENABLE_EXTENDED_FLAGS;
|
||||||
}
|
}
|
||||||
setConsoleMode(mode);
|
setConsoleMode(inConsole, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int ctrl(char key) {
|
protected int ctrl(char key) {
|
||||||
@ -197,7 +228,8 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
reader.close();
|
reader.close();
|
||||||
writer.close();
|
writer.close();
|
||||||
setConsoleMode(originalConsoleMode);
|
setConsoleMode(inConsole, originalInConsoleMode);
|
||||||
|
setConsoleMode(outConsole, originalOutConsoleMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final int SHIFT_FLAG = 0x01;
|
static final int SHIFT_FLAG = 0x01;
|
||||||
@ -213,7 +245,9 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
static final int SCROLLLOCK_ON = 0x0040;
|
static final int SCROLLLOCK_ON = 0x0040;
|
||||||
static final int CAPSLOCK_ON = 0x0080;
|
static final int CAPSLOCK_ON = 0x0080;
|
||||||
|
|
||||||
protected void processKeyEvent(final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState) throws IOException {
|
protected void processKeyEvent(
|
||||||
|
final boolean isKeyDown, final short virtualKeyCode, char ch, final int controlKeyState)
|
||||||
|
throws IOException {
|
||||||
final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0;
|
final boolean isCtrl = (controlKeyState & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) > 0;
|
||||||
final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0;
|
final boolean isAlt = (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) > 0;
|
||||||
final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0;
|
final boolean isShift = (controlKeyState & SHIFT_PRESSED) > 0;
|
||||||
@ -222,11 +256,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
// Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
|
// Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
|
||||||
// otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
|
// otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
|
||||||
if (ch != 0
|
if (ch != 0
|
||||||
&& (controlKeyState & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED | SHIFT_PRESSED))
|
&& (controlKeyState
|
||||||
|
& (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED | RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
|
||||||
== (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) {
|
== (RIGHT_ALT_PRESSED | LEFT_CTRL_PRESSED)) {
|
||||||
processInputChar(ch);
|
processInputChar(ch);
|
||||||
} else {
|
} else {
|
||||||
final String keySeq = getEscapeSequence(virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0));
|
final String keySeq = getEscapeSequence(
|
||||||
|
virtualKeyCode, (isCtrl ? CTRL_FLAG : 0) + (isAlt ? ALT_FLAG : 0) + (isShift ? SHIFT_FLAG : 0));
|
||||||
if (keySeq != null) {
|
if (keySeq != null) {
|
||||||
for (char c : keySeq.toCharArray()) {
|
for (char c : keySeq.toCharArray()) {
|
||||||
processInputChar(c);
|
processInputChar(c);
|
||||||
@ -254,10 +290,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
} else {
|
} else {
|
||||||
processInputChar(ch);
|
processInputChar(ch);
|
||||||
}
|
}
|
||||||
} else if (isCtrl) { //Handles the ctrl key events(uchar=0)
|
} else if (isCtrl) { // Handles the ctrl key events(uchar=0)
|
||||||
if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') {
|
if (virtualKeyCode >= 'A' && virtualKeyCode <= 'Z') {
|
||||||
ch = (char) (virtualKeyCode - 0x40);
|
ch = (char) (virtualKeyCode - 0x40);
|
||||||
} else if (virtualKeyCode == 191) { //?
|
} else if (virtualKeyCode == 191) { // ?
|
||||||
ch = 127;
|
ch = 127;
|
||||||
}
|
}
|
||||||
if (ch > 0) {
|
if (ch > 0) {
|
||||||
@ -468,7 +504,19 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
raise(Signal.INFO);
|
raise(Signal.INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) {
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
|
skipNextLf = true;
|
||||||
|
c = '\n';
|
||||||
|
} else if (c == '\n') {
|
||||||
|
if (skipNextLf) {
|
||||||
|
skipNextLf = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skipNextLf = false;
|
||||||
|
}
|
||||||
|
} else if (c == '\r') {
|
||||||
if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
|
if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -478,10 +526,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
} else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) {
|
} else if (c == '\n' && attributes.getInputFlag(Attributes.InputFlag.INLCR)) {
|
||||||
c = '\r';
|
c = '\r';
|
||||||
}
|
}
|
||||||
// if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) {
|
// if (attributes.getLocalFlag(Attributes.LocalFlag.ECHO)) {
|
||||||
// processOutputByte(c);
|
// processOutputByte(c);
|
||||||
// masterOutput.flush();
|
// masterOutput.flush();
|
||||||
// }
|
// }
|
||||||
slaveInputPipe.write(c);
|
slaveInputPipe.write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,9 +540,9 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract int getConsoleMode();
|
protected abstract int getConsoleMode(Console console);
|
||||||
|
|
||||||
protected abstract void setConsoleMode(int mode);
|
protected abstract void setConsoleMode(Console console, int mode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a single input event from the input buffer and process it.
|
* Read a single input event from the input buffer and process it.
|
||||||
@ -504,5 +552,13 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
|
|||||||
*/
|
*/
|
||||||
protected abstract boolean processConsoleInput() throws IOException;
|
protected abstract boolean processConsoleInput() throws IOException;
|
||||||
|
|
||||||
}
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemStream getSystemStream() {
|
||||||
|
return systemStream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,17 +8,17 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Cursor;
|
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
|
||||||
import jdk.internal.org.jline.utils.Curses;
|
|
||||||
import jdk.internal.org.jline.utils.InfoCmp;
|
|
||||||
|
|
||||||
import java.io.IOError;
|
import java.io.IOError;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Cursor;
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.utils.Curses;
|
||||||
|
import jdk.internal.org.jline.utils.InfoCmp;
|
||||||
|
|
||||||
public class CursorSupport {
|
public class CursorSupport {
|
||||||
|
|
||||||
public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) {
|
public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) {
|
||||||
@ -105,5 +105,4 @@ public class CursorSupport {
|
|||||||
throw new IOError(e);
|
throw new IOError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, the original author or authors.
|
* Copyright (c) 2022, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -17,6 +17,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.OSUtils;
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ public class Diag {
|
|||||||
diag(System.out);
|
diag(System.out);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void diag(PrintStream out) {
|
public static void diag(PrintStream out) {
|
||||||
out.println("System properties");
|
out.println("System properties");
|
||||||
out.println("=================");
|
out.println("=================");
|
||||||
out.println("os.name = " + System.getProperty("os.name"));
|
out.println("os.name = " + System.getProperty("os.name"));
|
||||||
@ -50,6 +51,17 @@ public class Diag {
|
|||||||
out.println("IS_OSX = " + OSUtils.IS_OSX);
|
out.println("IS_OSX = " + OSUtils.IS_OSX);
|
||||||
out.println();
|
out.println();
|
||||||
|
|
||||||
|
// FFM
|
||||||
|
out.println("FFM Support");
|
||||||
|
out.println("=================");
|
||||||
|
try {
|
||||||
|
TerminalProvider provider = TerminalProvider.load("ffm");
|
||||||
|
testProvider(out, provider);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
out.println("FFM support not available: " + t);
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
|
||||||
out.println("JnaSupport");
|
out.println("JnaSupport");
|
||||||
out.println("=================");
|
out.println("=================");
|
||||||
try {
|
try {
|
||||||
@ -60,13 +72,23 @@ public class Diag {
|
|||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
|
|
||||||
out.println("JansiSupport");
|
out.println("Jansi2Support");
|
||||||
out.println("=================");
|
out.println("=================");
|
||||||
try {
|
try {
|
||||||
TerminalProvider provider = TerminalProvider.load("jansi");
|
TerminalProvider provider = TerminalProvider.load("jansi");
|
||||||
testProvider(out, provider);
|
testProvider(out, provider);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
out.println("Jansi support not available: " + t);
|
out.println("Jansi 2 support not available: " + t);
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
|
||||||
|
out.println("JniSupport");
|
||||||
|
out.println("=================");
|
||||||
|
try {
|
||||||
|
TerminalProvider provider = TerminalProvider.load("jni");
|
||||||
|
testProvider(out, provider);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
out.println("JNI support not available: " + t);
|
||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
|
|
||||||
@ -83,32 +105,45 @@ public class Diag {
|
|||||||
|
|
||||||
private static void testProvider(PrintStream out, TerminalProvider provider) {
|
private static void testProvider(PrintStream out, TerminalProvider provider) {
|
||||||
try {
|
try {
|
||||||
out.println("StdIn stream = " + provider.isSystemStream(TerminalProvider.Stream.Input));
|
out.println("StdIn stream = " + provider.isSystemStream(SystemStream.Input));
|
||||||
out.println("StdOut stream = " + provider.isSystemStream(TerminalProvider.Stream.Output));
|
out.println("StdOut stream = " + provider.isSystemStream(SystemStream.Output));
|
||||||
out.println("StdErr stream = " + provider.isSystemStream(TerminalProvider.Stream.Error));
|
out.println("StdErr stream = " + provider.isSystemStream(SystemStream.Error));
|
||||||
} catch (Throwable t2) {
|
} catch (Throwable t2) {
|
||||||
out.println("Unable to check stream: " + t2);
|
out.println("Unable to check stream: " + t2);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
out.println("StdIn stream name = " + provider.systemStreamName(TerminalProvider.Stream.Input));
|
out.println("StdIn stream name = " + provider.systemStreamName(SystemStream.Input));
|
||||||
out.println("StdOut stream name = " + provider.systemStreamName(TerminalProvider.Stream.Output));
|
out.println("StdOut stream name = " + provider.systemStreamName(SystemStream.Output));
|
||||||
out.println("StdErr stream name = " + provider.systemStreamName(TerminalProvider.Stream.Error));
|
out.println("StdErr stream name = " + provider.systemStreamName(SystemStream.Error));
|
||||||
} catch (Throwable t2) {
|
} catch (Throwable t2) {
|
||||||
out.println("Unable to check stream names: " + t2);
|
out.println("Unable to check stream names: " + t2);
|
||||||
}
|
}
|
||||||
try (Terminal terminal = provider.sysTerminal("diag", "xterm", false, StandardCharsets.UTF_8,
|
try (Terminal terminal = provider.sysTerminal(
|
||||||
false, Terminal.SignalHandler.SIG_DFL, false, TerminalProvider.Stream.Output, input -> input) ) {
|
"diag",
|
||||||
|
"xterm",
|
||||||
|
false,
|
||||||
|
StandardCharsets.UTF_8,
|
||||||
|
false,
|
||||||
|
Terminal.SignalHandler.SIG_DFL,
|
||||||
|
false,
|
||||||
|
SystemStream.Output,
|
||||||
|
input -> input)) {
|
||||||
if (terminal != null) {
|
if (terminal != null) {
|
||||||
Attributes attr = terminal.enterRawMode();
|
Attributes attr = terminal.enterRawMode();
|
||||||
try {
|
try {
|
||||||
out.println("Terminal size: " + terminal.getSize());
|
out.println("Terminal size: " + terminal.getSize());
|
||||||
ForkJoinTask<Integer> t = new ForkJoinPool(1).submit(() -> terminal.reader().read(1) );
|
ForkJoinTask<Integer> t =
|
||||||
|
new ForkJoinPool(1).submit(() -> terminal.reader().read(1));
|
||||||
int r = t.get(1000, TimeUnit.MILLISECONDS);
|
int r = t.get(1000, TimeUnit.MILLISECONDS);
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append("The terminal seems to work: ");
|
sb.append("The terminal seems to work: ");
|
||||||
sb.append("terminal ").append(terminal.getClass().getName());
|
sb.append("terminal ").append(terminal.getClass().getName());
|
||||||
if (terminal instanceof AbstractPosixTerminal) {
|
if (terminal instanceof AbstractPosixTerminal) {
|
||||||
sb.append(" with pty ").append(((AbstractPosixTerminal) terminal).getPty().getClass().getName());
|
sb.append(" with pty ")
|
||||||
|
.append(((AbstractPosixTerminal) terminal)
|
||||||
|
.getPty()
|
||||||
|
.getClass()
|
||||||
|
.getName());
|
||||||
}
|
}
|
||||||
out.println(sb);
|
out.println(sb);
|
||||||
} catch (Throwable t3) {
|
} catch (Throwable t3) {
|
||||||
@ -129,5 +164,4 @@ public class Diag {
|
|||||||
static <S> S load(Class<S> clazz) {
|
static <S> S load(Class<S> clazz) {
|
||||||
return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next();
|
return ServiceLoader.load(clazz, clazz.getClassLoader()).iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -14,38 +14,58 @@ import java.io.OutputStream;
|
|||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
|
import jdk.internal.org.jline.terminal.Attributes.ControlChar;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.NonBlocking;
|
import jdk.internal.org.jline.utils.NonBlocking;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingReader;
|
import jdk.internal.org.jline.utils.NonBlockingReader;
|
||||||
|
|
||||||
public class DumbTerminal extends AbstractTerminal {
|
public class DumbTerminal extends AbstractTerminal {
|
||||||
|
|
||||||
|
private final TerminalProvider provider;
|
||||||
|
private final SystemStream systemStream;
|
||||||
private final NonBlockingInputStream input;
|
private final NonBlockingInputStream input;
|
||||||
private final OutputStream output;
|
private final OutputStream output;
|
||||||
private final NonBlockingReader reader;
|
private final NonBlockingReader reader;
|
||||||
private final PrintWriter writer;
|
private final PrintWriter writer;
|
||||||
private final Attributes attributes;
|
private final Attributes attributes;
|
||||||
private final Size size;
|
private final Size size;
|
||||||
|
private boolean skipNextLf;
|
||||||
|
|
||||||
public DumbTerminal(InputStream in, OutputStream out) throws IOException {
|
public DumbTerminal(InputStream in, OutputStream out, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
|
||||||
this(TYPE_DUMB, TYPE_DUMB, in, out, null);
|
this(TYPE_DUMB, TYPE_DUMB, in, out, null, inputStreamWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding) throws IOException {
|
public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
this(name, type, in, out, encoding, SignalHandler.SIG_DFL);
|
throws IOException {
|
||||||
|
this(null, null, name, type, in, out, encoding, SignalHandler.SIG_DFL, inputStreamWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DumbTerminal(String name, String type, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException {
|
@SuppressWarnings("this-escape")
|
||||||
|
public DumbTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
SystemStream systemStream,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
InputStream in,
|
||||||
|
OutputStream out,
|
||||||
|
Charset encoding,
|
||||||
|
SignalHandler signalHandler,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
super(name, type, encoding, signalHandler);
|
super(name, type, encoding, signalHandler);
|
||||||
NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), in);
|
this.provider = provider;
|
||||||
|
this.systemStream = systemStream;
|
||||||
|
NonBlockingInputStream nbis = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(in));
|
||||||
this.input = new NonBlockingInputStream() {
|
this.input = new NonBlockingInputStream() {
|
||||||
@Override
|
@Override
|
||||||
public int read(long timeout, boolean isPeek) throws IOException {
|
public int read(long timeout, boolean isPeek) throws IOException {
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
int c = nbis.read(timeout, isPeek);
|
int c = nbis.read(timeout, isPeek);
|
||||||
if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) {
|
if (attributes.getLocalFlag(Attributes.LocalFlag.ISIG)) {
|
||||||
if (c == attributes.getControlChar(ControlChar.VINTR)) {
|
if (c == attributes.getControlChar(ControlChar.VINTR)) {
|
||||||
@ -62,7 +82,19 @@ public class DumbTerminal extends AbstractTerminal {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (attributes.getInputFlag(Attributes.InputFlag.INORMEOL)) {
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
|
skipNextLf = true;
|
||||||
|
c = '\n';
|
||||||
|
} else if (c == '\n') {
|
||||||
|
if (skipNextLf) {
|
||||||
|
skipNextLf = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skipNextLf = false;
|
||||||
|
}
|
||||||
|
} else if (c == '\r') {
|
||||||
if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
|
if (attributes.getInputFlag(Attributes.InputFlag.IGNCR)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -107,9 +139,7 @@ public class DumbTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Attributes getAttributes() {
|
public Attributes getAttributes() {
|
||||||
Attributes attr = new Attributes();
|
return new Attributes(attributes);
|
||||||
attr.copy(attributes);
|
|
||||||
return attr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttributes(Attributes attr) {
|
public void setAttributes(Attributes attr) {
|
||||||
@ -126,4 +156,13 @@ public class DumbTerminal extends AbstractTerminal {
|
|||||||
size.copy(sz);
|
size.copy(sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemStream getSystemStream() {
|
||||||
|
return systemStream;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.terminal.TerminalBuilder;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
|
||||||
|
public class DumbTerminalProvider implements TerminalProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return TerminalBuilder.PROP_PROVIDER_DUMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal sysTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
|
return new DumbTerminal(
|
||||||
|
this,
|
||||||
|
systemStream,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
new FileInputStream(FileDescriptor.in),
|
||||||
|
new FileOutputStream(systemStream == SystemStream.Error ? FileDescriptor.err : FileDescriptor.out),
|
||||||
|
encoding,
|
||||||
|
signalHandler,
|
||||||
|
inputStreamWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal newTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
InputStream masterInput,
|
||||||
|
OutputStream masterOutput,
|
||||||
|
Charset encoding,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
Attributes attributes,
|
||||||
|
Size size)
|
||||||
|
throws IOException {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSystemStream(SystemStream stream) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String systemStreamName(SystemStream stream) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int systemStreamWidth(SystemStream stream) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TerminalProvider[" + name() + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,10 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
|
||||||
import jdk.internal.org.jline.terminal.Cursor;
|
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
@ -19,6 +15,11 @@ import java.nio.charset.Charset;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
|
import jdk.internal.org.jline.terminal.Cursor;
|
||||||
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console implementation with embedded line disciplined.
|
* Console implementation with embedded line disciplined.
|
||||||
*
|
*
|
||||||
@ -32,45 +33,59 @@ import java.util.function.IntConsumer;
|
|||||||
*/
|
*/
|
||||||
public class ExternalTerminal extends LineDisciplineTerminal {
|
public class ExternalTerminal extends LineDisciplineTerminal {
|
||||||
|
|
||||||
|
private final TerminalProvider provider;
|
||||||
protected final AtomicBoolean closed = new AtomicBoolean();
|
protected final AtomicBoolean closed = new AtomicBoolean();
|
||||||
protected final InputStream masterInput;
|
protected final InputStream masterInput;
|
||||||
protected final Object lock = new Object();
|
protected final Object lock = new Object();
|
||||||
protected boolean paused = true;
|
protected boolean paused = true;
|
||||||
protected Thread pumpThread;
|
protected Thread pumpThread;
|
||||||
|
|
||||||
public ExternalTerminal(String name, String type,
|
public ExternalTerminal(
|
||||||
InputStream masterInput,
|
String name, String type, InputStream masterInput, OutputStream masterOutput, Charset encoding)
|
||||||
OutputStream masterOutput,
|
throws IOException {
|
||||||
Charset encoding) throws IOException {
|
this(null, name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL);
|
||||||
this(name, type, masterInput, masterOutput, encoding, SignalHandler.SIG_DFL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalTerminal(String name, String type,
|
public ExternalTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
InputStream masterInput,
|
InputStream masterInput,
|
||||||
OutputStream masterOutput,
|
OutputStream masterOutput,
|
||||||
Charset encoding,
|
Charset encoding,
|
||||||
SignalHandler signalHandler) throws IOException {
|
SignalHandler signalHandler)
|
||||||
this(name, type, masterInput, masterOutput, encoding, signalHandler, false);
|
throws IOException {
|
||||||
|
this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalTerminal(String name, String type,
|
public ExternalTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
InputStream masterInput,
|
InputStream masterInput,
|
||||||
OutputStream masterOutput,
|
OutputStream masterOutput,
|
||||||
Charset encoding,
|
Charset encoding,
|
||||||
SignalHandler signalHandler,
|
SignalHandler signalHandler,
|
||||||
boolean paused) throws IOException {
|
boolean paused)
|
||||||
this(name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null);
|
throws IOException {
|
||||||
|
this(provider, name, type, masterInput, masterOutput, encoding, signalHandler, paused, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExternalTerminal(String name, String type,
|
@SuppressWarnings("this-escape")
|
||||||
|
public ExternalTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
InputStream masterInput,
|
InputStream masterInput,
|
||||||
OutputStream masterOutput,
|
OutputStream masterOutput,
|
||||||
Charset encoding,
|
Charset encoding,
|
||||||
SignalHandler signalHandler,
|
SignalHandler signalHandler,
|
||||||
boolean paused,
|
boolean paused,
|
||||||
Attributes attributes,
|
Attributes attributes,
|
||||||
Size size) throws IOException {
|
Size size)
|
||||||
|
throws IOException {
|
||||||
super(name, type, masterOutput, encoding, signalHandler);
|
super(name, type, masterOutput, encoding, signalHandler);
|
||||||
|
this.provider = provider;
|
||||||
this.masterInput = masterInput;
|
this.masterInput = masterInput;
|
||||||
if (attributes != null) {
|
if (attributes != null) {
|
||||||
setAttributes(attributes);
|
setAttributes(attributes);
|
||||||
@ -171,4 +186,8 @@ public class ExternalTerminal extends LineDisciplineTerminal {
|
|||||||
return CursorSupport.getCursorPosition(this, discarded);
|
return CursorSupport.getCursorPosition(this, discarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -14,6 +14,7 @@ import java.io.OutputStream;
|
|||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
@ -23,6 +24,8 @@ import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
|||||||
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.NonBlocking;
|
import jdk.internal.org.jline.utils.NonBlocking;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingPumpInputStream;
|
import jdk.internal.org.jline.utils.NonBlockingPumpInputStream;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingReader;
|
import jdk.internal.org.jline.utils.NonBlockingReader;
|
||||||
@ -45,21 +48,6 @@ import jdk.internal.org.jline.utils.NonBlockingReader;
|
|||||||
*/
|
*/
|
||||||
public class LineDisciplineTerminal extends AbstractTerminal {
|
public class LineDisciplineTerminal extends AbstractTerminal {
|
||||||
|
|
||||||
private static final String DEFAULT_TERMINAL_ATTRIBUTES =
|
|
||||||
"speed 9600 baud; 24 rows; 80 columns;\n" +
|
|
||||||
"lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl\n" +
|
|
||||||
"\t-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo\n" +
|
|
||||||
"\t-extproc\n" +
|
|
||||||
"iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8\n" +
|
|
||||||
"\t-ignbrk brkint -inpck -ignpar -parmrk\n" +
|
|
||||||
"oflags: opost onlcr -oxtabs -onocr -onlret\n" +
|
|
||||||
"cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow\n" +
|
|
||||||
"\t-dtrflow -mdmbuf\n" +
|
|
||||||
"cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;\n" +
|
|
||||||
"\teol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;\n" +
|
|
||||||
"\tmin = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;\n" +
|
|
||||||
"\tstop = ^S; susp = ^Z; time = 0; werase = ^W;\n";
|
|
||||||
|
|
||||||
private static final int PIPE_SIZE = 1024;
|
private static final int PIPE_SIZE = 1024;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -84,20 +72,20 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
* Console data
|
* Console data
|
||||||
*/
|
*/
|
||||||
protected final Attributes attributes;
|
protected final Attributes attributes;
|
||||||
|
|
||||||
protected final Size size;
|
protected final Size size;
|
||||||
|
|
||||||
public LineDisciplineTerminal(String name,
|
protected boolean skipNextLf;
|
||||||
String type,
|
|
||||||
OutputStream masterOutput,
|
public LineDisciplineTerminal(String name, String type, OutputStream masterOutput, Charset encoding)
|
||||||
Charset encoding) throws IOException {
|
throws IOException {
|
||||||
this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL);
|
this(name, type, masterOutput, encoding, SignalHandler.SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LineDisciplineTerminal(String name,
|
@SuppressWarnings("this-escape")
|
||||||
String type,
|
public LineDisciplineTerminal(
|
||||||
OutputStream masterOutput,
|
String name, String type, OutputStream masterOutput, Charset encoding, SignalHandler signalHandler)
|
||||||
Charset encoding,
|
throws IOException {
|
||||||
SignalHandler signalHandler) throws IOException {
|
|
||||||
super(name, type, encoding, signalHandler);
|
super(name, type, encoding, signalHandler);
|
||||||
NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE);
|
NonBlockingPumpInputStream input = NonBlocking.nonBlockingPumpInputStream(PIPE_SIZE);
|
||||||
this.slaveInputPipe = input.getOutputStream();
|
this.slaveInputPipe = input.getOutputStream();
|
||||||
@ -106,11 +94,66 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
this.slaveOutput = new FilteringOutputStream();
|
this.slaveOutput = new FilteringOutputStream();
|
||||||
this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding()));
|
this.slaveWriter = new PrintWriter(new OutputStreamWriter(slaveOutput, encoding()));
|
||||||
this.masterOutput = masterOutput;
|
this.masterOutput = masterOutput;
|
||||||
this.attributes = ExecPty.doGetAttr(DEFAULT_TERMINAL_ATTRIBUTES);
|
this.attributes = getDefaultTerminalAttributes();
|
||||||
this.size = new Size(160, 50);
|
this.size = new Size(160, 50);
|
||||||
parseInfoCmp();
|
parseInfoCmp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Attributes getDefaultTerminalAttributes() {
|
||||||
|
// speed 9600 baud; 24 rows; 80 columns;
|
||||||
|
// lflags: icanon isig iexten echo echoe -echok echoke -echonl echoctl
|
||||||
|
// -echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
|
||||||
|
// -extproc
|
||||||
|
// iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel iutf8
|
||||||
|
// -ignbrk brkint -inpck -ignpar -parmrk
|
||||||
|
// oflags: opost onlcr -oxtabs -onocr -onlret
|
||||||
|
// cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
|
||||||
|
// -dtrflow -mdmbuf
|
||||||
|
// cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
|
||||||
|
// eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
|
||||||
|
// min = 1; quit = ^\\; reprint = ^R; start = ^Q; status = ^T;
|
||||||
|
// stop = ^S; susp = ^Z; time = 0; werase = ^W;
|
||||||
|
Attributes attr = new Attributes();
|
||||||
|
attr.setLocalFlags(EnumSet.of(
|
||||||
|
LocalFlag.ICANON,
|
||||||
|
LocalFlag.ISIG,
|
||||||
|
LocalFlag.IEXTEN,
|
||||||
|
LocalFlag.ECHO,
|
||||||
|
LocalFlag.ECHOE,
|
||||||
|
LocalFlag.ECHOKE,
|
||||||
|
LocalFlag.ECHOCTL,
|
||||||
|
LocalFlag.PENDIN));
|
||||||
|
attr.setInputFlags(EnumSet.of(
|
||||||
|
InputFlag.ICRNL,
|
||||||
|
InputFlag.IXON,
|
||||||
|
InputFlag.IXANY,
|
||||||
|
InputFlag.IMAXBEL,
|
||||||
|
InputFlag.IUTF8,
|
||||||
|
InputFlag.BRKINT));
|
||||||
|
attr.setOutputFlags(EnumSet.of(OutputFlag.OPOST, OutputFlag.ONLCR));
|
||||||
|
attr.setControlChar(ControlChar.VDISCARD, ctrl('O'));
|
||||||
|
attr.setControlChar(ControlChar.VDSUSP, ctrl('Y'));
|
||||||
|
attr.setControlChar(ControlChar.VEOF, ctrl('D'));
|
||||||
|
attr.setControlChar(ControlChar.VERASE, ctrl('?'));
|
||||||
|
attr.setControlChar(ControlChar.VINTR, ctrl('C'));
|
||||||
|
attr.setControlChar(ControlChar.VKILL, ctrl('U'));
|
||||||
|
attr.setControlChar(ControlChar.VLNEXT, ctrl('V'));
|
||||||
|
attr.setControlChar(ControlChar.VMIN, 1);
|
||||||
|
attr.setControlChar(ControlChar.VQUIT, ctrl('\\'));
|
||||||
|
attr.setControlChar(ControlChar.VREPRINT, ctrl('R'));
|
||||||
|
attr.setControlChar(ControlChar.VSTART, ctrl('Q'));
|
||||||
|
attr.setControlChar(ControlChar.VSTATUS, ctrl('T'));
|
||||||
|
attr.setControlChar(ControlChar.VSTOP, ctrl('S'));
|
||||||
|
attr.setControlChar(ControlChar.VSUSP, ctrl('Z'));
|
||||||
|
attr.setControlChar(ControlChar.VTIME, 0);
|
||||||
|
attr.setControlChar(ControlChar.VWERASE, ctrl('W'));
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int ctrl(char c) {
|
||||||
|
return c == '?' ? 177 : c - 64;
|
||||||
|
}
|
||||||
|
|
||||||
public NonBlockingReader reader() {
|
public NonBlockingReader reader() {
|
||||||
return slaveReader;
|
return slaveReader;
|
||||||
}
|
}
|
||||||
@ -130,9 +173,7 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Attributes getAttributes() {
|
public Attributes getAttributes() {
|
||||||
Attributes attr = new Attributes();
|
return new Attributes(attributes);
|
||||||
attr.copy(attributes);
|
|
||||||
return attr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttributes(Attributes attr) {
|
public void setAttributes(Attributes attr) {
|
||||||
@ -214,7 +255,19 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
raise(Signal.INFO);
|
raise(Signal.INFO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (attributes.getInputFlag(InputFlag.INORMEOL)) {
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
|
skipNextLf = true;
|
||||||
|
c = '\n';
|
||||||
|
} else if (c == '\n') {
|
||||||
|
if (skipNextLf) {
|
||||||
|
skipNextLf = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skipNextLf = false;
|
||||||
|
}
|
||||||
|
} else if (c == '\r') {
|
||||||
if (attributes.getInputFlag(InputFlag.IGNCR)) {
|
if (attributes.getInputFlag(InputFlag.IGNCR)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -273,6 +326,16 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TerminalProvider getProvider() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SystemStream getSystemStream() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private class FilteringOutputStream extends OutputStream {
|
private class FilteringOutputStream extends OutputStream {
|
||||||
@Override
|
@Override
|
||||||
public void write(int b) throws IOException {
|
public void write(int b) throws IOException {
|
||||||
@ -284,13 +347,12 @@ public class LineDisciplineTerminal extends AbstractTerminal {
|
|||||||
public void write(byte[] b, int off, int len) throws IOException {
|
public void write(byte[] b, int off, int len) throws IOException {
|
||||||
if (b == null) {
|
if (b == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
} else if ((off < 0) || (off > b.length) || (len < 0) ||
|
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) {
|
||||||
((off + len) > b.length) || ((off + len) < 0)) {
|
|
||||||
throw new IndexOutOfBoundsException();
|
throw new IndexOutOfBoundsException();
|
||||||
} else if (len == 0) {
|
} else if (len == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0 ; i < len ; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
processOutputByte(b[off + i]);
|
processOutputByte(b[off + i]);
|
||||||
}
|
}
|
||||||
flush();
|
flush();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -8,11 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.MouseEvent;
|
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
|
||||||
import jdk.internal.org.jline.utils.InfoCmp;
|
|
||||||
import jdk.internal.org.jline.utils.InputStreamReader;
|
|
||||||
|
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.IOError;
|
import java.io.IOError;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -20,6 +15,11 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.function.IntSupplier;
|
import java.util.function.IntSupplier;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.MouseEvent;
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.utils.InfoCmp;
|
||||||
|
import jdk.internal.org.jline.utils.InputStreamReader;
|
||||||
|
|
||||||
public class MouseSupport {
|
public class MouseSupport {
|
||||||
|
|
||||||
public static boolean hasMouseSupport(Terminal terminal) {
|
public static boolean hasMouseSupport(Terminal terminal) {
|
||||||
@ -78,7 +78,8 @@ public class MouseSupport {
|
|||||||
case 0:
|
case 0:
|
||||||
button = MouseEvent.Button.Button1;
|
button = MouseEvent.Button.Button1;
|
||||||
if (last.getButton() == button
|
if (last.getButton() == button
|
||||||
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
|
&& (last.getType() == MouseEvent.Type.Pressed
|
||||||
|
|| last.getType() == MouseEvent.Type.Dragged)) {
|
||||||
type = MouseEvent.Type.Dragged;
|
type = MouseEvent.Type.Dragged;
|
||||||
} else {
|
} else {
|
||||||
type = MouseEvent.Type.Pressed;
|
type = MouseEvent.Type.Pressed;
|
||||||
@ -87,7 +88,8 @@ public class MouseSupport {
|
|||||||
case 1:
|
case 1:
|
||||||
button = MouseEvent.Button.Button2;
|
button = MouseEvent.Button.Button2;
|
||||||
if (last.getButton() == button
|
if (last.getButton() == button
|
||||||
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
|
&& (last.getType() == MouseEvent.Type.Pressed
|
||||||
|
|| last.getType() == MouseEvent.Type.Dragged)) {
|
||||||
type = MouseEvent.Type.Dragged;
|
type = MouseEvent.Type.Dragged;
|
||||||
} else {
|
} else {
|
||||||
type = MouseEvent.Type.Pressed;
|
type = MouseEvent.Type.Pressed;
|
||||||
@ -96,7 +98,8 @@ public class MouseSupport {
|
|||||||
case 2:
|
case 2:
|
||||||
button = MouseEvent.Button.Button3;
|
button = MouseEvent.Button.Button3;
|
||||||
if (last.getButton() == button
|
if (last.getButton() == button
|
||||||
&& (last.getType() == MouseEvent.Type.Pressed || last.getType() == MouseEvent.Type.Dragged)) {
|
&& (last.getType() == MouseEvent.Type.Pressed
|
||||||
|
|| last.getType() == MouseEvent.Type.Dragged)) {
|
||||||
type = MouseEvent.Type.Dragged;
|
type = MouseEvent.Type.Dragged;
|
||||||
} else {
|
} else {
|
||||||
type = MouseEvent.Type.Pressed;
|
type = MouseEvent.Type.Pressed;
|
||||||
@ -134,5 +137,4 @@ public class MouseSupport {
|
|||||||
throw new IOError(e);
|
throw new IOError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -17,8 +17,7 @@ public final class NativeSignalHandler implements SignalHandler {
|
|||||||
|
|
||||||
public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler();
|
public static final NativeSignalHandler SIG_IGN = new NativeSignalHandler();
|
||||||
|
|
||||||
private NativeSignalHandler() {
|
private NativeSignalHandler() {}
|
||||||
}
|
|
||||||
|
|
||||||
public void handle(Signal signal) {
|
public void handle(Signal signal) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -38,15 +38,34 @@ public class PosixPtyTerminal extends AbstractPosixTerminal {
|
|||||||
private Thread outputPumpThread;
|
private Thread outputPumpThread;
|
||||||
private boolean paused = true;
|
private boolean paused = true;
|
||||||
|
|
||||||
public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding) throws IOException {
|
public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding)
|
||||||
|
throws IOException {
|
||||||
this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL);
|
this(name, type, pty, in, out, encoding, SignalHandler.SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler) throws IOException {
|
public PosixPtyTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
Pty pty,
|
||||||
|
InputStream in,
|
||||||
|
OutputStream out,
|
||||||
|
Charset encoding,
|
||||||
|
SignalHandler signalHandler)
|
||||||
|
throws IOException {
|
||||||
this(name, type, pty, in, out, encoding, signalHandler, false);
|
this(name, type, pty, in, out, encoding, signalHandler, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PosixPtyTerminal(String name, String type, Pty pty, InputStream in, OutputStream out, Charset encoding, SignalHandler signalHandler, boolean paused) throws IOException {
|
@SuppressWarnings("this-escape")
|
||||||
|
public PosixPtyTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
Pty pty,
|
||||||
|
InputStream in,
|
||||||
|
OutputStream out,
|
||||||
|
Charset encoding,
|
||||||
|
SignalHandler signalHandler,
|
||||||
|
boolean paused)
|
||||||
|
throws IOException {
|
||||||
super(name, type, pty, encoding, signalHandler);
|
super(name, type, pty, encoding, signalHandler);
|
||||||
this.in = Objects.requireNonNull(in);
|
this.in = Objects.requireNonNull(in);
|
||||||
this.out = Objects.requireNonNull(out);
|
this.out = Objects.requireNonNull(out);
|
||||||
@ -113,7 +132,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal {
|
|||||||
if (p1 != null) {
|
if (p1 != null) {
|
||||||
p1.join();
|
p1.join();
|
||||||
}
|
}
|
||||||
if (p2 !=null) {
|
if (p2 != null) {
|
||||||
p2.join();
|
p2.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,7 +186,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal {
|
|||||||
|
|
||||||
private void pumpIn() {
|
private void pumpIn() {
|
||||||
try {
|
try {
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (paused) {
|
if (paused) {
|
||||||
inputPumpThread = null;
|
inputPumpThread = null;
|
||||||
@ -193,7 +212,7 @@ public class PosixPtyTerminal extends AbstractPosixTerminal {
|
|||||||
|
|
||||||
private void pumpOut() {
|
private void pumpOut() {
|
||||||
try {
|
try {
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
if (paused) {
|
if (paused) {
|
||||||
outputPumpThread = null;
|
outputPumpThread = null;
|
||||||
@ -221,5 +240,4 @@ public class PosixPtyTerminal extends AbstractPosixTerminal {
|
|||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -18,8 +18,9 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import jdk.internal.org.jline.utils.NonBlocking;
|
|
||||||
import jdk.internal.org.jline.terminal.spi.Pty;
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.utils.FastBufferedOutputStream;
|
||||||
|
import jdk.internal.org.jline.utils.NonBlocking;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
import jdk.internal.org.jline.utils.NonBlockingInputStream;
|
||||||
import jdk.internal.org.jline.utils.NonBlockingReader;
|
import jdk.internal.org.jline.utils.NonBlockingReader;
|
||||||
import jdk.internal.org.jline.utils.ShutdownHooks;
|
import jdk.internal.org.jline.utils.ShutdownHooks;
|
||||||
@ -35,12 +36,14 @@ public class PosixSysTerminal extends AbstractPosixTerminal {
|
|||||||
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
|
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
|
||||||
protected final Task closer;
|
protected final Task closer;
|
||||||
|
|
||||||
public PosixSysTerminal(String name, String type, Pty pty, Charset encoding,
|
@SuppressWarnings("this-escape")
|
||||||
boolean nativeSignals, SignalHandler signalHandler,
|
public PosixSysTerminal(
|
||||||
Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
|
String name, String type, Pty pty, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
super(name, type, pty, encoding, signalHandler);
|
super(name, type, pty, encoding, signalHandler);
|
||||||
this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput()));
|
this.input = NonBlocking.nonBlocking(getName(), inputStreamWrapper.apply(pty.getSlaveInput()));
|
||||||
this.output = pty.getSlaveOutput();
|
this.output = new FastBufferedOutputStream(pty.getSlaveOutput());
|
||||||
this.reader = NonBlocking.nonBlocking(getName(), input, encoding());
|
this.reader = NonBlocking.nonBlocking(getName(), input, encoding());
|
||||||
this.writer = new PrintWriter(new OutputStreamWriter(output, encoding()));
|
this.writer = new PrintWriter(new OutputStreamWriter(output, encoding()));
|
||||||
parseInfoCmp();
|
parseInfoCmp();
|
||||||
@ -98,5 +101,4 @@ public class PosixSysTerminal extends AbstractPosixTerminal {
|
|||||||
// Do not call reader.close()
|
// Do not call reader.close()
|
||||||
reader.shutdown();
|
reader.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
*
|
*
|
||||||
* https://opensource.org/licenses/BSD-3-Clause
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.terminal.impl;
|
package jdk.internal.org.jline.terminal.impl.exec;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.FileDescriptor;
|
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -26,8 +26,10 @@ import jdk.internal.org.jline.terminal.Attributes.InputFlag;
|
|||||||
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
import jdk.internal.org.jline.terminal.Attributes.LocalFlag;
|
||||||
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
import jdk.internal.org.jline.terminal.Attributes.OutputFlag;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
import jdk.internal.org.jline.terminal.impl.AbstractPty;
|
||||||
import jdk.internal.org.jline.terminal.spi.Pty;
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.OSUtils;
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
|
|
||||||
import static jdk.internal.org.jline.utils.ExecHelper.exec;
|
import static jdk.internal.org.jline.utils.ExecHelper.exec;
|
||||||
@ -35,28 +37,26 @@ import static jdk.internal.org.jline.utils.ExecHelper.exec;
|
|||||||
public class ExecPty extends AbstractPty implements Pty {
|
public class ExecPty extends AbstractPty implements Pty {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final TerminalProvider.Stream console;
|
|
||||||
|
|
||||||
public static Pty current(TerminalProvider.Stream console) throws IOException {
|
public static Pty current(TerminalProvider provider, SystemStream systemStream) throws IOException {
|
||||||
try {
|
try {
|
||||||
String result = exec(true, OSUtils.TTY_COMMAND);
|
String result = exec(true, OSUtils.TTY_COMMAND);
|
||||||
if (console != TerminalProvider.Stream.Output && console != TerminalProvider.Stream.Error) {
|
if (systemStream != SystemStream.Output && systemStream != SystemStream.Error) {
|
||||||
throw new IllegalArgumentException("console should be Output or Error: " + console);
|
throw new IllegalArgumentException("systemStream should be Output or Error: " + systemStream);
|
||||||
}
|
}
|
||||||
return new ExecPty(result.trim(), console);
|
return new ExecPty(provider, systemStream, result.trim());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IOException("Not a tty", e);
|
throw new IOException("Not a tty", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ExecPty(String name, TerminalProvider.Stream console) {
|
protected ExecPty(TerminalProvider provider, SystemStream systemStream, String name) {
|
||||||
|
super(provider, systemStream);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.console = console;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
@ -74,16 +74,14 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected InputStream doGetSlaveInput() throws IOException {
|
protected InputStream doGetSlaveInput() throws IOException {
|
||||||
return console != null
|
return systemStream != null ? new FileInputStream(FileDescriptor.in) : new FileInputStream(getName());
|
||||||
? new FileInputStream(FileDescriptor.in)
|
|
||||||
: new FileInputStream(getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream getSlaveOutput() throws IOException {
|
public OutputStream getSlaveOutput() throws IOException {
|
||||||
return console == TerminalProvider.Stream.Output
|
return systemStream == SystemStream.Output
|
||||||
? new FileOutputStream(FileDescriptor.out)
|
? new FileOutputStream(FileDescriptor.out)
|
||||||
: console == TerminalProvider.Stream.Error
|
: systemStream == SystemStream.Error
|
||||||
? new FileOutputStream(FileDescriptor.err)
|
? new FileOutputStream(FileDescriptor.err)
|
||||||
: new FileOutputStream(getName());
|
: new FileOutputStream(getName());
|
||||||
}
|
}
|
||||||
@ -99,18 +97,30 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
List<String> commands = getFlagsToSet(attr, getAttr());
|
List<String> commands = getFlagsToSet(attr, getAttr());
|
||||||
if (!commands.isEmpty()) {
|
if (!commands.isEmpty()) {
|
||||||
commands.add(0, OSUtils.STTY_COMMAND);
|
commands.add(0, OSUtils.STTY_COMMAND);
|
||||||
if (console == null) {
|
if (systemStream == null) {
|
||||||
commands.add(1, OSUtils.STTY_F_OPTION);
|
commands.add(1, OSUtils.STTY_F_OPTION);
|
||||||
commands.add(2, getName());
|
commands.add(2, getName());
|
||||||
}
|
}
|
||||||
exec(console != null, commands.toArray(new String[0]));
|
try {
|
||||||
|
exec(systemStream != null, commands.toArray(new String[0]));
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Handle partial failures with GNU stty, see #97
|
||||||
|
if (e.toString().contains("unable to perform all requested operations")) {
|
||||||
|
commands = getFlagsToSet(attr, getAttr());
|
||||||
|
if (!commands.isEmpty()) {
|
||||||
|
throw new IOException("Could not set the following flags: " + String.join(", ", commands), e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<String> getFlagsToSet(Attributes attr, Attributes current) {
|
protected List<String> getFlagsToSet(Attributes attr, Attributes current) {
|
||||||
List<String> commands = new ArrayList<>();
|
List<String> commands = new ArrayList<>();
|
||||||
for (InputFlag flag : InputFlag.values()) {
|
for (InputFlag flag : InputFlag.values()) {
|
||||||
if (attr.getInputFlag(flag) != current.getInputFlag(flag)) {
|
if (attr.getInputFlag(flag) != current.getInputFlag(flag) && flag != InputFlag.INORMEOL) {
|
||||||
commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
|
commands.add((attr.getInputFlag(flag) ? flag.name() : "-" + flag.name()).toLowerCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,11 +147,9 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
commands.add(cchar.name().toLowerCase().substring(1));
|
commands.add(cchar.name().toLowerCase().substring(1));
|
||||||
if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) {
|
if (cchar == ControlChar.VMIN || cchar == ControlChar.VTIME) {
|
||||||
commands.add(Integer.toString(v));
|
commands.add(Integer.toString(v));
|
||||||
}
|
} else if (v == 0) {
|
||||||
else if (v == 0) {
|
|
||||||
commands.add(undef);
|
commands.add(undef);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
if (v >= 128) {
|
if (v >= 128) {
|
||||||
v -= 128;
|
v -= 128;
|
||||||
str += "M-";
|
str += "M-";
|
||||||
@ -165,12 +173,12 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String doGetConfig() throws IOException {
|
protected String doGetConfig() throws IOException {
|
||||||
return console != null
|
return systemStream != null
|
||||||
? exec(true, OSUtils.STTY_COMMAND, "-a")
|
? exec(true, OSUtils.STTY_COMMAND, "-a")
|
||||||
: exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a");
|
: exec(false, OSUtils.STTY_COMMAND, OSUtils.STTY_F_OPTION, getName(), "-a");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Attributes doGetAttr(String cfg) throws IOException {
|
public static Attributes doGetAttr(String cfg) throws IOException {
|
||||||
Attributes attributes = new Attributes();
|
Attributes attributes = new Attributes();
|
||||||
for (InputFlag flag : InputFlag.values()) {
|
for (InputFlag flag : InputFlag.values()) {
|
||||||
Boolean value = doGetFlag(cfg, flag);
|
Boolean value = doGetFlag(cfg, flag);
|
||||||
@ -201,16 +209,19 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
if ("reprint".endsWith(name)) {
|
if ("reprint".endsWith(name)) {
|
||||||
name = "(?:reprint|rprnt)";
|
name = "(?:reprint|rprnt)";
|
||||||
}
|
}
|
||||||
Matcher matcher = Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg);
|
Matcher matcher =
|
||||||
|
Pattern.compile("[\\s;]" + name + "\\s*=\\s*(.+?)[\\s;]").matcher(cfg);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
attributes.setControlChar(cchar, parseControlChar(matcher.group(1).toUpperCase()));
|
attributes.setControlChar(
|
||||||
|
cchar, parseControlChar(matcher.group(1).toUpperCase()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Boolean doGetFlag(String cfg, Enum<?> flag) {
|
private static Boolean doGetFlag(String cfg, Enum<?> flag) {
|
||||||
Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)").matcher(cfg);
|
Matcher matcher = Pattern.compile("(?:^|[\\s;])(\\-?" + flag.name().toLowerCase() + ")(?:[\\s;]|$)")
|
||||||
|
.matcher(cfg);
|
||||||
return matcher.find() ? !matcher.group(1).startsWith("-") : null;
|
return matcher.find() ? !matcher.group(1).startsWith("-") : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,9 +270,7 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
|
|
||||||
static int doGetInt(String name, String cfg) throws IOException {
|
static int doGetInt(String name, String cfg) throws IOException {
|
||||||
String[] patterns = new String[] {
|
String[] patterns = new String[] {
|
||||||
"\\b([0-9]+)\\s+" + name + "\\b",
|
"\\b([0-9]+)\\s+" + name + "\\b", "\\b" + name + "\\s+([0-9]+)\\b", "\\b" + name + "\\s*=\\s*([0-9]+)\\b"
|
||||||
"\\b" + name + "\\s+([0-9]+)\\b",
|
|
||||||
"\\b" + name + "\\s*=\\s*([0-9]+)\\b"
|
|
||||||
};
|
};
|
||||||
for (String pattern : patterns) {
|
for (String pattern : patterns) {
|
||||||
Matcher matcher = Pattern.compile(pattern).matcher(cfg);
|
Matcher matcher = Pattern.compile(pattern).matcher(cfg);
|
||||||
@ -274,23 +283,29 @@ public class ExecPty extends AbstractPty implements Pty {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSize(Size size) throws IOException {
|
public void setSize(Size size) throws IOException {
|
||||||
if (console != null) {
|
if (systemStream != null) {
|
||||||
exec(true,
|
exec(
|
||||||
|
true,
|
||||||
OSUtils.STTY_COMMAND,
|
OSUtils.STTY_COMMAND,
|
||||||
"columns", Integer.toString(size.getColumns()),
|
"columns",
|
||||||
"rows", Integer.toString(size.getRows()));
|
Integer.toString(size.getColumns()),
|
||||||
|
"rows",
|
||||||
|
Integer.toString(size.getRows()));
|
||||||
} else {
|
} else {
|
||||||
exec(false,
|
exec(
|
||||||
|
false,
|
||||||
OSUtils.STTY_COMMAND,
|
OSUtils.STTY_COMMAND,
|
||||||
OSUtils.STTY_F_OPTION, getName(),
|
OSUtils.STTY_F_OPTION,
|
||||||
"columns", Integer.toString(size.getColumns()),
|
getName(),
|
||||||
"rows", Integer.toString(size.getRows()));
|
"columns",
|
||||||
|
Integer.toString(size.getColumns()),
|
||||||
|
"rows",
|
||||||
|
Integer.toString(size.getRows()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ExecPty[" + getName() + (console != null ? ", system]" : "]");
|
return "ExecPty[" + getName() + (systemStream != null ? ", system]" : "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, the original author or authors.
|
* Copyright (c) 2022, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -17,117 +17,249 @@ import java.lang.reflect.Field;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
//import jdk.internal.org.jline.nativ.JLineLibrary;
|
||||||
|
//import jdk.internal.org.jline.nativ.JLineNativeLoader;
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
import jdk.internal.org.jline.terminal.impl.ExecPty;
|
import jdk.internal.org.jline.terminal.TerminalBuilder;
|
||||||
import jdk.internal.org.jline.terminal.impl.ExternalTerminal;
|
import jdk.internal.org.jline.terminal.impl.ExternalTerminal;
|
||||||
import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
|
import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
|
||||||
import jdk.internal.org.jline.terminal.spi.Pty;
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
import jdk.internal.org.jline.utils.ExecHelper;
|
import jdk.internal.org.jline.utils.ExecHelper;
|
||||||
|
import jdk.internal.org.jline.utils.Log;
|
||||||
import jdk.internal.org.jline.utils.OSUtils;
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
|
|
||||||
public class ExecTerminalProvider implements TerminalProvider
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE;
|
||||||
{
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT;
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE;
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION;
|
||||||
|
|
||||||
|
public class ExecTerminalProvider implements TerminalProvider {
|
||||||
|
|
||||||
|
private static boolean warned;
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
return "exec";
|
return TerminalBuilder.PROP_PROVIDER_EXEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pty current(Stream consoleStream) throws IOException {
|
public Pty current(SystemStream systemStream) throws IOException {
|
||||||
return ExecPty.current(consoleStream);
|
return ExecPty.current(this, systemStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal sysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
|
public Terminal sysTerminal(
|
||||||
boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
|
String name,
|
||||||
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
|
String type,
|
||||||
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
if (OSUtils.IS_WINDOWS) {
|
if (OSUtils.IS_WINDOWS) {
|
||||||
return winSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
|
return winSysTerminal(
|
||||||
|
name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper);
|
||||||
} else {
|
} else {
|
||||||
return posixSysTerminal(name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, consoleStream, inputStreamWrapper );
|
return posixSysTerminal(
|
||||||
|
name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream, inputStreamWrapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Terminal winSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
|
public Terminal winSysTerminal(
|
||||||
boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
|
String name,
|
||||||
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper ) throws IOException {
|
String type,
|
||||||
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) {
|
if (OSUtils.IS_CYGWIN || OSUtils.IS_MSYSTEM) {
|
||||||
Pty pty = current(consoleStream);
|
Pty pty = current(systemStream);
|
||||||
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
|
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Terminal posixSysTerminal(String name, String type, boolean ansiPassThrough, Charset encoding,
|
public Terminal posixSysTerminal(
|
||||||
boolean nativeSignals, Terminal.SignalHandler signalHandler, boolean paused,
|
String name,
|
||||||
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper) throws IOException {
|
String type,
|
||||||
Pty pty = current(consoleStream);
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
|
Pty pty = current(systemStream);
|
||||||
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
|
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Terminal newTerminal(String name, String type, InputStream in, OutputStream out,
|
public Terminal newTerminal(
|
||||||
Charset encoding, Terminal.SignalHandler signalHandler, boolean paused,
|
String name,
|
||||||
Attributes attributes, Size size) throws IOException
|
String type,
|
||||||
{
|
InputStream in,
|
||||||
return new ExternalTerminal(name, type, in, out, encoding, signalHandler, paused, attributes, size);
|
OutputStream out,
|
||||||
|
Charset encoding,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
Attributes attributes,
|
||||||
|
Size size)
|
||||||
|
throws IOException {
|
||||||
|
return new ExternalTerminal(this, name, type, in, out, encoding, signalHandler, paused, attributes, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isSystemStream(Stream stream) {
|
public boolean isSystemStream(SystemStream stream) {
|
||||||
try {
|
try {
|
||||||
return isWindowsSystemStream(stream) || isPosixSystemStream(stream);
|
return isPosixSystemStream(stream) || isWindowsSystemStream(stream);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWindowsSystemStream(Stream stream) {
|
public boolean isWindowsSystemStream(SystemStream stream) {
|
||||||
return systemStreamName( stream ) != null;
|
return systemStreamName(stream) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPosixSystemStream(Stream stream) {
|
public boolean isPosixSystemStream(SystemStream stream) {
|
||||||
try {
|
try {
|
||||||
Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal()))
|
Process p = new ProcessBuilder(OSUtils.TEST_COMMAND, "-t", Integer.toString(stream.ordinal()))
|
||||||
.inheritIO().start();
|
.inheritIO()
|
||||||
|
.start();
|
||||||
return p.waitFor() == 0;
|
return p.waitFor() == 0;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
Log.debug("ExecTerminalProvider failed 'test -t' for " + stream, t);
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String systemStreamName(Stream stream) {
|
public String systemStreamName(SystemStream stream) {
|
||||||
try {
|
try {
|
||||||
ProcessBuilder.Redirect input = stream == Stream.Input
|
ProcessBuilder.Redirect input = stream == SystemStream.Input
|
||||||
? ProcessBuilder.Redirect.INHERIT
|
? ProcessBuilder.Redirect.INHERIT
|
||||||
: getRedirect(stream == Stream.Output ? FileDescriptor.out : FileDescriptor.err);
|
: newDescriptor(stream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err);
|
||||||
Process p = new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start();
|
Process p =
|
||||||
|
new ProcessBuilder(OSUtils.TTY_COMMAND).redirectInput(input).start();
|
||||||
String result = ExecHelper.waitAndCapture(p);
|
String result = ExecHelper.waitAndCapture(p);
|
||||||
if (p.exitValue() == 0) {
|
if (p.exitValue() == 0) {
|
||||||
return result.trim();
|
return result.trim();
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
if ("java.lang.reflect.InaccessibleObjectException"
|
||||||
|
.equals(t.getClass().getName())
|
||||||
|
&& !warned) {
|
||||||
|
Log.warn(
|
||||||
|
"The ExecTerminalProvider requires the JVM options: '--add-opens java.base/java.lang=ALL-UNNAMED'");
|
||||||
|
warned = true;
|
||||||
|
}
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ProcessBuilder.Redirect getRedirect(FileDescriptor fd) throws ReflectiveOperationException {
|
@Override
|
||||||
// This is not really allowed, but this is the only way to redirect the output or error stream
|
public int systemStreamWidth(SystemStream stream) {
|
||||||
// to the input. This is definitely not something you'd usually want to do, but in the case of
|
try (ExecPty pty = new ExecPty(this, stream, null)) {
|
||||||
// the `tty` utility, it provides a way to get
|
return pty.getSize().getColumns();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RedirectPipeCreator redirectPipeCreator;
|
||||||
|
|
||||||
|
protected static ProcessBuilder.Redirect newDescriptor(FileDescriptor fd) {
|
||||||
|
if (redirectPipeCreator == null) {
|
||||||
|
String str = System.getProperty(PROP_REDIRECT_PIPE_CREATION_MODE, PROP_REDIRECT_PIPE_CREATION_MODE_DEFAULT);
|
||||||
|
String[] modes = str.split(",");
|
||||||
|
IllegalStateException ise = new IllegalStateException("Unable to create RedirectPipe");
|
||||||
|
for (String mode : modes) {
|
||||||
|
try {
|
||||||
|
switch (mode) {
|
||||||
|
case PROP_REDIRECT_PIPE_CREATION_MODE_NATIVE:
|
||||||
|
redirectPipeCreator = null;//new NativeRedirectPipeCreator();
|
||||||
|
break;
|
||||||
|
case PROP_REDIRECT_PIPE_CREATION_MODE_REFLECTION:
|
||||||
|
redirectPipeCreator = new ReflectionRedirectPipeCreator();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// ignore
|
||||||
|
ise.addSuppressed(t);
|
||||||
|
}
|
||||||
|
if (redirectPipeCreator != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (redirectPipeCreator == null) {
|
||||||
|
throw ise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return redirectPipeCreator.newRedirectPipe(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RedirectPipeCreator {
|
||||||
|
ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reflection based file descriptor creator.
|
||||||
|
* This requires the following option
|
||||||
|
* --add-opens java.base/java.lang=ALL-UNNAMED
|
||||||
|
*/
|
||||||
|
static class ReflectionRedirectPipeCreator implements RedirectPipeCreator {
|
||||||
|
private final Constructor<ProcessBuilder.Redirect> constructor;
|
||||||
|
private final Field fdField;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
ReflectionRedirectPipeCreator() throws Exception {
|
||||||
Class<?> rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl");
|
Class<?> rpi = Class.forName("java.lang.ProcessBuilder$RedirectPipeImpl");
|
||||||
Constructor<?> cns = rpi.getDeclaredConstructor();
|
constructor = (Constructor<ProcessBuilder.Redirect>) rpi.getDeclaredConstructor();
|
||||||
cns.setAccessible(true);
|
constructor.setAccessible(true);
|
||||||
ProcessBuilder.Redirect input = (ProcessBuilder.Redirect) cns.newInstance();
|
fdField = rpi.getDeclaredField("fd");
|
||||||
Field f = rpi.getDeclaredField("fd");
|
fdField.setAccessible(true);
|
||||||
f.setAccessible(true);
|
}
|
||||||
f.set(input, fd);
|
|
||||||
|
@Override
|
||||||
|
public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) {
|
||||||
|
try {
|
||||||
|
ProcessBuilder.Redirect input = constructor.newInstance();
|
||||||
|
fdField.set(input, fd);
|
||||||
return input;
|
return input;
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
// This should not happen as the field has been set accessible
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static class NativeRedirectPipeCreator implements RedirectPipeCreator {
|
||||||
|
// public NativeRedirectPipeCreator() {
|
||||||
|
// // Force load the library
|
||||||
|
// JLineNativeLoader.initialize();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public ProcessBuilder.Redirect newRedirectPipe(FileDescriptor fd) {
|
||||||
|
// return JLineLibrary.newRedirectPipe(fd);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TerminalProvider[" + name() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,175 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.AbstractPty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
|
||||||
|
class FfmNativePty extends AbstractPty {
|
||||||
|
private final int master;
|
||||||
|
private final int slave;
|
||||||
|
private final int slaveOut;
|
||||||
|
private final String name;
|
||||||
|
private final FileDescriptor masterFD;
|
||||||
|
private final FileDescriptor slaveFD;
|
||||||
|
private final FileDescriptor slaveOutFD;
|
||||||
|
|
||||||
|
public FfmNativePty(TerminalProvider provider, SystemStream systemStream, int master, int slave, String name) {
|
||||||
|
this(
|
||||||
|
provider,
|
||||||
|
systemStream,
|
||||||
|
master,
|
||||||
|
newDescriptor(master),
|
||||||
|
slave,
|
||||||
|
newDescriptor(slave),
|
||||||
|
slave,
|
||||||
|
newDescriptor(slave),
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FfmNativePty(
|
||||||
|
TerminalProvider provider,
|
||||||
|
SystemStream systemStream,
|
||||||
|
int master,
|
||||||
|
FileDescriptor masterFD,
|
||||||
|
int slave,
|
||||||
|
FileDescriptor slaveFD,
|
||||||
|
int slaveOut,
|
||||||
|
FileDescriptor slaveOutFD,
|
||||||
|
String name) {
|
||||||
|
super(provider, systemStream);
|
||||||
|
this.master = master;
|
||||||
|
this.slave = slave;
|
||||||
|
this.slaveOut = slaveOut;
|
||||||
|
this.name = name;
|
||||||
|
this.masterFD = masterFD;
|
||||||
|
this.slaveFD = slaveFD;
|
||||||
|
this.slaveOutFD = slaveOutFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (master > 0) {
|
||||||
|
getMasterInput().close();
|
||||||
|
}
|
||||||
|
if (slave > 0) {
|
||||||
|
getSlaveInput().close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaster() {
|
||||||
|
return master;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlave() {
|
||||||
|
return slave;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlaveOut() {
|
||||||
|
return slaveOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescriptor getMasterFD() {
|
||||||
|
return masterFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescriptor getSlaveFD() {
|
||||||
|
return slaveFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileDescriptor getSlaveOutFD() {
|
||||||
|
return slaveOutFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getMasterInput() {
|
||||||
|
return new FileInputStream(getMasterFD());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getMasterOutput() {
|
||||||
|
return new FileOutputStream(getMasterFD());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected InputStream doGetSlaveInput() {
|
||||||
|
return new FileInputStream(getSlaveFD());
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputStream getSlaveOutput() {
|
||||||
|
return new FileOutputStream(getSlaveOutFD());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Attributes getAttr() throws IOException {
|
||||||
|
return CLibrary.getAttributes(slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doSetAttr(Attributes attr) throws IOException {
|
||||||
|
CLibrary.setAttributes(slave, attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Size getSize() throws IOException {
|
||||||
|
return CLibrary.getTerminalSize(slave);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSize(Size size) throws IOException {
|
||||||
|
CLibrary.setTerminalSize(slave, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FfmNativePty[" + getName() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPosixSystemStream(SystemStream stream) {
|
||||||
|
switch (stream) {
|
||||||
|
case Input:
|
||||||
|
return CLibrary.isTty(0);
|
||||||
|
case Output:
|
||||||
|
return CLibrary.isTty(1);
|
||||||
|
case Error:
|
||||||
|
return CLibrary.isTty(2);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String posixSystemStreamName(SystemStream stream) {
|
||||||
|
switch (stream) {
|
||||||
|
case Input:
|
||||||
|
return CLibrary.ttyName(0);
|
||||||
|
case Output:
|
||||||
|
return CLibrary.ttyName(1);
|
||||||
|
case Error:
|
||||||
|
return CLibrary.ttyName(2);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int systemStreamWidth(SystemStream systemStream) {
|
||||||
|
int fd = systemStream == SystemStream.Output ? 1 : 2;
|
||||||
|
return CLibrary.getTerminalSize(fd).getColumns();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.foreign.MemoryLayout;
|
||||||
|
import java.lang.foreign.MemoryLayout.PathElement;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
import jdk.internal.org.jline.terminal.TerminalBuilder;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.PosixPtyTerminal;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.PosixSysTerminal;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.Pty;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
|
|
||||||
|
public class FfmTerminalProvider implements TerminalProvider {
|
||||||
|
|
||||||
|
public FfmTerminalProvider() {
|
||||||
|
if (!FfmTerminalProvider.class.getModule().isNativeAccessEnabled()) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
"Native access is not enabled for the current module: " + FfmTerminalProvider.class.getModule());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return TerminalBuilder.PROP_PROVIDER_FFM;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal sysTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
|
if (OSUtils.IS_WINDOWS) {
|
||||||
|
return NativeWinSysTerminal.createTerminal(
|
||||||
|
this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, inputStreamWrapper);
|
||||||
|
} else {
|
||||||
|
Pty pty = new FfmNativePty(
|
||||||
|
this,
|
||||||
|
systemStream,
|
||||||
|
-1,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
FileDescriptor.in,
|
||||||
|
systemStream == SystemStream.Output ? 1 : 2,
|
||||||
|
systemStream == SystemStream.Output ? FileDescriptor.out : FileDescriptor.err,
|
||||||
|
CLibrary.ttyName(0));
|
||||||
|
return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler, inputStreamWrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Terminal newTerminal(
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
InputStream in,
|
||||||
|
OutputStream out,
|
||||||
|
Charset encoding,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
Attributes attributes,
|
||||||
|
Size size)
|
||||||
|
throws IOException {
|
||||||
|
Pty pty = CLibrary.openpty(this, attributes, size);
|
||||||
|
return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSystemStream(SystemStream stream) {
|
||||||
|
if (OSUtils.IS_WINDOWS) {
|
||||||
|
return isWindowsSystemStream(stream);
|
||||||
|
} else {
|
||||||
|
return isPosixSystemStream(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWindowsSystemStream(SystemStream stream) {
|
||||||
|
return NativeWinSysTerminal.isWindowsSystemStream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPosixSystemStream(SystemStream stream) {
|
||||||
|
return FfmNativePty.isPosixSystemStream(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String systemStreamName(SystemStream stream) {
|
||||||
|
return FfmNativePty.posixSystemStreamName(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int systemStreamWidth(SystemStream stream) {
|
||||||
|
return FfmNativePty.systemStreamWidth(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TerminalProvider[" + name() + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
static VarHandle lookupVarHandle(MemoryLayout layout, PathElement... element) {
|
||||||
|
VarHandle h = layout.varHandle(element);
|
||||||
|
|
||||||
|
// the last parameter of the VarHandle is additional offset, hardcode zero:
|
||||||
|
h = MethodHandles.insertCoordinates(h, h.coordinateTypes().size() - 1, 0L);
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,927 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.VarHandle;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@SuppressWarnings({"unused", "restricted"})
|
||||||
|
final class Kernel32 {
|
||||||
|
|
||||||
|
public static final int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
|
||||||
|
|
||||||
|
public static final int INVALID_HANDLE_VALUE = -1;
|
||||||
|
public static final int STD_INPUT_HANDLE = -10;
|
||||||
|
public static final int STD_OUTPUT_HANDLE = -11;
|
||||||
|
public static final int STD_ERROR_HANDLE = -12;
|
||||||
|
|
||||||
|
public static final int ENABLE_PROCESSED_INPUT = 0x0001;
|
||||||
|
public static final int ENABLE_LINE_INPUT = 0x0002;
|
||||||
|
public static final int ENABLE_ECHO_INPUT = 0x0004;
|
||||||
|
public static final int ENABLE_WINDOW_INPUT = 0x0008;
|
||||||
|
public static final int ENABLE_MOUSE_INPUT = 0x0010;
|
||||||
|
public static final int ENABLE_INSERT_MODE = 0x0020;
|
||||||
|
public static final int ENABLE_QUICK_EDIT_MODE = 0x0040;
|
||||||
|
public static final int ENABLE_EXTENDED_FLAGS = 0x0080;
|
||||||
|
|
||||||
|
public static final int RIGHT_ALT_PRESSED = 0x0001;
|
||||||
|
public static final int LEFT_ALT_PRESSED = 0x0002;
|
||||||
|
public static final int RIGHT_CTRL_PRESSED = 0x0004;
|
||||||
|
public static final int LEFT_CTRL_PRESSED = 0x0008;
|
||||||
|
public static final int SHIFT_PRESSED = 0x0010;
|
||||||
|
|
||||||
|
public static final int FOREGROUND_BLUE = 0x0001;
|
||||||
|
public static final int FOREGROUND_GREEN = 0x0002;
|
||||||
|
public static final int FOREGROUND_RED = 0x0004;
|
||||||
|
public static final int FOREGROUND_INTENSITY = 0x0008;
|
||||||
|
public static final int BACKGROUND_BLUE = 0x0010;
|
||||||
|
public static final int BACKGROUND_GREEN = 0x0020;
|
||||||
|
public static final int BACKGROUND_RED = 0x0040;
|
||||||
|
public static final int BACKGROUND_INTENSITY = 0x0080;
|
||||||
|
|
||||||
|
// Button state
|
||||||
|
public static final int FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001;
|
||||||
|
public static final int RIGHTMOST_BUTTON_PRESSED = 0x0002;
|
||||||
|
public static final int FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004;
|
||||||
|
public static final int FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008;
|
||||||
|
public static final int FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010;
|
||||||
|
|
||||||
|
// Event flags
|
||||||
|
public static final int MOUSE_MOVED = 0x0001;
|
||||||
|
public static final int DOUBLE_CLICK = 0x0002;
|
||||||
|
public static final int MOUSE_WHEELED = 0x0004;
|
||||||
|
public static final int MOUSE_HWHEELED = 0x0008;
|
||||||
|
|
||||||
|
// Event types
|
||||||
|
public static final short KEY_EVENT = 0x0001;
|
||||||
|
public static final short MOUSE_EVENT = 0x0002;
|
||||||
|
public static final short WINDOW_BUFFER_SIZE_EVENT = 0x0004;
|
||||||
|
public static final short MENU_EVENT = 0x0008;
|
||||||
|
public static final short FOCUS_EVENT = 0x0010;
|
||||||
|
|
||||||
|
public static int WaitForSingleObject(java.lang.foreign.MemorySegment hHandle, int dwMilliseconds) {
|
||||||
|
MethodHandle mh$ = requireNonNull(WaitForSingleObject$MH, "WaitForSingleObject");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hHandle, dwMilliseconds);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static java.lang.foreign.MemorySegment GetStdHandle(int nStdHandle) {
|
||||||
|
MethodHandle mh$ = requireNonNull(GetStdHandle$MH, "GetStdHandle");
|
||||||
|
try {
|
||||||
|
return (java.lang.foreign.MemorySegment) mh$.invokeExact(nStdHandle);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int FormatMessageW(
|
||||||
|
int dwFlags,
|
||||||
|
java.lang.foreign.MemorySegment lpSource,
|
||||||
|
int dwMessageId,
|
||||||
|
int dwLanguageId,
|
||||||
|
java.lang.foreign.MemorySegment lpBuffer,
|
||||||
|
int nSize,
|
||||||
|
java.lang.foreign.MemorySegment Arguments) {
|
||||||
|
MethodHandle mh$ = requireNonNull(FormatMessageW$MH, "FormatMessageW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(dwFlags, lpSource, dwMessageId, dwLanguageId, lpBuffer, nSize, Arguments);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SetConsoleTextAttribute(java.lang.foreign.MemorySegment hConsoleOutput, short wAttributes) {
|
||||||
|
MethodHandle mh$ = requireNonNull(SetConsoleTextAttribute$MH, "SetConsoleTextAttribute");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleOutput, wAttributes);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SetConsoleMode(java.lang.foreign.MemorySegment hConsoleHandle, int dwMode) {
|
||||||
|
MethodHandle mh$ = requireNonNull(SetConsoleMode$MH, "SetConsoleMode");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleHandle, dwMode);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetConsoleMode(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleHandle, java.lang.foreign.MemorySegment lpMode) {
|
||||||
|
MethodHandle mh$ = requireNonNull(GetConsoleMode$MH, "GetConsoleMode");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleHandle, lpMode);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SetConsoleTitleW(java.lang.foreign.MemorySegment lpConsoleTitle) {
|
||||||
|
MethodHandle mh$ = requireNonNull(SetConsoleTitleW$MH, "SetConsoleTitleW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(lpConsoleTitle);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int SetConsoleCursorPosition(java.lang.foreign.MemorySegment hConsoleOutput, COORD dwCursorPosition) {
|
||||||
|
MethodHandle mh$ = requireNonNull(SetConsoleCursorPosition$MH, "SetConsoleCursorPosition");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleOutput, dwCursorPosition.seg);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int FillConsoleOutputCharacterW(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleOutput,
|
||||||
|
char cCharacter,
|
||||||
|
int nLength,
|
||||||
|
COORD dwWriteCoord,
|
||||||
|
java.lang.foreign.MemorySegment lpNumberOfCharsWritten) {
|
||||||
|
MethodHandle mh$ = requireNonNull(FillConsoleOutputCharacterW$MH, "FillConsoleOutputCharacterW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleOutput, cCharacter, nLength, dwWriteCoord.seg, lpNumberOfCharsWritten);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int FillConsoleOutputAttribute(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleOutput,
|
||||||
|
short wAttribute,
|
||||||
|
int nLength,
|
||||||
|
COORD dwWriteCoord,
|
||||||
|
java.lang.foreign.MemorySegment lpNumberOfAttrsWritten) {
|
||||||
|
MethodHandle mh$ = requireNonNull(FillConsoleOutputAttribute$MH, "FillConsoleOutputAttribute");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleOutput, wAttribute, nLength, dwWriteCoord.seg, lpNumberOfAttrsWritten);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int WriteConsoleW(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleOutput,
|
||||||
|
java.lang.foreign.MemorySegment lpBuffer,
|
||||||
|
int nNumberOfCharsToWrite,
|
||||||
|
java.lang.foreign.MemorySegment lpNumberOfCharsWritten,
|
||||||
|
java.lang.foreign.MemorySegment lpReserved) {
|
||||||
|
MethodHandle mh$ = requireNonNull(WriteConsoleW$MH, "WriteConsoleW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(
|
||||||
|
hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ReadConsoleInputW(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleInput,
|
||||||
|
java.lang.foreign.MemorySegment lpBuffer,
|
||||||
|
int nLength,
|
||||||
|
java.lang.foreign.MemorySegment lpNumberOfEventsRead) {
|
||||||
|
MethodHandle mh$ = requireNonNull(ReadConsoleInputW$MH, "ReadConsoleInputW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int PeekConsoleInputW(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleInput,
|
||||||
|
java.lang.foreign.MemorySegment lpBuffer,
|
||||||
|
int nLength,
|
||||||
|
java.lang.foreign.MemorySegment lpNumberOfEventsRead) {
|
||||||
|
MethodHandle mh$ = requireNonNull(PeekConsoleInputW$MH, "PeekConsoleInputW");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleInput, lpBuffer, nLength, lpNumberOfEventsRead);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetConsoleScreenBufferInfo(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleOutput, CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo) {
|
||||||
|
MethodHandle mh$ = requireNonNull(GetConsoleScreenBufferInfo$MH, "GetConsoleScreenBufferInfo");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hConsoleOutput, lpConsoleScreenBufferInfo.seg);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int ScrollConsoleScreenBuffer(
|
||||||
|
java.lang.foreign.MemorySegment hConsoleOutput,
|
||||||
|
SMALL_RECT lpScrollRectangle,
|
||||||
|
SMALL_RECT lpClipRectangle,
|
||||||
|
COORD dwDestinationOrigin,
|
||||||
|
CHAR_INFO lpFill) {
|
||||||
|
MethodHandle mh$ = requireNonNull(ScrollConsoleScreenBufferW$MH, "ScrollConsoleScreenBuffer");
|
||||||
|
try {
|
||||||
|
return (int)
|
||||||
|
mh$.invokeExact(hConsoleOutput, lpScrollRectangle, lpClipRectangle, dwDestinationOrigin, lpFill);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetLastError() {
|
||||||
|
MethodHandle mh$ = requireNonNull(GetLastError$MH, "GetLastError");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact();
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetFileType(java.lang.foreign.MemorySegment hFile) {
|
||||||
|
MethodHandle mh$ = requireNonNull(GetFileType$MH, "GetFileType");
|
||||||
|
try {
|
||||||
|
return (int) mh$.invokeExact(hFile);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static java.lang.foreign.MemorySegment _get_osfhandle(int fd) {
|
||||||
|
MethodHandle mh$ = requireNonNull(_get_osfhandle$MH, "_get_osfhandle");
|
||||||
|
try {
|
||||||
|
return (java.lang.foreign.MemorySegment) mh$.invokeExact(fd);
|
||||||
|
} catch (Throwable ex$) {
|
||||||
|
throw new AssertionError("should not reach here", ex$);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static INPUT_RECORD[] readConsoleInputHelper(java.lang.foreign.MemorySegment handle, int count, boolean peek)
|
||||||
|
throws IOException {
|
||||||
|
return readConsoleInputHelper(java.lang.foreign.Arena.ofAuto(), handle, count, peek);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static INPUT_RECORD[] readConsoleInputHelper(
|
||||||
|
java.lang.foreign.Arena arena, java.lang.foreign.MemorySegment handle, int count, boolean peek)
|
||||||
|
throws IOException {
|
||||||
|
java.lang.foreign.MemorySegment inputRecordPtr = arena.allocate(INPUT_RECORD.LAYOUT, count);
|
||||||
|
java.lang.foreign.MemorySegment length = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT, 1);
|
||||||
|
int res = peek
|
||||||
|
? PeekConsoleInputW(handle, inputRecordPtr, count, length)
|
||||||
|
: ReadConsoleInputW(handle, inputRecordPtr, count, length);
|
||||||
|
if (res == 0) {
|
||||||
|
throw new IOException("ReadConsoleInputW failed: " + getLastErrorMessage());
|
||||||
|
}
|
||||||
|
int len = length.get(java.lang.foreign.ValueLayout.JAVA_INT, 0);
|
||||||
|
return inputRecordPtr
|
||||||
|
.elements(INPUT_RECORD.LAYOUT)
|
||||||
|
.map(INPUT_RECORD::new)
|
||||||
|
.limit(len)
|
||||||
|
.toArray(INPUT_RECORD[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getLastErrorMessage() {
|
||||||
|
int errorCode = GetLastError();
|
||||||
|
return getErrorMessage(errorCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getErrorMessage(int errorCode) {
|
||||||
|
int bufferSize = 160;
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment data = arena.allocate(bufferSize);
|
||||||
|
FormatMessageW(
|
||||||
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
|
java.lang.foreign.MemorySegment.NULL,
|
||||||
|
errorCode,
|
||||||
|
0,
|
||||||
|
data,
|
||||||
|
bufferSize,
|
||||||
|
java.lang.foreign.MemorySegment.NULL);
|
||||||
|
return new String(data.toArray(java.lang.foreign.ValueLayout.JAVA_BYTE), StandardCharsets.UTF_16LE).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final java.lang.foreign.SymbolLookup SYMBOL_LOOKUP;
|
||||||
|
|
||||||
|
static {
|
||||||
|
System.loadLibrary("msvcrt");
|
||||||
|
System.loadLibrary("Kernel32");
|
||||||
|
SYMBOL_LOOKUP = java.lang.foreign.SymbolLookup.loaderLookup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static MethodHandle downcallHandle(String name, java.lang.foreign.FunctionDescriptor fdesc) {
|
||||||
|
return SYMBOL_LOOKUP
|
||||||
|
.find(name)
|
||||||
|
.map(addr -> java.lang.foreign.Linker.nativeLinker().downcallHandle(addr, fdesc))
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static final java.lang.foreign.ValueLayout.OfBoolean C_BOOL$LAYOUT = java.lang.foreign.ValueLayout.JAVA_BOOLEAN;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfByte C_CHAR$LAYOUT = java.lang.foreign.ValueLayout.JAVA_BYTE;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfChar C_WCHAR$LAYOUT = java.lang.foreign.ValueLayout.JAVA_CHAR;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfShort C_SHORT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_SHORT;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfShort C_WORD$LAYOUT = java.lang.foreign.ValueLayout.JAVA_SHORT;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfInt C_DWORD$LAYOUT = java.lang.foreign.ValueLayout.JAVA_INT;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfInt C_INT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_INT;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfLong C_LONG$LAYOUT = java.lang.foreign.ValueLayout.JAVA_LONG;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfLong C_LONG_LONG$LAYOUT = java.lang.foreign.ValueLayout.JAVA_LONG;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfFloat C_FLOAT$LAYOUT = java.lang.foreign.ValueLayout.JAVA_FLOAT;
|
||||||
|
static final java.lang.foreign.ValueLayout.OfDouble C_DOUBLE$LAYOUT = java.lang.foreign.ValueLayout.JAVA_DOUBLE;
|
||||||
|
static final java.lang.foreign.AddressLayout C_POINTER$LAYOUT = java.lang.foreign.ValueLayout.ADDRESS;
|
||||||
|
|
||||||
|
static final MethodHandle WaitForSingleObject$MH = downcallHandle(
|
||||||
|
"WaitForSingleObject",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT));
|
||||||
|
static final MethodHandle GetStdHandle$MH =
|
||||||
|
downcallHandle("GetStdHandle", java.lang.foreign.FunctionDescriptor.of(C_POINTER$LAYOUT, C_INT$LAYOUT));
|
||||||
|
static final MethodHandle FormatMessageW$MH = downcallHandle(
|
||||||
|
"FormatMessageW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle SetConsoleTextAttribute$MH = downcallHandle(
|
||||||
|
"SetConsoleTextAttribute",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_SHORT$LAYOUT));
|
||||||
|
static final MethodHandle SetConsoleMode$MH = downcallHandle(
|
||||||
|
"SetConsoleMode", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT));
|
||||||
|
static final MethodHandle GetConsoleMode$MH = downcallHandle(
|
||||||
|
"GetConsoleMode",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
|
||||||
|
static final MethodHandle SetConsoleTitleW$MH =
|
||||||
|
downcallHandle("SetConsoleTitleW", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle SetConsoleCursorPosition$MH = downcallHandle(
|
||||||
|
"SetConsoleCursorPosition",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, COORD.LAYOUT));
|
||||||
|
static final MethodHandle FillConsoleOutputCharacterW$MH = downcallHandle(
|
||||||
|
"FillConsoleOutputCharacterW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT, C_POINTER$LAYOUT, C_WCHAR$LAYOUT, C_INT$LAYOUT, COORD.LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle FillConsoleOutputAttribute$MH = downcallHandle(
|
||||||
|
"FillConsoleOutputAttribute",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT, C_POINTER$LAYOUT, C_SHORT$LAYOUT, C_INT$LAYOUT, COORD.LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle WriteConsoleW$MH = downcallHandle(
|
||||||
|
"WriteConsoleW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT));
|
||||||
|
|
||||||
|
static final MethodHandle ReadConsoleInputW$MH = downcallHandle(
|
||||||
|
"ReadConsoleInputW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle PeekConsoleInputW$MH = downcallHandle(
|
||||||
|
"PeekConsoleInputW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT, C_INT$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
|
||||||
|
static final MethodHandle GetConsoleScreenBufferInfo$MH = downcallHandle(
|
||||||
|
"GetConsoleScreenBufferInfo",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
|
||||||
|
static final MethodHandle ScrollConsoleScreenBufferW$MH = downcallHandle(
|
||||||
|
"ScrollConsoleScreenBufferW",
|
||||||
|
java.lang.foreign.FunctionDescriptor.of(
|
||||||
|
C_INT$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
C_POINTER$LAYOUT,
|
||||||
|
COORD.LAYOUT,
|
||||||
|
C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle GetLastError$MH =
|
||||||
|
downcallHandle("GetLastError", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT));
|
||||||
|
static final MethodHandle GetFileType$MH =
|
||||||
|
downcallHandle("GetFileType", java.lang.foreign.FunctionDescriptor.of(C_INT$LAYOUT, C_POINTER$LAYOUT));
|
||||||
|
static final MethodHandle _get_osfhandle$MH =
|
||||||
|
downcallHandle("_get_osfhandle", java.lang.foreign.FunctionDescriptor.of(C_POINTER$LAYOUT, C_INT$LAYOUT));
|
||||||
|
|
||||||
|
public static final class INPUT_RECORD {
|
||||||
|
static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_SHORT.withName("EventType"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_SHORT, // padding
|
||||||
|
java.lang.foreign.MemoryLayout.unionLayout(
|
||||||
|
KEY_EVENT_RECORD.LAYOUT.withName("KeyEvent"),
|
||||||
|
MOUSE_EVENT_RECORD.LAYOUT.withName("MouseEvent"),
|
||||||
|
WINDOW_BUFFER_SIZE_RECORD.LAYOUT.withName("WindowBufferSizeEvent"),
|
||||||
|
MENU_EVENT_RECORD.LAYOUT.withName("MenuEvent"),
|
||||||
|
FOCUS_EVENT_RECORD.LAYOUT.withName("FocusEvent"))
|
||||||
|
.withName("Event"));
|
||||||
|
static final VarHandle EventType$VH = varHandle(LAYOUT, "EventType");
|
||||||
|
static final long Event$OFFSET = byteOffset(LAYOUT, "Event");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public INPUT_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public INPUT_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public INPUT_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short eventType() {
|
||||||
|
return (short) EventType$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KEY_EVENT_RECORD keyEvent() {
|
||||||
|
return new KEY_EVENT_RECORD(seg, Event$OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MOUSE_EVENT_RECORD mouseEvent() {
|
||||||
|
return new MOUSE_EVENT_RECORD(seg, Event$OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FOCUS_EVENT_RECORD focusEvent() {
|
||||||
|
return new FOCUS_EVENT_RECORD(seg, Event$OFFSET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class MENU_EVENT_RECORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT =
|
||||||
|
java.lang.foreign.MemoryLayout.structLayout(C_DWORD$LAYOUT.withName("dwCommandId"));
|
||||||
|
static final VarHandle COMMAND_ID = varHandle(LAYOUT, "dwCommandId");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public MENU_EVENT_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MENU_EVENT_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MENU_EVENT_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int commandId() {
|
||||||
|
return (int) MENU_EVENT_RECORD.COMMAND_ID.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void commandId(int commandId) {
|
||||||
|
MENU_EVENT_RECORD.COMMAND_ID.set(seg, commandId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class FOCUS_EVENT_RECORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT =
|
||||||
|
java.lang.foreign.MemoryLayout.structLayout(C_INT$LAYOUT.withName("bSetFocus"));
|
||||||
|
static final VarHandle SET_FOCUS = varHandle(LAYOUT, "bSetFocus");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public FOCUS_EVENT_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public FOCUS_EVENT_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public FOCUS_EVENT_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = Objects.requireNonNull(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FOCUS_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) {
|
||||||
|
this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setFocus() {
|
||||||
|
return ((int) FOCUS_EVENT_RECORD.SET_FOCUS.get(seg) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFocus(boolean setFocus) {
|
||||||
|
FOCUS_EVENT_RECORD.SET_FOCUS.set(seg, setFocus ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class WINDOW_BUFFER_SIZE_RECORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT =
|
||||||
|
java.lang.foreign.MemoryLayout.structLayout(COORD.LAYOUT.withName("size"));
|
||||||
|
static final long SIZE_OFFSET = byteOffset(LAYOUT, "size");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public WINDOW_BUFFER_SIZE_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public WINDOW_BUFFER_SIZE_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public WINDOW_BUFFER_SIZE_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD size() {
|
||||||
|
return new COORD(seg, SIZE_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "WINDOW_BUFFER_SIZE_RECORD{size=" + this.size() + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class MOUSE_EVENT_RECORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
COORD.LAYOUT.withName("dwMousePosition"),
|
||||||
|
C_DWORD$LAYOUT.withName("dwButtonState"),
|
||||||
|
C_DWORD$LAYOUT.withName("dwControlKeyState"),
|
||||||
|
C_DWORD$LAYOUT.withName("dwEventFlags"));
|
||||||
|
static final long MOUSE_POSITION_OFFSET = byteOffset(LAYOUT, "dwMousePosition");
|
||||||
|
static final VarHandle BUTTON_STATE = varHandle(LAYOUT, "dwButtonState");
|
||||||
|
static final VarHandle CONTROL_KEY_STATE = varHandle(LAYOUT, "dwControlKeyState");
|
||||||
|
static final VarHandle EVENT_FLAGS = varHandle(LAYOUT, "dwEventFlags");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public MOUSE_EVENT_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MOUSE_EVENT_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MOUSE_EVENT_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = Objects.requireNonNull(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MOUSE_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) {
|
||||||
|
this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD mousePosition() {
|
||||||
|
return new COORD(seg, MOUSE_POSITION_OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int buttonState() {
|
||||||
|
return (int) BUTTON_STATE.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int controlKeyState() {
|
||||||
|
return (int) CONTROL_KEY_STATE.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int eventFlags() {
|
||||||
|
return (int) EVENT_FLAGS.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MOUSE_EVENT_RECORD{mousePosition=" + mousePosition() + ", buttonState=" + buttonState()
|
||||||
|
+ ", controlKeyState=" + controlKeyState() + ", eventFlags=" + eventFlags() + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class KEY_EVENT_RECORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.MemoryLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_INT.withName("bKeyDown"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wRepeatCount"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wVirtualKeyCode"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_SHORT.withName("wVirtualScanCode"),
|
||||||
|
java.lang.foreign.MemoryLayout.unionLayout(
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_CHAR.withName("UnicodeChar"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_BYTE.withName("AsciiChar"))
|
||||||
|
.withName("uChar"),
|
||||||
|
java.lang.foreign.ValueLayout.JAVA_INT.withName("dwControlKeyState"));
|
||||||
|
static final VarHandle bKeyDown$VH = varHandle(LAYOUT, "bKeyDown");
|
||||||
|
static final VarHandle wRepeatCount$VH = varHandle(LAYOUT, "wRepeatCount");
|
||||||
|
static final VarHandle wVirtualKeyCode$VH = varHandle(LAYOUT, "wVirtualKeyCode");
|
||||||
|
static final VarHandle wVirtualScanCode$VH = varHandle(LAYOUT, "wVirtualScanCode");
|
||||||
|
static final VarHandle UnicodeChar$VH = varHandle(LAYOUT, "uChar", "UnicodeChar");
|
||||||
|
static final VarHandle AsciiChar$VH = varHandle(LAYOUT, "uChar", "AsciiChar");
|
||||||
|
static final VarHandle dwControlKeyState$VH = varHandle(LAYOUT, "dwControlKeyState");
|
||||||
|
|
||||||
|
final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public KEY_EVENT_RECORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public KEY_EVENT_RECORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public KEY_EVENT_RECORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KEY_EVENT_RECORD(java.lang.foreign.MemorySegment seg, long offset) {
|
||||||
|
this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean keyDown() {
|
||||||
|
return ((int) bKeyDown$VH.get(seg)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int repeatCount() {
|
||||||
|
return (int) wRepeatCount$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short keyCode() {
|
||||||
|
return (short) wVirtualKeyCode$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short scanCode() {
|
||||||
|
return (short) wVirtualScanCode$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char uchar() {
|
||||||
|
return (char) UnicodeChar$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int controlKeyState() {
|
||||||
|
return (int) dwControlKeyState$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "KEY_EVENT_RECORD{keyDown=" + this.keyDown() + ", repeatCount=" + this.repeatCount() + ", keyCode="
|
||||||
|
+ this.keyCode() + ", scanCode=" + this.scanCode() + ", uchar=" + this.uchar()
|
||||||
|
+ ", controlKeyState="
|
||||||
|
+ this.controlKeyState() + '}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class CHAR_INFO {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
java.lang.foreign.MemoryLayout.unionLayout(
|
||||||
|
C_WCHAR$LAYOUT.withName("UnicodeChar"), C_CHAR$LAYOUT.withName("AsciiChar"))
|
||||||
|
.withName("Char"),
|
||||||
|
C_WORD$LAYOUT.withName("Attributes"));
|
||||||
|
static final VarHandle UnicodeChar$VH = varHandle(LAYOUT, "Char", "UnicodeChar");
|
||||||
|
static final VarHandle Attributes$VH = varHandle(LAYOUT, "Attributes");
|
||||||
|
|
||||||
|
final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public CHAR_INFO() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CHAR_INFO(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CHAR_INFO(java.lang.foreign.Arena arena, char c, short a) {
|
||||||
|
this(arena);
|
||||||
|
UnicodeChar$VH.set(seg, c);
|
||||||
|
Attributes$VH.set(seg, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CHAR_INFO(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char unicodeChar() {
|
||||||
|
return (char) UnicodeChar$VH.get(seg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class CONSOLE_SCREEN_BUFFER_INFO {
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
COORD.LAYOUT.withName("dwSize"),
|
||||||
|
COORD.LAYOUT.withName("dwCursorPosition"),
|
||||||
|
C_WORD$LAYOUT.withName("wAttributes"),
|
||||||
|
SMALL_RECT.LAYOUT.withName("srWindow"),
|
||||||
|
COORD.LAYOUT.withName("dwMaximumWindowSize"));
|
||||||
|
static final long dwSize$OFFSET = byteOffset(LAYOUT, "dwSize");
|
||||||
|
static final long dwCursorPosition$OFFSET = byteOffset(LAYOUT, "dwCursorPosition");
|
||||||
|
static final VarHandle wAttributes$VH = varHandle(LAYOUT, "wAttributes");
|
||||||
|
static final long srWindow$OFFSET = byteOffset(LAYOUT, "srWindow");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public CONSOLE_SCREEN_BUFFER_INFO() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD size() {
|
||||||
|
return new COORD(seg, dwSize$OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD cursorPosition() {
|
||||||
|
return new COORD(seg, dwCursorPosition$OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short attributes() {
|
||||||
|
return (short) wAttributes$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT window() {
|
||||||
|
return new SMALL_RECT(seg, srWindow$OFFSET);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int windowWidth() {
|
||||||
|
return this.window().width() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int windowHeight() {
|
||||||
|
return this.window().height() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void attributes(short attr) {
|
||||||
|
wAttributes$VH.set(seg, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class COORD {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT =
|
||||||
|
java.lang.foreign.MemoryLayout.structLayout(C_SHORT$LAYOUT.withName("x"), C_SHORT$LAYOUT.withName("y"));
|
||||||
|
static final VarHandle x$VH = varHandle(LAYOUT, "x");
|
||||||
|
static final VarHandle y$VH = varHandle(LAYOUT, "y");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public COORD() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD(java.lang.foreign.Arena arena, short x, short y) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
x(x);
|
||||||
|
y(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD(java.lang.foreign.MemorySegment seg, long offset) {
|
||||||
|
this.seg = Objects.requireNonNull(seg).asSlice(offset, LAYOUT.byteSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
public short x() {
|
||||||
|
return (short) COORD.x$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void x(short x) {
|
||||||
|
COORD.x$VH.set(seg, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short y() {
|
||||||
|
return (short) COORD.y$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void y(short y) {
|
||||||
|
COORD.y$VH.set(seg, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public COORD copy(java.lang.foreign.Arena arena) {
|
||||||
|
return new COORD(arena.allocate(LAYOUT).copyFrom(seg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class SMALL_RECT {
|
||||||
|
|
||||||
|
static final java.lang.foreign.GroupLayout LAYOUT = java.lang.foreign.MemoryLayout.structLayout(
|
||||||
|
C_SHORT$LAYOUT.withName("Left"),
|
||||||
|
C_SHORT$LAYOUT.withName("Top"),
|
||||||
|
C_SHORT$LAYOUT.withName("Right"),
|
||||||
|
C_SHORT$LAYOUT.withName("Bottom"));
|
||||||
|
static final VarHandle Left$VH = varHandle(LAYOUT, "Left");
|
||||||
|
static final VarHandle Top$VH = varHandle(LAYOUT, "Top");
|
||||||
|
static final VarHandle Right$VH = varHandle(LAYOUT, "Right");
|
||||||
|
static final VarHandle Bottom$VH = varHandle(LAYOUT, "Bottom");
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment seg;
|
||||||
|
|
||||||
|
public SMALL_RECT() {
|
||||||
|
this(java.lang.foreign.Arena.ofAuto());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT(java.lang.foreign.Arena arena) {
|
||||||
|
this(arena.allocate(LAYOUT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT(java.lang.foreign.Arena arena, SMALL_RECT rect) {
|
||||||
|
this(arena);
|
||||||
|
left(rect.left());
|
||||||
|
right(rect.right());
|
||||||
|
top(rect.top());
|
||||||
|
bottom(rect.bottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT(java.lang.foreign.MemorySegment seg, long offset) {
|
||||||
|
this(seg.asSlice(offset, LAYOUT.byteSize()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT(java.lang.foreign.MemorySegment seg) {
|
||||||
|
this.seg = seg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short left() {
|
||||||
|
return (short) Left$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short top() {
|
||||||
|
return (short) Top$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short right() {
|
||||||
|
return (short) Right$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short bottom() {
|
||||||
|
return (short) Bottom$VH.get(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short width() {
|
||||||
|
return (short) (this.right() - this.left());
|
||||||
|
}
|
||||||
|
|
||||||
|
public short height() {
|
||||||
|
return (short) (this.bottom() - this.top());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void left(short l) {
|
||||||
|
Left$VH.set(seg, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void top(short t) {
|
||||||
|
Top$VH.set(seg, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void right(short r) {
|
||||||
|
Right$VH.set(seg, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bottom(short b) {
|
||||||
|
Bottom$VH.set(seg, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SMALL_RECT copy(java.lang.foreign.Arena arena) {
|
||||||
|
return new SMALL_RECT(arena.allocate(LAYOUT).copyFrom(seg));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> T requireNonNull(T obj, String symbolName) {
|
||||||
|
if (obj == null) {
|
||||||
|
throw new UnsatisfiedLinkError("unresolved symbol: " + symbolName);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VarHandle varHandle(java.lang.foreign.MemoryLayout layout, String name) {
|
||||||
|
return FfmTerminalProvider.lookupVarHandle(
|
||||||
|
layout, java.lang.foreign.MemoryLayout.PathElement.groupElement(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static VarHandle varHandle(java.lang.foreign.MemoryLayout layout, String e1, String name) {
|
||||||
|
return FfmTerminalProvider.lookupVarHandle(
|
||||||
|
layout,
|
||||||
|
java.lang.foreign.MemoryLayout.PathElement.groupElement(e1),
|
||||||
|
java.lang.foreign.MemoryLayout.PathElement.groupElement(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static long byteOffset(java.lang.foreign.MemoryLayout layout, String name) {
|
||||||
|
return layout.byteOffset(java.lang.foreign.MemoryLayout.PathElement.groupElement(name));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.foreign.MemorySegment;
|
||||||
|
import java.lang.foreign.ValueLayout;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.impl.AbstractWindowsConsoleWriter;
|
||||||
|
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.WriteConsoleW;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage;
|
||||||
|
|
||||||
|
class NativeWinConsoleWriter extends AbstractWindowsConsoleWriter {
|
||||||
|
|
||||||
|
private final java.lang.foreign.MemorySegment console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void writeConsole(char[] text, int len) throws IOException {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment txt = arena.allocateFrom(ValueLayout.JAVA_CHAR, text);
|
||||||
|
if (WriteConsoleW(console, txt, len, MemorySegment.NULL, MemorySegment.NULL) == 0) {
|
||||||
|
throw new IOException("Failed to write to console: " + getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOError;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Cursor;
|
||||||
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.SystemStream;
|
||||||
|
import jdk.internal.org.jline.terminal.spi.TerminalProvider;
|
||||||
|
import jdk.internal.org.jline.utils.OSUtils;
|
||||||
|
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.*;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleMode;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleScreenBufferInfo;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.INPUT_RECORD;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.INVALID_HANDLE_VALUE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.KEY_EVENT_RECORD;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.MOUSE_EVENT_RECORD;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_ERROR_HANDLE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_INPUT_HANDLE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleMode;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.WaitForSingleObject;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.readConsoleInputHelper;
|
||||||
|
|
||||||
|
public class NativeWinSysTerminal extends AbstractWindowsTerminal<java.lang.foreign.MemorySegment> {
|
||||||
|
|
||||||
|
public static NativeWinSysTerminal createTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
SystemStream systemStream,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
// Get input console mode
|
||||||
|
java.lang.foreign.MemorySegment consoleIn = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
java.lang.foreign.MemorySegment inMode = allocateInt(arena);
|
||||||
|
if (GetConsoleMode(consoleIn, inMode) == 0) {
|
||||||
|
throw new IOException("Failed to get console mode: " + getLastErrorMessage());
|
||||||
|
}
|
||||||
|
// Get output console and mode
|
||||||
|
java.lang.foreign.MemorySegment console;
|
||||||
|
switch (systemStream) {
|
||||||
|
case Output:
|
||||||
|
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
break;
|
||||||
|
case Error:
|
||||||
|
console = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unsupported stream for console: " + systemStream);
|
||||||
|
}
|
||||||
|
java.lang.foreign.MemorySegment outMode = allocateInt(arena);
|
||||||
|
if (GetConsoleMode(console, outMode) == 0) {
|
||||||
|
throw new IOException("Failed to get console mode: " + getLastErrorMessage());
|
||||||
|
}
|
||||||
|
// Create writer
|
||||||
|
Writer writer;
|
||||||
|
if (ansiPassThrough) {
|
||||||
|
type = type != null ? type : OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS;
|
||||||
|
writer = new NativeWinConsoleWriter();
|
||||||
|
} else {
|
||||||
|
int m = inMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0);
|
||||||
|
if (enableVtp(console, m)) {
|
||||||
|
type = type != null ? type : TYPE_WINDOWS_VTP;
|
||||||
|
writer = new NativeWinConsoleWriter();
|
||||||
|
} else if (OSUtils.IS_CONEMU) {
|
||||||
|
type = type != null ? type : TYPE_WINDOWS_CONEMU;
|
||||||
|
writer = new NativeWinConsoleWriter();
|
||||||
|
} else {
|
||||||
|
type = type != null ? type : TYPE_WINDOWS;
|
||||||
|
writer = new WindowsAnsiWriter(new BufferedWriter(new NativeWinConsoleWriter()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Create terminal
|
||||||
|
NativeWinSysTerminal terminal = new NativeWinSysTerminal(
|
||||||
|
provider,
|
||||||
|
systemStream,
|
||||||
|
writer,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
encoding,
|
||||||
|
nativeSignals,
|
||||||
|
signalHandler,
|
||||||
|
consoleIn,
|
||||||
|
inMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0),
|
||||||
|
console,
|
||||||
|
outMode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0),
|
||||||
|
inputStreamWrapper);
|
||||||
|
// Start input pump thread
|
||||||
|
if (!paused) {
|
||||||
|
terminal.resume();
|
||||||
|
}
|
||||||
|
return terminal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean enableVtp(java.lang.foreign.MemorySegment console, int m) {
|
||||||
|
return SetConsoleMode(console, m | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isWindowsSystemStream(SystemStream stream) {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment console;
|
||||||
|
java.lang.foreign.MemorySegment mode = allocateInt(arena);
|
||||||
|
switch (stream) {
|
||||||
|
case Input:
|
||||||
|
console = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
break;
|
||||||
|
case Output:
|
||||||
|
console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
break;
|
||||||
|
case Error:
|
||||||
|
console = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return GetConsoleMode(console, mode) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static java.lang.foreign.MemorySegment allocateInt(java.lang.foreign.Arena arena) {
|
||||||
|
return arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeWinSysTerminal(
|
||||||
|
TerminalProvider provider,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Writer writer,
|
||||||
|
String name,
|
||||||
|
String type,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
SignalHandler signalHandler,
|
||||||
|
java.lang.foreign.MemorySegment inConsole,
|
||||||
|
int inConsoleMode,
|
||||||
|
java.lang.foreign.MemorySegment outConsole,
|
||||||
|
int outConsoleMode,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException {
|
||||||
|
super(
|
||||||
|
provider,
|
||||||
|
systemStream,
|
||||||
|
writer,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
encoding,
|
||||||
|
nativeSignals,
|
||||||
|
signalHandler,
|
||||||
|
inConsole,
|
||||||
|
inConsoleMode,
|
||||||
|
outConsole,
|
||||||
|
outConsoleMode,
|
||||||
|
inputStreamWrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getConsoleMode(java.lang.foreign.MemorySegment console) {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment mode = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT);
|
||||||
|
if (GetConsoleMode(console, mode) == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return mode.get(java.lang.foreign.ValueLayout.JAVA_INT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setConsoleMode(java.lang.foreign.MemorySegment console, int mode) {
|
||||||
|
SetConsoleMode(console, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size getSize() {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena);
|
||||||
|
GetConsoleScreenBufferInfo(outConsole, info);
|
||||||
|
return new Size(info.windowWidth(), info.windowHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Size getBufferSize() {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena);
|
||||||
|
GetConsoleScreenBufferInfo(outConsole, info);
|
||||||
|
return new Size(info.size().x(), info.size().y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean processConsoleInput() throws IOException {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
INPUT_RECORD[] events;
|
||||||
|
if (inConsole != null
|
||||||
|
&& inConsole.address() != INVALID_HANDLE_VALUE
|
||||||
|
&& WaitForSingleObject(inConsole, 100) == 0) {
|
||||||
|
events = readConsoleInputHelper(arena, inConsole, 1, false);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flush = false;
|
||||||
|
for (INPUT_RECORD event : events) {
|
||||||
|
int eventType = event.eventType();
|
||||||
|
if (eventType == KEY_EVENT) {
|
||||||
|
KEY_EVENT_RECORD keyEvent = event.keyEvent();
|
||||||
|
processKeyEvent(
|
||||||
|
keyEvent.keyDown(), keyEvent.keyCode(), keyEvent.uchar(), keyEvent.controlKeyState());
|
||||||
|
flush = true;
|
||||||
|
} else if (eventType == WINDOW_BUFFER_SIZE_EVENT) {
|
||||||
|
raise(Signal.WINCH);
|
||||||
|
} else if (eventType == MOUSE_EVENT) {
|
||||||
|
processMouseEvent(event.mouseEvent());
|
||||||
|
flush = true;
|
||||||
|
} else if (eventType == FOCUS_EVENT) {
|
||||||
|
processFocusEvent(event.focusEvent().setFocus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final char[] focus = new char[] {'\033', '[', ' '};
|
||||||
|
|
||||||
|
private void processFocusEvent(boolean hasFocus) throws IOException {
|
||||||
|
if (focusTracking) {
|
||||||
|
focus[2] = hasFocus ? 'I' : 'O';
|
||||||
|
slaveInputPipe.write(focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final char[] mouse = new char[] {'\033', '[', 'M', ' ', ' ', ' '};
|
||||||
|
|
||||||
|
private void processMouseEvent(MOUSE_EVENT_RECORD mouseEvent) throws IOException {
|
||||||
|
int dwEventFlags = mouseEvent.eventFlags();
|
||||||
|
int dwButtonState = mouseEvent.buttonState();
|
||||||
|
if (tracking == MouseTracking.Off
|
||||||
|
|| tracking == MouseTracking.Normal && dwEventFlags == MOUSE_MOVED
|
||||||
|
|| tracking == MouseTracking.Button && dwEventFlags == MOUSE_MOVED && dwButtonState == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int cb = 0;
|
||||||
|
dwEventFlags &= ~DOUBLE_CLICK; // Treat double-clicks as normal
|
||||||
|
if (dwEventFlags == MOUSE_WHEELED) {
|
||||||
|
cb |= 64;
|
||||||
|
if ((dwButtonState >> 16) < 0) {
|
||||||
|
cb |= 1;
|
||||||
|
}
|
||||||
|
} else if (dwEventFlags == MOUSE_HWHEELED) {
|
||||||
|
return;
|
||||||
|
} else if ((dwButtonState & FROM_LEFT_1ST_BUTTON_PRESSED) != 0) {
|
||||||
|
cb |= 0x00;
|
||||||
|
} else if ((dwButtonState & RIGHTMOST_BUTTON_PRESSED) != 0) {
|
||||||
|
cb |= 0x01;
|
||||||
|
} else if ((dwButtonState & FROM_LEFT_2ND_BUTTON_PRESSED) != 0) {
|
||||||
|
cb |= 0x02;
|
||||||
|
} else {
|
||||||
|
cb |= 0x03;
|
||||||
|
}
|
||||||
|
int cx = mouseEvent.mousePosition().x();
|
||||||
|
int cy = mouseEvent.mousePosition().y();
|
||||||
|
mouse[3] = (char) (' ' + cb);
|
||||||
|
mouse[4] = (char) (' ' + cx + 1);
|
||||||
|
mouse[5] = (char) (' ' + cy + 1);
|
||||||
|
slaveInputPipe.write(mouse);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Cursor getCursorPosition(IntConsumer discarded) {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(arena);
|
||||||
|
if (GetConsoleScreenBufferInfo(outConsole, info) == 0) {
|
||||||
|
throw new IOError(new IOException("Could not get the cursor position: " + getLastErrorMessage()));
|
||||||
|
}
|
||||||
|
return new Cursor(info.cursorPosition().x(), info.cursorPosition().y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,407 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.impl.ffm;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.utils.AnsiWriter;
|
||||||
|
import jdk.internal.org.jline.utils.Colors;
|
||||||
|
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_BLUE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_GREEN;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_INTENSITY;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.BACKGROUND_RED;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.CHAR_INFO;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.CONSOLE_SCREEN_BUFFER_INFO;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.COORD;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_BLUE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_GREEN;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_INTENSITY;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FOREGROUND_RED;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FillConsoleOutputAttribute;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.FillConsoleOutputCharacterW;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetConsoleScreenBufferInfo;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.GetStdHandle;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SMALL_RECT;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.STD_OUTPUT_HANDLE;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.ScrollConsoleScreenBuffer;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleCursorPosition;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleTextAttribute;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.SetConsoleTitleW;
|
||||||
|
import static jdk.internal.org.jline.terminal.impl.ffm.Kernel32.getLastErrorMessage;
|
||||||
|
|
||||||
|
class WindowsAnsiWriter extends AnsiWriter {
|
||||||
|
|
||||||
|
private static final java.lang.foreign.MemorySegment console = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
|
||||||
|
private static final short FOREGROUND_BLACK = 0;
|
||||||
|
private static final short FOREGROUND_YELLOW = (short) (FOREGROUND_RED | FOREGROUND_GREEN);
|
||||||
|
private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE | FOREGROUND_RED);
|
||||||
|
private static final short FOREGROUND_CYAN = (short) (FOREGROUND_BLUE | FOREGROUND_GREEN);
|
||||||
|
private static final short FOREGROUND_WHITE = (short) (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
|
||||||
|
|
||||||
|
private static final short BACKGROUND_BLACK = 0;
|
||||||
|
private static final short BACKGROUND_YELLOW = (short) (BACKGROUND_RED | BACKGROUND_GREEN);
|
||||||
|
private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE | BACKGROUND_RED);
|
||||||
|
private static final short BACKGROUND_CYAN = (short) (BACKGROUND_BLUE | BACKGROUND_GREEN);
|
||||||
|
private static final short BACKGROUND_WHITE = (short) (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE);
|
||||||
|
|
||||||
|
private static final short[] ANSI_FOREGROUND_COLOR_MAP = {
|
||||||
|
FOREGROUND_BLACK,
|
||||||
|
FOREGROUND_RED,
|
||||||
|
FOREGROUND_GREEN,
|
||||||
|
FOREGROUND_YELLOW,
|
||||||
|
FOREGROUND_BLUE,
|
||||||
|
FOREGROUND_MAGENTA,
|
||||||
|
FOREGROUND_CYAN,
|
||||||
|
FOREGROUND_WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final short[] ANSI_BACKGROUND_COLOR_MAP = {
|
||||||
|
BACKGROUND_BLACK,
|
||||||
|
BACKGROUND_RED,
|
||||||
|
BACKGROUND_GREEN,
|
||||||
|
BACKGROUND_YELLOW,
|
||||||
|
BACKGROUND_BLUE,
|
||||||
|
BACKGROUND_MAGENTA,
|
||||||
|
BACKGROUND_CYAN,
|
||||||
|
BACKGROUND_WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
private final CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(java.lang.foreign.Arena.ofAuto());
|
||||||
|
private final short originalColors;
|
||||||
|
|
||||||
|
private boolean negative;
|
||||||
|
private boolean bold;
|
||||||
|
private boolean underline;
|
||||||
|
private short savedX = -1;
|
||||||
|
private short savedY = -1;
|
||||||
|
|
||||||
|
public WindowsAnsiWriter(Writer out) throws IOException {
|
||||||
|
super(out);
|
||||||
|
getConsoleInfo();
|
||||||
|
originalColors = info.attributes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getConsoleInfo() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
if (GetConsoleScreenBufferInfo(console, info) == 0) {
|
||||||
|
throw new IOException("Could not get the screen info: " + getLastErrorMessage());
|
||||||
|
}
|
||||||
|
if (negative) {
|
||||||
|
info.attributes(invertAttributeColors(info.attributes()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyAttribute() throws IOException {
|
||||||
|
out.flush();
|
||||||
|
short attributes = info.attributes();
|
||||||
|
// bold is simulated by high foreground intensity
|
||||||
|
if (bold) {
|
||||||
|
attributes |= FOREGROUND_INTENSITY;
|
||||||
|
}
|
||||||
|
// underline is simulated by high foreground intensity
|
||||||
|
if (underline) {
|
||||||
|
attributes |= BACKGROUND_INTENSITY;
|
||||||
|
}
|
||||||
|
if (negative) {
|
||||||
|
attributes = invertAttributeColors(attributes);
|
||||||
|
}
|
||||||
|
if (SetConsoleTextAttribute(console, attributes) == 0) {
|
||||||
|
throw new IOException(getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private short invertAttributeColors(short attributes) {
|
||||||
|
// Swap the the Foreground and Background bits.
|
||||||
|
int fg = 0x000F & attributes;
|
||||||
|
fg <<= 4;
|
||||||
|
int bg = 0X00F0 & attributes;
|
||||||
|
bg >>= 4;
|
||||||
|
attributes = (short) ((attributes & 0xFF00) | fg | bg);
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCursorPosition() throws IOException {
|
||||||
|
info.cursorPosition().x((short)
|
||||||
|
Math.max(0, Math.min(info.size().x() - 1, info.cursorPosition().x())));
|
||||||
|
info.cursorPosition().y((short)
|
||||||
|
Math.max(0, Math.min(info.size().y() - 1, info.cursorPosition().y())));
|
||||||
|
if (SetConsoleCursorPosition(console, info.cursorPosition()) == 0) {
|
||||||
|
throw new IOException(getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processEraseScreen(int eraseOption) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment written = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT);
|
||||||
|
switch (eraseOption) {
|
||||||
|
case ERASE_SCREEN -> {
|
||||||
|
COORD topLeft = new COORD(arena, (short) 0, info.window().top());
|
||||||
|
int screenLength = info.window().height() * info.size().x();
|
||||||
|
FillConsoleOutputAttribute(console, originalColors, screenLength, topLeft, written);
|
||||||
|
FillConsoleOutputCharacterW(console, ' ', screenLength, topLeft, written);
|
||||||
|
}
|
||||||
|
case ERASE_SCREEN_TO_BEGINING -> {
|
||||||
|
COORD topLeft2 = new COORD(arena, (short) 0, info.window().top());
|
||||||
|
int lengthToCursor =
|
||||||
|
(info.cursorPosition().y() - info.window().top())
|
||||||
|
* info.size().x()
|
||||||
|
+ info.cursorPosition().x();
|
||||||
|
FillConsoleOutputAttribute(console, originalColors, lengthToCursor, topLeft2, written);
|
||||||
|
FillConsoleOutputCharacterW(console, ' ', lengthToCursor, topLeft2, written);
|
||||||
|
}
|
||||||
|
case ERASE_SCREEN_TO_END -> {
|
||||||
|
int lengthToEnd =
|
||||||
|
(info.window().bottom() - info.cursorPosition().y())
|
||||||
|
* info.size().x()
|
||||||
|
+ (info.size().x() - info.cursorPosition().x());
|
||||||
|
FillConsoleOutputAttribute(console, originalColors, lengthToEnd, info.cursorPosition(), written);
|
||||||
|
FillConsoleOutputCharacterW(console, ' ', lengthToEnd, info.cursorPosition(), written);
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processEraseLine(int eraseOption) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment written = arena.allocate(java.lang.foreign.ValueLayout.JAVA_INT);
|
||||||
|
switch (eraseOption) {
|
||||||
|
case ERASE_LINE -> {
|
||||||
|
COORD leftColCurrRow =
|
||||||
|
new COORD(arena, (short) 0, info.cursorPosition().y());
|
||||||
|
FillConsoleOutputAttribute(
|
||||||
|
console, originalColors, info.size().x(), leftColCurrRow, written);
|
||||||
|
FillConsoleOutputCharacterW(console, ' ', info.size().x(), leftColCurrRow, written);
|
||||||
|
}
|
||||||
|
case ERASE_LINE_TO_BEGINING -> {
|
||||||
|
COORD leftColCurrRow2 =
|
||||||
|
new COORD(arena, (short) 0, info.cursorPosition().y());
|
||||||
|
FillConsoleOutputAttribute(
|
||||||
|
console, originalColors, info.cursorPosition().x(), leftColCurrRow2, written);
|
||||||
|
FillConsoleOutputCharacterW(
|
||||||
|
console, ' ', info.cursorPosition().x(), leftColCurrRow2, written);
|
||||||
|
}
|
||||||
|
case ERASE_LINE_TO_END -> {
|
||||||
|
int lengthToLastCol =
|
||||||
|
info.size().x() - info.cursorPosition().x();
|
||||||
|
FillConsoleOutputAttribute(
|
||||||
|
console, originalColors, lengthToLastCol, info.cursorPosition(), written);
|
||||||
|
FillConsoleOutputCharacterW(console, ' ', lengthToLastCol, info.cursorPosition(), written);
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void processCursorUpLine(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().x((short) 0);
|
||||||
|
info.cursorPosition().y((short) (info.cursorPosition().y() - count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void processCursorDownLine(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().x((short) 0);
|
||||||
|
info.cursorPosition().y((short) (info.cursorPosition().y() + count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorLeft(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().x((short) (info.cursorPosition().x() - count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorRight(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().x((short) (info.cursorPosition().x() + count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorDown(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
int nb = Math.max(0, info.cursorPosition().y() + count - info.size().y() + 1);
|
||||||
|
if (nb != count) {
|
||||||
|
info.cursorPosition().y((short) (info.cursorPosition().y() + count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
if (nb > 0) {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
SMALL_RECT scroll = new SMALL_RECT(arena, info.window());
|
||||||
|
scroll.top((short) 0);
|
||||||
|
COORD org = new COORD(arena);
|
||||||
|
org.x((short) 0);
|
||||||
|
org.y((short) (-nb));
|
||||||
|
CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors);
|
||||||
|
ScrollConsoleScreenBuffer(console, scroll, scroll, org, info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorUp(int count) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().y((short) (info.cursorPosition().y() - count));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorTo(int row, int col) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().y((short) (info.window().top() + row - 1));
|
||||||
|
info.cursorPosition().x((short) (col - 1));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processCursorToColumn(int x) throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
info.cursorPosition().x((short) (x - 1));
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
|
||||||
|
int color = Colors.roundColor(paletteIndex, 16);
|
||||||
|
info.attributes((short) ((info.attributes() & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]));
|
||||||
|
info.attributes(
|
||||||
|
(short) ((info.attributes() & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0)));
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
|
||||||
|
int color = Colors.roundColor(paletteIndex, 16);
|
||||||
|
info.attributes((short) ((info.attributes() & ~0x0070) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]));
|
||||||
|
info.attributes(
|
||||||
|
(short) ((info.attributes() & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0)));
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processDefaultTextColor() throws IOException {
|
||||||
|
info.attributes((short) ((info.attributes() & ~0x000F) | (originalColors & 0xF)));
|
||||||
|
info.attributes((short) (info.attributes() & ~FOREGROUND_INTENSITY));
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processDefaultBackgroundColor() throws IOException {
|
||||||
|
info.attributes((short) ((info.attributes() & ~0x00F0) | (originalColors & 0xF0)));
|
||||||
|
info.attributes((short) (info.attributes() & ~BACKGROUND_INTENSITY));
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processAttributeRest() throws IOException {
|
||||||
|
info.attributes((short) ((info.attributes() & ~0x00FF) | originalColors));
|
||||||
|
this.negative = false;
|
||||||
|
this.bold = false;
|
||||||
|
this.underline = false;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processSetAttribute(int attribute) throws IOException {
|
||||||
|
switch (attribute) {
|
||||||
|
case ATTRIBUTE_INTENSITY_BOLD -> {
|
||||||
|
bold = true;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_INTENSITY_NORMAL -> {
|
||||||
|
bold = false;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_UNDERLINE -> {
|
||||||
|
underline = true;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_UNDERLINE_OFF -> {
|
||||||
|
underline = false;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_NEGATIVE_ON -> {
|
||||||
|
negative = true;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
case ATTRIBUTE_NEGATIVE_OFF -> {
|
||||||
|
negative = false;
|
||||||
|
applyAttribute();
|
||||||
|
}
|
||||||
|
default -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processSaveCursorPosition() throws IOException {
|
||||||
|
getConsoleInfo();
|
||||||
|
savedX = info.cursorPosition().x();
|
||||||
|
savedY = info.cursorPosition().y();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processRestoreCursorPosition() throws IOException {
|
||||||
|
// restore only if there was a save operation first
|
||||||
|
if (savedX != -1 && savedY != -1) {
|
||||||
|
out.flush();
|
||||||
|
info.cursorPosition().x(savedX);
|
||||||
|
info.cursorPosition().y(savedY);
|
||||||
|
applyCursorPosition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processInsertLine(int optionInt) throws IOException {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
getConsoleInfo();
|
||||||
|
SMALL_RECT scroll = info.window().copy(arena);
|
||||||
|
scroll.top(info.cursorPosition().y());
|
||||||
|
COORD org =
|
||||||
|
new COORD(arena, (short) 0, (short) (info.cursorPosition().y() + optionInt));
|
||||||
|
CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors);
|
||||||
|
if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) {
|
||||||
|
throw new IOException(getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processDeleteLine(int optionInt) throws IOException {
|
||||||
|
try (java.lang.foreign.Arena arena = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
getConsoleInfo();
|
||||||
|
SMALL_RECT scroll = info.window().copy(arena);
|
||||||
|
scroll.top(info.cursorPosition().y());
|
||||||
|
COORD org =
|
||||||
|
new COORD(arena, (short) 0, (short) (info.cursorPosition().y() - optionInt));
|
||||||
|
CHAR_INFO info = new CHAR_INFO(arena, ' ', originalColors);
|
||||||
|
if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) {
|
||||||
|
throw new IOException(getLastErrorMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void processChangeWindowTitle(String title) {
|
||||||
|
try (java.lang.foreign.Arena session = java.lang.foreign.Arena.ofConfined()) {
|
||||||
|
java.lang.foreign.MemorySegment str = session.allocateFrom(title);
|
||||||
|
SetConsoleTitleW(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the LICENSE file that accompanied this code.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.internal.org.jline.terminal.impl.jna;
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class LastErrorException extends RuntimeException{
|
|
||||||
|
|
||||||
public final long lastError;
|
|
||||||
|
|
||||||
public LastErrorException(long lastError) {
|
|
||||||
this.lastError = lastError;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -34,4 +34,7 @@ public interface Pty extends Closeable {
|
|||||||
|
|
||||||
void setSize(Size size) throws IOException;
|
void setSize(Size size) throws IOException;
|
||||||
|
|
||||||
|
SystemStream getSystemStream();
|
||||||
|
|
||||||
|
TerminalProvider getProvider();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.spi;
|
||||||
|
|
||||||
|
public enum SystemStream {
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
Error
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023, the original author(s).
|
||||||
|
*
|
||||||
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
|
* BSD license in the documentation provided with this software.
|
||||||
|
*
|
||||||
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
*/
|
||||||
|
package jdk.internal.org.jline.terminal.spi;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@code TerminalExt} interface is implemented by {@code Terminal}s
|
||||||
|
* and provides access to the Terminal's internals.
|
||||||
|
*/
|
||||||
|
public interface TerminalExt extends Terminal {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@code TerminalProvider} that created this terminal
|
||||||
|
* or {@code null} if the terminal was created with no provider.
|
||||||
|
*/
|
||||||
|
TerminalProvider getProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlying system stream, may be {@link SystemStream#Output},
|
||||||
|
* {@link SystemStream#Error}, or {@code null} if this terminal is not bound
|
||||||
|
* to a system stream.
|
||||||
|
*/
|
||||||
|
SystemStream getSystemStream();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, the original author or authors.
|
* Copyright (c) 2022, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -11,58 +11,60 @@ package jdk.internal.org.jline.terminal.spi;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ServiceLoader;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import jdk.internal.org.jline.terminal.Attributes;
|
import jdk.internal.org.jline.terminal.Attributes;
|
||||||
import jdk.internal.org.jline.terminal.Size;
|
import jdk.internal.org.jline.terminal.Size;
|
||||||
import jdk.internal.org.jline.terminal.Terminal;
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider;
|
import jdk.internal.org.jline.terminal.impl.exec.ExecTerminalProvider;
|
||||||
|
import jdk.internal.org.jline.terminal.impl.ffm.FfmTerminalProvider;
|
||||||
|
|
||||||
public interface TerminalProvider
|
public interface TerminalProvider {
|
||||||
{
|
|
||||||
|
|
||||||
enum Stream {
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
Error
|
|
||||||
}
|
|
||||||
|
|
||||||
String name();
|
String name();
|
||||||
|
|
||||||
Terminal sysTerminal(String name, String type, boolean ansiPassThrough,
|
Terminal sysTerminal(
|
||||||
Charset encoding, boolean nativeSignals,
|
String name,
|
||||||
Terminal.SignalHandler signalHandler, boolean paused,
|
String type,
|
||||||
Stream consoleStream, Function<InputStream, InputStream> inputStreamWrapper) throws IOException;
|
boolean ansiPassThrough,
|
||||||
|
Charset encoding,
|
||||||
|
boolean nativeSignals,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
SystemStream systemStream,
|
||||||
|
Function<InputStream, InputStream> inputStreamWrapper)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
Terminal newTerminal(String name, String type,
|
Terminal newTerminal(
|
||||||
InputStream masterInput, OutputStream masterOutput,
|
String name,
|
||||||
Charset encoding, Terminal.SignalHandler signalHandler,
|
String type,
|
||||||
boolean paused, Attributes attributes, Size size) throws IOException;
|
InputStream masterInput,
|
||||||
|
OutputStream masterOutput,
|
||||||
|
Charset encoding,
|
||||||
|
Terminal.SignalHandler signalHandler,
|
||||||
|
boolean paused,
|
||||||
|
Attributes attributes,
|
||||||
|
Size size)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
boolean isSystemStream(Stream stream);
|
boolean isSystemStream(SystemStream stream);
|
||||||
|
|
||||||
String systemStreamName(Stream stream);
|
String systemStreamName(SystemStream stream);
|
||||||
|
|
||||||
|
int systemStreamWidth(SystemStream stream);
|
||||||
|
|
||||||
static TerminalProvider load(String name) throws IOException {
|
static TerminalProvider load(String name) throws IOException {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "exec": return new ExecTerminalProvider();
|
case "exec": return new ExecTerminalProvider();
|
||||||
case "jna": {
|
case "ffm": return new FfmTerminalProvider();
|
||||||
try {
|
|
||||||
return (TerminalProvider) Class.forName("jdk.internal.org.jline.terminal.impl.jna.JnaTerminalProvider").getConstructor().newInstance();
|
|
||||||
} catch (ReflectiveOperationException t) {
|
|
||||||
throw new IOException(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
cl = ClassLoader.getSystemClassLoader();
|
cl = ClassLoader.getSystemClassLoader();
|
||||||
}
|
}
|
||||||
InputStream is = cl.getResourceAsStream( "META-INF/services/org/jline/terminal/provider/" + name);
|
InputStream is = cl.getResourceAsStream("META-INF/services/org/jline/terminal/provider/" + name);
|
||||||
if (is != null) {
|
if (is != null) {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
try {
|
try {
|
||||||
@ -71,14 +73,13 @@ public interface TerminalProvider
|
|||||||
if (className == null) {
|
if (className == null) {
|
||||||
throw new IOException("No class defined in terminal provider file " + name);
|
throw new IOException("No class defined in terminal provider file " + name);
|
||||||
}
|
}
|
||||||
Class<?> clazz = cl.loadClass( className );
|
Class<?> clazz = cl.loadClass(className);
|
||||||
return (TerminalProvider) clazz.getConstructor().newInstance();
|
return (TerminalProvider) clazz.getConstructor().newInstance();
|
||||||
} catch ( Exception e ) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Unable to load terminal provider " + name, e);
|
throw new IOException("Unable to load terminal provider " + name + ": " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IOException("Unable to find terminal provider " + name);
|
throw new IOException("Unable to find terminal provider " + name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2009-2018 the original author(s).
|
* Copyright (c) 2009-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* you may not use this file except in compliance with the License.
|
* BSD license in the documentation provided with this software.
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* https://opensource.org/licenses/BSD-3-Clause
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
*/
|
||||||
package jdk.internal.org.jline.utils;
|
package jdk.internal.org.jline.utils;
|
||||||
|
|
||||||
@ -252,12 +245,10 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @throws IOException if no more non-null values left
|
* @throws IOException if no more non-null values left
|
||||||
*/
|
*/
|
||||||
private int getNextOptionInt(Iterator<Object> optionsIterator) throws IOException {
|
private int getNextOptionInt(Iterator<Object> optionsIterator) throws IOException {
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (!optionsIterator.hasNext())
|
if (!optionsIterator.hasNext()) throw new IllegalArgumentException();
|
||||||
throw new IllegalArgumentException();
|
|
||||||
Object arg = optionsIterator.next();
|
Object arg = optionsIterator.next();
|
||||||
if (arg != null)
|
if (arg != null) return (Integer) arg;
|
||||||
return (Integer) arg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,27 +337,21 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
int g = getNextOptionInt(optionsIterator);
|
int g = getNextOptionInt(optionsIterator);
|
||||||
int b = getNextOptionInt(optionsIterator);
|
int b = getNextOptionInt(optionsIterator);
|
||||||
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
|
if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
|
||||||
if (value == 38)
|
if (value == 38) processSetForegroundColorExt(r, g, b);
|
||||||
processSetForegroundColorExt(r, g, b);
|
else processSetBackgroundColorExt(r, g, b);
|
||||||
else
|
|
||||||
processSetBackgroundColorExt(r, g, b);
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
} else if (arg2or5 == 5) {
|
||||||
else if (arg2or5 == 5) {
|
|
||||||
// 256 color style like `esc[38;5;<index>m`
|
// 256 color style like `esc[38;5;<index>m`
|
||||||
int paletteIndex = getNextOptionInt(optionsIterator);
|
int paletteIndex = getNextOptionInt(optionsIterator);
|
||||||
if (paletteIndex >= 0 && paletteIndex <= 255) {
|
if (paletteIndex >= 0 && paletteIndex <= 255) {
|
||||||
if (value == 38)
|
if (value == 38) processSetForegroundColorExt(paletteIndex);
|
||||||
processSetForegroundColorExt(paletteIndex);
|
else processSetBackgroundColorExt(paletteIndex);
|
||||||
else
|
|
||||||
processSetBackgroundColorExt(paletteIndex);
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -449,47 +434,41 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* Process <code>CSI u</code> ANSI code, corresponding to <code>RCP \u2013 Restore Cursor Position</code>
|
* Process <code>CSI u</code> ANSI code, corresponding to <code>RCP \u2013 Restore Cursor Position</code>
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processRestoreCursorPosition() throws IOException {
|
protected void processRestoreCursorPosition() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process <code>CSI s</code> ANSI code, corresponding to <code>SCP \u2013 Save Cursor Position</code>
|
* Process <code>CSI s</code> ANSI code, corresponding to <code>SCP \u2013 Save Cursor Position</code>
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processSaveCursorPosition() throws IOException {
|
protected void processSaveCursorPosition() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process <code>CSI s</code> ANSI code, corresponding to <code>IL \u2013 Insert Line</code>
|
* Process <code>CSI s</code> ANSI code, corresponding to <code>IL \u2013 Insert Line</code>
|
||||||
* @param optionInt the option
|
* @param optionInt the option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processInsertLine(int optionInt) throws IOException {
|
protected void processInsertLine(int optionInt) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process <code>CSI s</code> ANSI code, corresponding to <code>DL \u2013 Delete Line</code>
|
* Process <code>CSI s</code> ANSI code, corresponding to <code>DL \u2013 Delete Line</code>
|
||||||
* @param optionInt the option
|
* @param optionInt the option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processDeleteLine(int optionInt) throws IOException {
|
protected void processDeleteLine(int optionInt) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process <code>CSI n T</code> ANSI code, corresponding to <code>SD \u2013 Scroll Down</code>
|
* Process <code>CSI n T</code> ANSI code, corresponding to <code>SD \u2013 Scroll Down</code>
|
||||||
* @param optionInt the option
|
* @param optionInt the option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processScrollDown(int optionInt) throws IOException {
|
protected void processScrollDown(int optionInt) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process <code>CSI n U</code> ANSI code, corresponding to <code>SU \u2013 Scroll Up</code>
|
* Process <code>CSI n U</code> ANSI code, corresponding to <code>SU \u2013 Scroll Up</code>
|
||||||
* @param optionInt the option
|
* @param optionInt the option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processScrollUp(int optionInt) throws IOException {
|
protected void processScrollUp(int optionInt) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
protected static final int ERASE_SCREEN_TO_END = 0;
|
protected static final int ERASE_SCREEN_TO_END = 0;
|
||||||
protected static final int ERASE_SCREEN_TO_BEGINING = 1;
|
protected static final int ERASE_SCREEN_TO_BEGINING = 1;
|
||||||
@ -500,8 +479,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param eraseOption the erase option
|
* @param eraseOption the erase option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processEraseScreen(int eraseOption) throws IOException {
|
protected void processEraseScreen(int eraseOption) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
protected static final int ERASE_LINE_TO_END = 0;
|
protected static final int ERASE_LINE_TO_END = 0;
|
||||||
protected static final int ERASE_LINE_TO_BEGINING = 1;
|
protected static final int ERASE_LINE_TO_BEGINING = 1;
|
||||||
@ -512,8 +490,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param eraseOption the erase option
|
* @param eraseOption the erase option
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processEraseLine(int eraseOption) throws IOException {
|
protected void processEraseLine(int eraseOption) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold
|
protected static final int ATTRIBUTE_INTENSITY_BOLD = 1; // Intensity: Bold
|
||||||
protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported
|
protected static final int ATTRIBUTE_INTENSITY_FAINT = 2; // Intensity; Faint not widely supported
|
||||||
@ -521,14 +498,17 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single
|
protected static final int ATTRIBUTE_UNDERLINE = 4; // Underline; Single
|
||||||
protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute
|
protected static final int ATTRIBUTE_BLINK_SLOW = 5; // Blink; Slow less than 150 per minute
|
||||||
protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more
|
protected static final int ATTRIBUTE_BLINK_FAST = 6; // Blink; Rapid MS-DOS ANSI.SYS; 150 per minute or more
|
||||||
protected static final int ATTRIBUTE_NEGATIVE_ON = 7; // Image; Negative inverse or reverse; swap foreground and background
|
protected static final int ATTRIBUTE_NEGATIVE_ON =
|
||||||
|
7; // Image; Negative inverse or reverse; swap foreground and background
|
||||||
protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on
|
protected static final int ATTRIBUTE_CONCEAL_ON = 8; // Conceal on
|
||||||
protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported
|
protected static final int ATTRIBUTE_UNDERLINE_DOUBLE = 21; // Underline; Double not widely supported
|
||||||
protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint
|
protected static final int ATTRIBUTE_INTENSITY_NORMAL = 22; // Intensity; Normal not bold and not faint
|
||||||
protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None
|
protected static final int ATTRIBUTE_UNDERLINE_OFF = 24; // Underline; None
|
||||||
protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off
|
protected static final int ATTRIBUTE_BLINK_OFF = 25; // Blink; off
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
protected static final int ATTRIBUTE_NEGATIVE_Off = 27; // Image; Positive
|
protected static final int ATTRIBUTE_NEGATIVE_Off = 27; // Image; Positive
|
||||||
|
|
||||||
protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive
|
protected static final int ATTRIBUTE_NEGATIVE_OFF = 27; // Image; Positive
|
||||||
protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off
|
protected static final int ATTRIBUTE_CONCEAL_OFF = 28; // Reveal conceal off
|
||||||
|
|
||||||
@ -546,8 +526,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @see #processDefaultTextColor()
|
* @see #processDefaultTextColor()
|
||||||
* @see #processDefaultBackgroundColor()
|
* @see #processDefaultBackgroundColor()
|
||||||
*/
|
*/
|
||||||
protected void processSetAttribute(int attribute) throws IOException {
|
protected void processSetAttribute(int attribute) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
protected static final int BLACK = 0;
|
protected static final int BLACK = 0;
|
||||||
protected static final int RED = 1;
|
protected static final int RED = 1;
|
||||||
@ -584,8 +563,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param paletteIndex the text color in the palette
|
* @param paletteIndex the text color in the palette
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processSetForegroundColorExt(int paletteIndex) throws IOException {
|
protected void processSetForegroundColorExt(int paletteIndex) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>SGR 38</code> corresponding to <code>extended set text color (foreground)</code>
|
* process <code>SGR 38</code> corresponding to <code>extended set text color (foreground)</code>
|
||||||
@ -625,8 +603,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param paletteIndex the background color in the palette
|
* @param paletteIndex the background color in the palette
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {
|
protected void processSetBackgroundColorExt(int paletteIndex) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>SGR 48</code> corresponding to <code>extended set background color</code>
|
* process <code>SGR 48</code> corresponding to <code>extended set background color</code>
|
||||||
@ -644,22 +621,19 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* process <code>SGR 39</code> corresponding to <code>Default text color (foreground)</code>
|
* process <code>SGR 39</code> corresponding to <code>Default text color (foreground)</code>
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processDefaultTextColor() throws IOException {
|
protected void processDefaultTextColor() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>SGR 49</code> corresponding to <code>Default background color</code>
|
* process <code>SGR 49</code> corresponding to <code>Default background color</code>
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processDefaultBackgroundColor() throws IOException {
|
protected void processDefaultBackgroundColor() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>SGR 0</code> corresponding to <code>Reset / Normal</code>
|
* process <code>SGR 0</code> corresponding to <code>Reset / Normal</code>
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processAttributeRest() throws IOException {
|
protected void processAttributeRest() throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n ; m H</code> corresponding to <code>CUP \u2013 Cursor Position</code> or
|
* process <code>CSI n ; m H</code> corresponding to <code>CUP \u2013 Cursor Position</code> or
|
||||||
@ -668,24 +642,21 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param col the column
|
* @param col the column
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorTo(int row, int col) throws IOException {
|
protected void processCursorTo(int row, int col) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n G</code> corresponding to <code>CHA \u2013 Cursor Horizontal Absolute</code>
|
* process <code>CSI n G</code> corresponding to <code>CHA \u2013 Cursor Horizontal Absolute</code>
|
||||||
* @param x the column
|
* @param x the column
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorToColumn(int x) throws IOException {
|
protected void processCursorToColumn(int x) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n F</code> corresponding to <code>CPL \u2013 Cursor Previous Line</code>
|
* process <code>CSI n F</code> corresponding to <code>CPL \u2013 Cursor Previous Line</code>
|
||||||
* @param count line count
|
* @param count line count
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorUpLine(int count) throws IOException {
|
protected void processCursorUpLine(int count) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n E</code> corresponding to <code>CNL \u2013 Cursor Next Line</code>
|
* process <code>CSI n E</code> corresponding to <code>CNL \u2013 Cursor Next Line</code>
|
||||||
@ -704,8 +675,7 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param count the count
|
* @param count the count
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorLeft(int count) throws IOException {
|
protected void processCursorLeft(int count) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n C</code> corresponding to <code>CUF \u2013 Cursor Forward</code>
|
* process <code>CSI n C</code> corresponding to <code>CUF \u2013 Cursor Forward</code>
|
||||||
@ -724,19 +694,16 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* @param count the count
|
* @param count the count
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorDown(int count) throws IOException {
|
protected void processCursorDown(int count) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>CSI n A</code> corresponding to <code>CUU \u2013 Cursor Up</code>
|
* process <code>CSI n A</code> corresponding to <code>CUU \u2013 Cursor Up</code>
|
||||||
* @param count the count
|
* @param count the count
|
||||||
* @throws IOException if an error occurs
|
* @throws IOException if an error occurs
|
||||||
*/
|
*/
|
||||||
protected void processCursorUp(int count) throws IOException {
|
protected void processCursorUp(int count) throws IOException {}
|
||||||
}
|
|
||||||
|
|
||||||
protected void processUnknownExtension(ArrayList<Object> options, int command) {
|
protected void processUnknownExtension(ArrayList<Object> options, int command) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>OSC 0;text BEL</code> corresponding to <code>Change Window and Icon label</code>
|
* process <code>OSC 0;text BEL</code> corresponding to <code>Change Window and Icon label</code>
|
||||||
@ -751,23 +718,20 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
* process <code>OSC 1;text BEL</code> corresponding to <code>Change Icon label</code>
|
* process <code>OSC 1;text BEL</code> corresponding to <code>Change Icon label</code>
|
||||||
* @param name the icon name
|
* @param name the icon name
|
||||||
*/
|
*/
|
||||||
protected void processChangeIconName(String name) {
|
protected void processChangeIconName(String name) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* process <code>OSC 2;text BEL</code> corresponding to <code>Change Window title</code>
|
* process <code>OSC 2;text BEL</code> corresponding to <code>Change Window title</code>
|
||||||
* @param title the title
|
* @param title the title
|
||||||
*/
|
*/
|
||||||
protected void processChangeWindowTitle(String title) {
|
protected void processChangeWindowTitle(String title) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process unknown <code>OSC</code> command.
|
* Process unknown <code>OSC</code> command.
|
||||||
* @param command the command
|
* @param command the command
|
||||||
* @param param the param
|
* @param param the param
|
||||||
*/
|
*/
|
||||||
protected void processUnknownOperatingSystemCommand(int command, String param) {
|
protected void processUnknownOperatingSystemCommand(int command, String param) {}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process character set sequence.
|
* Process character set sequence.
|
||||||
@ -781,17 +745,13 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void processCharsetSelect(int set, char seq) {
|
protected void processCharsetSelect(int set, char seq) {}
|
||||||
}
|
|
||||||
|
|
||||||
private int optionInt(ArrayList<Object> options, int index) {
|
private int optionInt(ArrayList<Object> options, int index) {
|
||||||
if (options.size() <= index)
|
if (options.size() <= index) throw new IllegalArgumentException();
|
||||||
throw new IllegalArgumentException();
|
|
||||||
Object value = options.get(index);
|
Object value = options.get(index);
|
||||||
if (value == null)
|
if (value == null) throw new IllegalArgumentException();
|
||||||
throw new IllegalArgumentException();
|
if (!value.getClass().equals(Integer.class)) throw new IllegalArgumentException();
|
||||||
if (!value.getClass().equals(Integer.class))
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
return (Integer) value;
|
return (Integer) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,5 +788,4 @@ public class AnsiWriter extends FilterWriter {
|
|||||||
flush();
|
flush();
|
||||||
super.close();
|
super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -15,6 +15,7 @@ import jdk.internal.org.jline.terminal.Terminal;
|
|||||||
import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
|
import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
|
||||||
import jdk.internal.org.jline.utils.InfoCmp.Capability;
|
import jdk.internal.org.jline.utils.InfoCmp.Capability;
|
||||||
|
|
||||||
|
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR;
|
import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP;
|
import static jdk.internal.org.jline.utils.AttributedStyle.BG_COLOR_EXP;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR;
|
import static jdk.internal.org.jline.utils.AttributedStyle.FG_COLOR;
|
||||||
@ -30,12 +31,11 @@ import static jdk.internal.org.jline.utils.AttributedStyle.F_FAINT;
|
|||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_IND;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_IND;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_RGB;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_FOREGROUND_RGB;
|
||||||
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_INVERSE;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_ITALIC;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE;
|
import static jdk.internal.org.jline.utils.AttributedStyle.F_UNDERLINE;
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.F_HIDDEN;
|
|
||||||
import static jdk.internal.org.jline.utils.AttributedStyle.MASK;
|
import static jdk.internal.org.jline.utils.AttributedStyle.MASK;
|
||||||
import static jdk.internal.org.jline.terminal.TerminalBuilder.PROP_DISABLE_ALTERNATE_CHARSET;
|
|
||||||
|
|
||||||
public abstract class AttributedCharSequence implements CharSequence {
|
public abstract class AttributedCharSequence implements CharSequence {
|
||||||
|
|
||||||
@ -120,6 +120,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
char c = charAt(i);
|
char c = charAt(i);
|
||||||
if (altIn != null && altOut != null) {
|
if (altIn != null && altOut != null) {
|
||||||
char pc = c;
|
char pc = c;
|
||||||
|
// @spotless:off
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '\u2518': c = 'j'; break;
|
case '\u2518': c = 'j'; break;
|
||||||
case '\u2510': c = 'k'; break;
|
case '\u2510': c = 'k'; break;
|
||||||
@ -133,6 +134,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
case '\u252C': c = 'w'; break;
|
case '\u252C': c = 'w'; break;
|
||||||
case '\u2502': c = 'x'; break;
|
case '\u2502': c = 'x'; break;
|
||||||
}
|
}
|
||||||
|
// @spotless:on
|
||||||
boolean oldalt = alt;
|
boolean oldalt = alt;
|
||||||
alt = c != pc;
|
alt = c != pc;
|
||||||
if (oldalt ^ alt) {
|
if (oldalt ^ alt) {
|
||||||
@ -172,16 +174,16 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
if (fg > 0) {
|
if (fg > 0) {
|
||||||
int rounded = -1;
|
int rounded = -1;
|
||||||
if ((fg & F_FOREGROUND_RGB) != 0) {
|
if ((fg & F_FOREGROUND_RGB) != 0) {
|
||||||
int r = (int)(fg >> (FG_COLOR_EXP + 16)) & 0xFF;
|
int r = (int) (fg >> (FG_COLOR_EXP + 16)) & 0xFF;
|
||||||
int g = (int)(fg >> (FG_COLOR_EXP + 8)) & 0xFF;
|
int g = (int) (fg >> (FG_COLOR_EXP + 8)) & 0xFF;
|
||||||
int b = (int)(fg >> FG_COLOR_EXP) & 0xFF;
|
int b = (int) (fg >> FG_COLOR_EXP) & 0xFF;
|
||||||
if (colors >= HIGH_COLORS) {
|
if (colors >= HIGH_COLORS) {
|
||||||
first = attr(sb, "38;2;" + r + ";" + g + ";" + b, first);
|
first = attr(sb, "38;2;" + r + ";" + g + ";" + b, first);
|
||||||
} else {
|
} else {
|
||||||
rounded = palette.round(r, g, b);
|
rounded = palette.round(r, g, b);
|
||||||
}
|
}
|
||||||
} else if ((fg & F_FOREGROUND_IND) != 0) {
|
} else if ((fg & F_FOREGROUND_IND) != 0) {
|
||||||
rounded = palette.round((int)(fg >> FG_COLOR_EXP) & 0xFF);
|
rounded = palette.round((int) (fg >> FG_COLOR_EXP) & 0xFF);
|
||||||
}
|
}
|
||||||
if (rounded >= 0) {
|
if (rounded >= 0) {
|
||||||
if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) {
|
if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) {
|
||||||
@ -211,16 +213,16 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
if (bg > 0) {
|
if (bg > 0) {
|
||||||
int rounded = -1;
|
int rounded = -1;
|
||||||
if ((bg & F_BACKGROUND_RGB) != 0) {
|
if ((bg & F_BACKGROUND_RGB) != 0) {
|
||||||
int r = (int)(bg >> (BG_COLOR_EXP + 16)) & 0xFF;
|
int r = (int) (bg >> (BG_COLOR_EXP + 16)) & 0xFF;
|
||||||
int g = (int)(bg >> (BG_COLOR_EXP + 8)) & 0xFF;
|
int g = (int) (bg >> (BG_COLOR_EXP + 8)) & 0xFF;
|
||||||
int b = (int)(bg >> BG_COLOR_EXP) & 0xFF;
|
int b = (int) (bg >> BG_COLOR_EXP) & 0xFF;
|
||||||
if (colors >= HIGH_COLORS) {
|
if (colors >= HIGH_COLORS) {
|
||||||
first = attr(sb, "48;2;" + r + ";" + g + ";" + b, first);
|
first = attr(sb, "48;2;" + r + ";" + g + ";" + b, first);
|
||||||
} else {
|
} else {
|
||||||
rounded = palette.round(r, g, b);
|
rounded = palette.round(r, g, b);
|
||||||
}
|
}
|
||||||
} else if ((bg & F_BACKGROUND_IND) != 0) {
|
} else if ((bg & F_BACKGROUND_IND) != 0) {
|
||||||
rounded = palette.round((int)(bg >> BG_COLOR_EXP) & 0xFF);
|
rounded = palette.round((int) (bg >> BG_COLOR_EXP) & 0xFF);
|
||||||
}
|
}
|
||||||
if (rounded >= 0) {
|
if (rounded >= 0) {
|
||||||
if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) {
|
if (colors >= HIGH_COLORS && force == ForceMode.ForceTrueColors) {
|
||||||
@ -243,8 +245,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
background = bg;
|
background = bg;
|
||||||
}
|
}
|
||||||
if ((d & (F_BOLD | F_FAINT)) != 0) {
|
if ((d & (F_BOLD | F_FAINT)) != 0) {
|
||||||
if ( (d & F_BOLD) != 0 && (s & F_BOLD) == 0
|
if ((d & F_BOLD) != 0 && (s & F_BOLD) == 0 || (d & F_FAINT) != 0 && (s & F_FAINT) == 0) {
|
||||||
|| (d & F_FAINT) != 0 && (s & F_FAINT) == 0) {
|
|
||||||
first = attr(sb, "22", first);
|
first = attr(sb, "22", first);
|
||||||
}
|
}
|
||||||
if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) {
|
if ((d & F_BOLD) != 0 && (s & F_BOLD) != 0) {
|
||||||
@ -360,8 +361,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
int len = length();
|
int len = length();
|
||||||
for (int cur = 0; cur < len; ) {
|
for (int cur = 0; cur < len; ) {
|
||||||
int cp = codePointAt(cur);
|
int cp = codePointAt(cur);
|
||||||
if (!isHidden(cur))
|
if (!isHidden(cur)) cols += WCWidth.wcwidth(cp);
|
||||||
cols += WCWidth.wcwidth(cp);
|
|
||||||
cur += Character.charCount(cp);
|
cur += Character.charCount(cp);
|
||||||
}
|
}
|
||||||
return cols;
|
return cols;
|
||||||
@ -382,8 +382,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
int end = begin;
|
int end = begin;
|
||||||
while (end < this.length()) {
|
while (end < this.length()) {
|
||||||
int cp = codePointAt(end);
|
int cp = codePointAt(end);
|
||||||
if (cp == '\n')
|
if (cp == '\n') break;
|
||||||
break;
|
|
||||||
int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp);
|
int w = isHidden(end) ? 0 : WCWidth.wcwidth(cp);
|
||||||
if (col + w > stop) {
|
if (col + w > stop) {
|
||||||
break;
|
break;
|
||||||
@ -407,7 +406,7 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
int cp = codePointAt(cur);
|
int cp = codePointAt(cur);
|
||||||
int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp);
|
int w = isHidden(cur) ? 0 : WCWidth.wcwidth(cp);
|
||||||
if (cp == '\n') {
|
if (cp == '\n') {
|
||||||
strings.add(subSequence(beg, includeNewlines ? cur+1 : cur));
|
strings.add(subSequence(beg, includeNewlines ? cur + 1 : cur));
|
||||||
beg = cur + 1;
|
beg = cur + 1;
|
||||||
col = 0;
|
col = 0;
|
||||||
} else if ((col += w) > columns) {
|
} else if ((col += w) > columns) {
|
||||||
@ -429,5 +428,4 @@ public abstract class AttributedCharSequence implements CharSequence {
|
|||||||
public AttributedString toAttributedString() {
|
public AttributedString toAttributedString() {
|
||||||
return substring(0, length());
|
return substring(0, length());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -15,6 +15,8 @@ import java.util.Objects;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import jdk.internal.org.jline.terminal.Terminal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attributed string.
|
* Attributed string.
|
||||||
* Instances of this class are immutables.
|
* Instances of this class are immutables.
|
||||||
@ -103,11 +105,28 @@ public class AttributedString extends AttributedCharSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static AttributedString fromAnsi(String ansi, List<Integer> tabs) {
|
public static AttributedString fromAnsi(String ansi, List<Integer> tabs) {
|
||||||
|
return fromAnsi(ansi, tabs, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AttributedString fromAnsi(String ansi, Terminal terminal) {
|
||||||
|
String alternateIn, alternateOut;
|
||||||
|
if (!DISABLE_ALTERNATE_CHARSET) {
|
||||||
|
alternateIn = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.enter_alt_charset_mode));
|
||||||
|
alternateOut = Curses.tputs(terminal.getStringCapability(InfoCmp.Capability.exit_alt_charset_mode));
|
||||||
|
} else {
|
||||||
|
alternateIn = null;
|
||||||
|
alternateOut = null;
|
||||||
|
}
|
||||||
|
return fromAnsi(ansi, Arrays.asList(0), alternateIn, alternateOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AttributedString fromAnsi(String ansi, List<Integer> tabs, String altIn, String altOut) {
|
||||||
if (ansi == null) {
|
if (ansi == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new AttributedStringBuilder(ansi.length())
|
return new AttributedStringBuilder(ansi.length())
|
||||||
.tabs(tabs)
|
.tabs(tabs)
|
||||||
|
.altCharset(altIn, altOut)
|
||||||
.ansiAppend(ansi)
|
.ansiAppend(ansi)
|
||||||
.toAttributedString();
|
.toAttributedString();
|
||||||
}
|
}
|
||||||
@ -116,9 +135,7 @@ public class AttributedString extends AttributedCharSequence {
|
|||||||
if (ansi == null) {
|
if (ansi == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new AttributedStringBuilder(ansi.length())
|
return new AttributedStringBuilder(ansi.length()).ansiAppend(ansi).toString();
|
||||||
.ansiAppend(ansi)
|
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -162,7 +179,7 @@ public class AttributedString extends AttributedCharSequence {
|
|||||||
}
|
}
|
||||||
result = matcher.find();
|
result = matcher.find();
|
||||||
} while (result);
|
} while (result);
|
||||||
return new AttributedString(buffer, newstyle, start , end);
|
return new AttributedString(buffer, newstyle, start, end);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -179,15 +196,16 @@ public class AttributedString extends AttributedCharSequence {
|
|||||||
|
|
||||||
private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) {
|
private boolean arrEq(char[] a1, char[] a2, int s1, int s2, int l) {
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < l; i++) {
|
||||||
if (a1[s1+i] != a2[s2+i]) {
|
if (a1[s1 + i] != a2[s2 + i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean arrEq(long[] a1, long[] a2, int s1, int s2, int l) {
|
private boolean arrEq(long[] a1, long[] a2, int s1, int s2, int l) {
|
||||||
for (int i = 0; i < l; i++) {
|
for (int i = 0; i < l; i++) {
|
||||||
if (a1[s1+i] != a2[s2+i]) {
|
if (a1[s1 + i] != a2[s2 + i]) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,5 +239,4 @@ public class AttributedString extends AttributedCharSequence {
|
|||||||
}
|
}
|
||||||
return sb.toAttributedString();
|
return sb.toAttributedString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2018, the original author or authors.
|
* Copyright (c) 2002-2018, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -27,6 +27,9 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
private long[] style;
|
private long[] style;
|
||||||
private int length;
|
private int length;
|
||||||
private TabStops tabs = new TabStops(0);
|
private TabStops tabs = new TabStops(0);
|
||||||
|
private char[] altIn;
|
||||||
|
private char[] altOut;
|
||||||
|
private boolean inAltCharset;
|
||||||
private int lastLineLength = 0;
|
private int lastLineLength = 0;
|
||||||
private AttributedStyle current = AttributedStyle.DEFAULT;
|
private AttributedStyle current = AttributedStyle.DEFAULT;
|
||||||
|
|
||||||
@ -81,10 +84,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
@Override
|
@Override
|
||||||
public AttributedString subSequence(int start, int end) {
|
public AttributedString subSequence(int start, int end) {
|
||||||
return new AttributedString(
|
return new AttributedString(
|
||||||
Arrays.copyOfRange(buffer, start, end),
|
Arrays.copyOfRange(buffer, start, end), Arrays.copyOfRange(style, start, end), 0, end - start);
|
||||||
Arrays.copyOfRange(style, start, end),
|
|
||||||
0,
|
|
||||||
end - start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -108,6 +108,14 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
return append(Character.toString(c));
|
return append(Character.toString(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AttributedStringBuilder append(char c, int repeat) {
|
||||||
|
AttributedString s = new AttributedString(Character.toString(c), current);
|
||||||
|
while (repeat-- > 0) {
|
||||||
|
append(s);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) {
|
public AttributedStringBuilder append(CharSequence csq, AttributedStyle style) {
|
||||||
return append(new AttributedString(csq, style));
|
return append(new AttributedString(csq, style));
|
||||||
}
|
}
|
||||||
@ -117,12 +125,12 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStringBuilder style(Function<AttributedStyle,AttributedStyle> style) {
|
public AttributedStringBuilder style(Function<AttributedStyle, AttributedStyle> style) {
|
||||||
current = style.apply(current);
|
current = style.apply(current);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStringBuilder styled(Function<AttributedStyle,AttributedStyle> style, CharSequence cs) {
|
public AttributedStringBuilder styled(Function<AttributedStyle, AttributedStyle> style, CharSequence cs) {
|
||||||
return styled(style, sb -> sb.append(cs));
|
return styled(style, sb -> sb.append(cs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +138,8 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
return styled(s -> style, sb -> sb.append(cs));
|
return styled(s -> style, sb -> sb.append(cs));
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStringBuilder styled(Function<AttributedStyle,AttributedStyle> style, Consumer<AttributedStringBuilder> consumer) {
|
public AttributedStringBuilder styled(
|
||||||
|
Function<AttributedStyle, AttributedStyle> style, Consumer<AttributedStringBuilder> consumer) {
|
||||||
AttributedStyle prev = current;
|
AttributedStyle prev = current;
|
||||||
current = style.apply(prev);
|
current = style.apply(prev);
|
||||||
consumer.accept(this);
|
consumer.accept(this);
|
||||||
@ -338,10 +347,57 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
// This is not a SGR code, so ignore
|
// This is not a SGR code, so ignore
|
||||||
ansiState = 0;
|
ansiState = 0;
|
||||||
}
|
}
|
||||||
} else if (c == '\t' && tabs.defined()) {
|
} else {
|
||||||
|
if (ansiState >= 1) {
|
||||||
|
ensureCapacity(length + 1);
|
||||||
|
buffer[length++] = 27;
|
||||||
|
if (ansiState >= 2) {
|
||||||
|
ensureCapacity(length + 1);
|
||||||
|
buffer[length++] = '[';
|
||||||
|
}
|
||||||
|
ansiState = 0;
|
||||||
|
}
|
||||||
|
if (c == '\t' && tabs.defined()) {
|
||||||
insertTab(current);
|
insertTab(current);
|
||||||
} else {
|
} else {
|
||||||
ensureCapacity(length + 1);
|
ensureCapacity(length + 1);
|
||||||
|
if (inAltCharset) {
|
||||||
|
switch (c) {
|
||||||
|
case 'j':
|
||||||
|
c = '\u2518';
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
c = '\u2510';
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
c = '\u250C';
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
c = '\u2514';
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
c = '\u253C';
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
c = '\u2500';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
c = '\u251C';
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
c = '\u2524';
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
c = '\u2534';
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
c = '\u252C';
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
c = '\u2502';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
buffer[length] = c;
|
buffer[length] = c;
|
||||||
style[length] = this.current.getStyle();
|
style[length] = this.current.getStyle();
|
||||||
if (c == '\n') {
|
if (c == '\n') {
|
||||||
@ -350,11 +406,31 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
lastLineLength++;
|
lastLineLength++;
|
||||||
}
|
}
|
||||||
length++;
|
length++;
|
||||||
|
if (altIn != null && altOut != null) {
|
||||||
|
char[] alt = inAltCharset ? altOut : altIn;
|
||||||
|
if (equals(buffer, length - alt.length, alt, 0, alt.length)) {
|
||||||
|
inAltCharset = !inAltCharset;
|
||||||
|
length -= alt.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean equals(char[] a, int aFromIndex, char[] b, int bFromIndex, int length) {
|
||||||
|
if (aFromIndex < 0 || bFromIndex < 0 || aFromIndex + length > a.length || bFromIndex + length > b.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
if (a[aFromIndex + i] != b[bFromIndex + i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected void insertTab(AttributedStyle s) {
|
protected void insertTab(AttributedStyle s) {
|
||||||
int nb = tabs.spaces(lastLineLength);
|
int nb = tabs.spaces(lastLineLength);
|
||||||
ensureCapacity(length + nb);
|
ensureCapacity(length + nb);
|
||||||
@ -393,6 +469,15 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AttributedStringBuilder altCharset(String altIn, String altOut) {
|
||||||
|
if (length > 0) {
|
||||||
|
throw new IllegalStateException("Cannot change alternative charset after appending text");
|
||||||
|
}
|
||||||
|
this.altIn = altIn != null ? altIn.toCharArray() : null;
|
||||||
|
this.altOut = altOut != null ? altOut.toCharArray() : null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) {
|
public AttributedStringBuilder styleMatches(Pattern pattern, AttributedStyle s) {
|
||||||
Matcher matcher = pattern.matcher(this);
|
Matcher matcher = pattern.matcher(this);
|
||||||
while (matcher.find()) {
|
while (matcher.find()) {
|
||||||
@ -416,7 +501,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TabStops {
|
private static class TabStops {
|
||||||
private List<Integer> tabs = new ArrayList<>();
|
private List<Integer> tabs = new ArrayList<>();
|
||||||
private int lastStop = 0;
|
private int lastStop = 0;
|
||||||
private int lastSize = 0;
|
private int lastSize = 0;
|
||||||
@ -428,7 +513,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
public TabStops(List<Integer> tabs) {
|
public TabStops(List<Integer> tabs) {
|
||||||
this.tabs = tabs;
|
this.tabs = tabs;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
for (int s: tabs) {
|
for (int s : tabs) {
|
||||||
if (s <= p) {
|
if (s <= p) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -447,7 +532,7 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
if (lastLineLength >= lastStop) {
|
if (lastLineLength >= lastStop) {
|
||||||
out = lastSize - (lastLineLength - lastStop) % lastSize;
|
out = lastSize - (lastLineLength - lastStop) % lastSize;
|
||||||
} else {
|
} else {
|
||||||
for (int s: tabs) {
|
for (int s : tabs) {
|
||||||
if (s > lastLineLength) {
|
if (s > lastLineLength) {
|
||||||
out = s - lastLineLength;
|
out = s - lastLineLength;
|
||||||
break;
|
break;
|
||||||
@ -456,7 +541,5 @@ public class AttributedStringBuilder extends AttributedCharSequence implements A
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2021, the original author or authors.
|
* Copyright (c) 2002-2021, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -70,7 +70,8 @@ public class AttributedStyle {
|
|||||||
|
|
||||||
public AttributedStyle(long style, long mask) {
|
public AttributedStyle(long style, long mask) {
|
||||||
this.style = style;
|
this.style = style;
|
||||||
this.mask = mask & MASK | ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0)
|
this.mask = mask & MASK
|
||||||
|
| ((style & F_FOREGROUND) != 0 ? FG_COLOR : 0)
|
||||||
| ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0);
|
| ((style & F_BACKGROUND) != 0 ? BG_COLOR : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +177,9 @@ public class AttributedStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle foreground(int color) {
|
public AttributedStyle foreground(int color) {
|
||||||
return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_IND);
|
return new AttributedStyle(
|
||||||
|
style & ~FG_COLOR | F_FOREGROUND_IND | (((long) color << FG_COLOR_EXP) & FG_COLOR),
|
||||||
|
mask | F_FOREGROUND_IND);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle foreground(int r, int g, int b) {
|
public AttributedStyle foreground(int r, int g, int b) {
|
||||||
@ -184,7 +187,9 @@ public class AttributedStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle foregroundRgb(int color) {
|
public AttributedStyle foregroundRgb(int color) {
|
||||||
return new AttributedStyle(style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR), mask | F_FOREGROUND_RGB);
|
return new AttributedStyle(
|
||||||
|
style & ~FG_COLOR | F_FOREGROUND_RGB | ((((long) color & 0xFFFFFF) << FG_COLOR_EXP) & FG_COLOR),
|
||||||
|
mask | F_FOREGROUND_RGB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle foregroundOff() {
|
public AttributedStyle foregroundOff() {
|
||||||
@ -196,7 +201,9 @@ public class AttributedStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle background(int color) {
|
public AttributedStyle background(int color) {
|
||||||
return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_IND);
|
return new AttributedStyle(
|
||||||
|
style & ~BG_COLOR | F_BACKGROUND_IND | (((long) color << BG_COLOR_EXP) & BG_COLOR),
|
||||||
|
mask | F_BACKGROUND_IND);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle background(int r, int g, int b) {
|
public AttributedStyle background(int r, int g, int b) {
|
||||||
@ -204,7 +211,9 @@ public class AttributedStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle backgroundRgb(int color) {
|
public AttributedStyle backgroundRgb(int color) {
|
||||||
return new AttributedStyle(style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR), mask | F_BACKGROUND_RGB);
|
return new AttributedStyle(
|
||||||
|
style & ~BG_COLOR | F_BACKGROUND_RGB | ((((long) color & 0xFFFFFF) << BG_COLOR_EXP) & BG_COLOR),
|
||||||
|
mask | F_BACKGROUND_RGB);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AttributedStyle backgroundOff() {
|
public AttributedStyle backgroundOff() {
|
||||||
@ -249,7 +258,6 @@ public class AttributedStyle {
|
|||||||
AttributedStyle that = (AttributedStyle) o;
|
AttributedStyle that = (AttributedStyle) o;
|
||||||
if (style != that.style) return false;
|
if (style != that.style) return false;
|
||||||
return mask == that.mask;
|
return mask == that.mask;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -266,10 +274,6 @@ public class AttributedStyle {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AttributedStyle{" +
|
return "AttributedStyle{" + "style=" + style + ", mask=" + mask + ", ansi=" + toAnsi() + '}';
|
||||||
"style=" + style +
|
|
||||||
", mask=" + mask +
|
|
||||||
", ansi=" + toAnsi() +
|
|
||||||
'}';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002-2016, the original author or authors.
|
* Copyright (c) 2002-2016, the original author(s).
|
||||||
*
|
*
|
||||||
* This software is distributable under the BSD license. See the terms of the
|
* This software is distributable under the BSD license. See the terms of the
|
||||||
* BSD license in the documentation provided with this software.
|
* BSD license in the documentation provided with this software.
|
||||||
@ -14,8 +14,7 @@ public class ClosedException extends IOException {
|
|||||||
|
|
||||||
private static final long serialVersionUID = 3085420657077696L;
|
private static final long serialVersionUID = 3085420657077696L;
|
||||||
|
|
||||||
public ClosedException() {
|
public ClosedException() {}
|
||||||
}
|
|
||||||
|
|
||||||
public ClosedException(String message) {
|
public ClosedException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user