001/* 002 * JDrupes Builder 003 * Copyright (C) 2026 Michael N. Lipp 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <https://www.gnu.org/licenses/>. 017 */ 018 019package org.jdrupes.builder.core.console; 020 021import java.io.InputStreamReader; 022 023/// Provides information about the terminal. This class relies on variables 024/// `LINES` and `COLUMNS` to be environment variables (exported). 025/// 026public class TerminalInfo { 027 private int lines; 028 private int cols; 029 private final boolean supportsAnsi; 030 031 /// Initializes a new terminal info. 032 /// 033 public TerminalInfo() { 034 this.supportsAnsi = System.console() != null 035 && System.getenv("TERM") != null 036 && !"dumb".equals(System.getenv("TERM")); 037 refreshSize(); 038 } 039 040 /// Returns whether the terminal supports ANSI. 041 /// 042 /// @return true, if successful 043 /// 044 public boolean supportsAnsi() { 045 return supportsAnsi; 046 } 047 048 /// Returns the number of lines. 049 /// 050 /// @return the lines 051 /// 052 public int lines() { 053 return lines; 054 } 055 056 /// Returns the number of columns. 057 /// 058 /// @return the columns 059 /// 060 public int columns() { 061 return cols; 062 } 063 064 @SuppressWarnings({ "PMD.RelianceOnDefaultCharset", 065 "PMD.AvoidCatchingGenericException", "PMD.ShortVariable", 066 "PMD.AvoidLiteralsInIfCondition", "PMD.UnusedAssignment" }) 067 private void refreshSize() { 068 try { 069 Process proc 070 = new ProcessBuilder("sh", "-c", "stty size < /dev/tty") 071 .redirectErrorStream(true).start(); 072 073 try (java.io.BufferedReader in = new java.io.BufferedReader( 074 new InputStreamReader(proc.getInputStream()))) { 075 String line = in.readLine(); 076 if (line != null) { 077 String[] parts = line.trim().split("\\s+"); 078 if (parts.length == 2) { 079 lines = Integer.parseInt(parts[0]); 080 cols = Integer.parseInt(parts[1]); 081 return; 082 } 083 } 084 } 085 } catch (Exception ignored) { 086 // use fallback 087 } 088 089 // fallback 090 lines = 24; 091 cols = 80; 092 } 093}