print – println hatası var mış gibi birbiri içerisinde geçiyor. Solda ise, tıpkı IDE’de aldığım gibi tertemiz çıktılar alıyorum. Zaten soldaki görsele bakarak sağ tarafın ne kadar problemli olduğunu anlayabilirsiniz hocalarım.Rica ederim. Sorunu nasil tespit ettigime dair sureci anlatacak olursam;Çok teşekkürler hocam yeni bir şey kattın.
private record Session(String username, int clearance) {}
public static void testMenuLoop() throws IOException {
Session session = new Session("charlie", 3);
FileSystem app = new FileSystem();
app.loadStoreIfPresent();
app.menuLoop(session);
}
Koddan değildir diye atmamıştım, koddan olsa Terminal'de de problem yaşardım diye ancak buyrun aşağı bıraktım.Kodu paylasmazsan yardimci olamayiz ki.
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.security.*;
import java.util.*;
public class FileSystem {
private static final Path SALT_PATH = Paths.get("salt.txt");
private static final Path SHADOW_PATH = Paths.get("shadow.txt");
private static final Path STORE_PATH = Paths.get("Files.store");
private static class VFile {
String name;
String owner;
int level; // classification
StringBuilder data; // content
VFile(String name, String owner, int level) {
this.name = name;
this.owner = owner;
this.level = level;
this.data = new StringBuilder();
}
String serialize() {
// name|owner|level|content (content escaped as base64 to remain readable/safe)
String contentB64 = Base64.getEncoder().encodeToString(data.toString().getBytes(StandardCharsets.UTF_8));
return name + "|" + owner + "|" + level + "|" + contentB64;
}
static VFile deserialize(String line) {
String[] parts = line.split("\\|", 4);
if (parts.length < 4) return null;
VFile f = new VFile(parts[0], parts[1], Integer.parseInt(parts[2]));
try {
byte[] bytes = Base64.getDecoder().decode(parts[3]);
f.data.append(new String(bytes, StandardCharsets.UTF_8));
} catch (IllegalArgumentException e) {
// ignore decode errors; leave content empty
}
return f;
}
}
private final Map<String, VFile> files = new LinkedHashMap<>(); // preserve insertion order
private static class Session {
String username;
int clearance;
}
public static void main(String[] args) throws Exception {
// Always print MD5 test first
String testInput = "This is a test";
System.out.println("MD5 (\"" + testInput + "\") = " + md5Hex(testInput));
FileSystem app = new FileSystem();
if (args.length == 1 && "-i".equals(args[0])) {
app.initialiseUser();
return;
}
app.loadStoreIfPresent();
Session s = app.loginFlow();
if (s != null) {
app.menuLoop(s);
}
}
// UserReg
private void initialiseUser() throws IOException, NoSuchAlgorithmException {
ensureFilesExist();
Scanner sc = new Scanner(System.in);
System.out.print("Username: ");
String username = sc.nextLine().trim();
if (username.isEmpty() || username.contains(":")) {
System.out.println("Invalid username.");
return;
}
Map<String, String> saltMap = readSaltFile();
if (saltMap.containsKey(username)) {
System.out.println("User already exists. Aborting.");
return;
}
String password = promptPassword(sc, "Password: ");
String confirm = promptPassword(sc, "Confirm Password: ");
if (!password.equals(confirm)) {
System.out.println("Passwords do not match. Aborting.");
return;
}
List<String> pwIssues = passwordIssues(password);
if (!pwIssues.isEmpty()) {
System.out.println("Password does not meet requirements:");
for (String issue : pwIssues) System.out.println(" - " + issue);
System.out.println("Requirements: at least 8 chars, include lowercase, uppercase, and digit.");
return;
}
int clearance = promptClearance(sc);
if (clearance < 0) return;
String salt = randomEightDigits();
String passSaltHash = md5Hex(password + salt);
// Write salt.txt line
String saltLine = username + ":" + salt + System.lineSeparator();
Files.write(SALT_PATH, saltLine.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
// Write shadow.txt line
String shadowLine = username + ":" + passSaltHash + ":" + clearance + System.lineSeparator();
Files.write(SHADOW_PATH, shadowLine.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
System.out.println("User '" + username + "' created with clearance " + clearance + ".");
System.out.println("Added to salt.txt and shadow.txt.");
}
//Login
private Session loginFlow() throws Exception {
ensureFilesExist();
Scanner sc = new Scanner(System.in);
System.out.print("Username: ");
String username = sc.nextLine().trim();
String password = promptPassword(sc, "Password: ");
Map<String, String> saltMap = readSaltFile();
if (!saltMap.containsKey(username)) {
System.out.println("Username not found in salt.txt. Exiting.");
return null;
}
String salt = saltMap.get(username);
System.out.println(username + " found in salt.txt");
System.out.println("salt retrieved: " + salt);
System.out.println("hashing ...");
String hash = md5Hex(password + salt);
System.out.println("hash value: " + hash);
// Files
ShadowEntry sh = readShadowFor(username);
if (sh == null) {
System.out.println("No matching entry in shadow.txt. Exiting.");
return null;
}
if (!hash.equalsIgnoreCase(sh.passSaltHash)) {
System.out.println("Authentication failed: hash mismatch.");
return null;
}
Session s = new Session();
s.username = username;
s.clearance = sh.clearance;
System.out.println("Authentication for user " + username + " complete.");
System.out.println("The clearance for " + username + " is " + s.clearance + ".");
return s;
}
private void menuLoop(Session s) throws IOException {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.flush();
System.out.println(); // blank line for readability
System.out.println("Options: (C)reate, (A)ppend, (R)ead, (W)rite, (L)ist, (S)ave or (E)xit.");
System.out.print("Your choice: ");
System.out.flush();
String choice = sc.nextLine().trim();
if (choice.isEmpty()) continue;
char k = Character.toUpperCase(choice.charAt(0));
switch (k) {
case 'C':
System.out.print("Filename: ");
String newName = sc.nextLine().trim();
if (newName.isEmpty()) {
System.out.println("Invalid name.");
break;
}
if (files.containsKey(newName)) {
System.out.println("File already exists.");
} else {
VFile f = new VFile(newName, s.username, s.clearance);
files.put(newName, f);
System.out.println("File '" + newName + "' created at level " + f.level + ".");
}
break;
case 'A':
handleAppend(sc, s);
break;
case 'R':
handleRead(sc, s);
break;
case 'W':
handleWrite(sc, s, /*overwrite*/true);
break;
case 'L':
listFiles();
break;
case 'S':
saveStore();
System.out.println("Saved to " + STORE_PATH.getFileName() + ".");
break;
case 'E':
System.out.print("Shut down the FileSystem? (Y)es or (N)o ");
System.out.flush();
String yn = sc.nextLine().trim();
if (!yn.isEmpty() && Character.toUpperCase(yn.charAt(0)) == 'Y') {
System.out.println("Goodbye.");
return;
}
break;
default:
System.out.println("Unknown option.");
}
}
}
private void handleAppend(Scanner sc, Session s) {
System.out.print("Filename: ");
System.out.flush();
String name = sc.nextLine().trim();
VFile f = files.get(name);
if (f == null) { System.out.println("No such file."); return; }
if (!canWriteOrAppend(s.clearance, f.level)) {
System.out.println("Access denied (no write down). Your level: " + s.clearance + ", file level: " + f.level);
return;
}
System.out.print("Append text (single line): ");
String line = sc.nextLine();
f.data.append(line).append(System.lineSeparator());
System.out.println("Appended.");
}
private void handleWrite(Scanner sc, Session s, boolean overwrite) {
System.out.print("Filename: ");
System.out.flush();
String name = sc.nextLine().trim();
VFile f = files.get(name);
if (f == null) { System.out.println("No such file."); return; }
if (!canWriteOrAppend(s.clearance, f.level)) {
System.out.println("Access denied (no write down). Your level: " + s.clearance + ", file level: " + f.level);
return;
}
System.out.println("Enter content; end with a single line containing only " + ":wq");
StringBuilder buf = new StringBuilder();
while (true) {
String line = sc.nextLine();
if (line.equals(":wq")) break;
buf.append(line).append(System.lineSeparator());
}
if (overwrite) f.data.setLength(0);
f.data.append(buf);
System.out.println("Written.");
}
private void handleRead(Scanner sc, Session s) {
System.out.print("Filename: ");
System.out.flush();
String name = sc.nextLine().trim();
VFile f = files.get(name);
if (f == null) { System.out.println("No such file."); return; }
if (!canRead(s.clearance, f.level)) {
System.out.println("Access denied (no read up). Your level: " + s.clearance + ", file level: " + f.level);
return;
}
System.out.println("--- BEGIN " + name + " (owner=" + f.owner + ", level=" + f.level + ") ---");
System.out.print(f.data.toString());
System.out.println("--- END " + name + " ---");
}
private void listFiles() {
if (files.isEmpty()) {
System.out.println("No files in system.");
return;
}
System.out.println("Name\tOwner\tLevel\tBytes");
for (VFile f : files.values()) {
System.out.println(f.name + "\t" + f.owner + "\t" + f.level + "\t" + f.data.length());
}
}
// higher number dominates lower number.
private static boolean canRead(int subjectClearance, int objectLevel) {
return subjectClearance >= objectLevel; // no read up violation
}
private static boolean canWriteOrAppend(int subjectClearance, int objectLevel) {
return subjectClearance <= objectLevel; // no write down violation
}
// ===== Persistence for Files.store =====
private void saveStore() throws IOException {
try (BufferedWriter bw = Files.newBufferedWriter(STORE_PATH, StandardCharsets.UTF_8)) {
bw.write("# Files.store — human-readable file records\n");
bw.write("# Format: name|owner|level|base64(content)\n");
for (VFile f : files.values()) {
bw.write(f.serialize());
bw.write('\n');
}
}
}
private void loadStoreIfPresent() throws IOException {
if (!Files.exists(STORE_PATH)) return;
List<String> lines = Files.readAllLines(STORE_PATH, StandardCharsets.UTF_8);
int count = 0;
for (String line : lines) {
if (line.startsWith("#") || line.isBlank()) continue;
VFile f = VFile.deserialize(line);
if (f != null) {
files.put(f.name, f);
count++;
}
}
System.out.println("Loaded " + count + " file record(s) from " + STORE_PATH.getFileName() + ".");
}
private static class ShadowEntry {
String user;
String passSaltHash;
int clearance;
}
private static Map<String, String> readSaltFile() throws IOException {
Map<String, String> map = new HashMap<>();
if (!Files.exists(SALT_PATH)) return map;
List<String> lines = Files.readAllLines(SALT_PATH, StandardCharsets.UTF_8);
for (String line : lines) {
if (line.isBlank()) continue;
String[] parts = line.split(":", 2);
if (parts.length == 2) map.put(parts[0], parts[1]);
}
return map;
}
private static ShadowEntry readShadowFor(String username) throws IOException {
if (!Files.exists(SHADOW_PATH)) return null;
List<String> lines = Files.readAllLines(SHADOW_PATH, StandardCharsets.UTF_8);
for (String line : lines) {
if (line.isBlank()) continue;
String[] parts = line.split(":", 3);
if (parts.length == 3 && parts[0].equals(username)) {
ShadowEntry e = new ShadowEntry();
e.user = parts[0];
e.passSaltHash = parts[1];
try { e.clearance = Integer.parseInt(parts[2]); } catch (NumberFormatException ex) { return null; }
return e;
}
}
return null;
}
private static void ensureFilesExist() throws IOException {
if (!Files.exists(SALT_PATH)) Files.createFile(SALT_PATH);
if (!Files.exists(SHADOW_PATH)) Files.createFile(SHADOW_PATH);
}
private static String md5Hex(String s) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dig = md.digest(s.getBytes(StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
for (byte b : dig) sb.append(String.format("%02x", b));
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
private static String promptPassword(Scanner sc, String prompt) {
Console console = System.console();
if (console != null) {
char[] pwd = console.readPassword(prompt);
return pwd == null ? "" : new String(pwd);
}
System.out.print(prompt);
return sc.nextLine();
}
private static List<String> passwordIssues(String pw) {
List<String> issues = new ArrayList<>();
if (pw.length() < 8) issues.add("must be at least 8 characters long");
if (!pw.chars().anyMatch(Character::isLowerCase)) issues.add("must include a lowercase letter");
if (!pw.chars().anyMatch(Character::isUpperCase)) issues.add("must include an uppercase letter");
if (!pw.chars().anyMatch(Character::isDigit)) issues.add("must include a digit");
return issues;
}
private static int promptClearance(Scanner sc) {
System.out.print("User clearance (0 or 1 or 2 or 3): ");
String in = sc.nextLine().trim();
try {
int level = Integer.parseInt(in);
if (level < 0 || level > 3) throw new NumberFormatException();
return level;
} catch (NumberFormatException e) {
System.out.println("Invalid clearance. Must be 0, 1, 2, or 3.");
return -1;
}
}
private static String randomEightDigits() {
SecureRandom rnd = new SecureRandom();
int n = rnd.nextInt(1_0000_0000); // 0..99,999,999
return String.format("%08d", n);
}
}
Fonksiyonlarda sıkıntı yok zaten ancak ezbere bildiğim için sadece ben kullanabiliyorum. Yazılar hep iç içe geçiyor. Mesela Terminal tıkır tıkır yürürken CMD’de tekrar tekrar boş yere Enter’a basmam gerekiyor tek satır geriden geliyor gibi her şey ve böyle kullanmak imkansız bir hal alıyor bir yerden sonra.Tam olarak CMD çıktılarındaki hatayı anlayamadım ama - tabii ki farklı çıktılar olduğu bariz belli - bir de WSL üzerinde dener misiniz? İkisi de Linux tabanlı olduğu için muhtemelen aynı çıktıları alırsınız diye düşünüyorum. Ek olarak CMD çıktılarında dosya oluşturulmuş gibi gözüküyor, yani create ve yes olarak input vermişsiniz ve program hatasız bitmiş gibi, değil mi?
-Djdk.console=java.base VM secenegiyle baslatirsan duzgun calisiyor.package jdk.internal.org.jline.reader.impl; (GitHub)public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer)
throws UserInterruptException, EndOfFileException {
// prompt may be null
// maskingCallback may be null
// buffer may be null
if (!commandsBuffer.isEmpty()) {
String cmd = commandsBuffer.remove(0);
boolean done = false;
do {
try {
parser.parse(cmd, cmd.length() + 1, ParseContext.ACCEPT_LINE);
done = true;
} catch (EOFError e) {
if (commandsBuffer.isEmpty()) {
throw new IllegalArgumentException("Incompleted command: \n" + cmd);
}
cmd += "\n";
cmd += commandsBuffer.remove(0);
} catch (SyntaxError e) {
done = true;
} catch (Exception e) {
commandsBuffer.clear();
throw new IllegalArgumentException(e.getMessage());
}
} while (!done);
AttributedStringBuilder sb = new AttributedStringBuilder();
sb.styled(AttributedStyle::bold, cmd);
sb.toAttributedString().println(terminal);
terminal.flush();
return finish(cmd);
}
if (!startedReading.compareAndSet(false, true)) {
throw new IllegalStateException();
}
Thread readLineThread = Thread.currentThread();
SignalHandler previousIntrHandler = null;
SignalHandler previousWinchHandler = null;
SignalHandler previousContHandler = null;
Attributes originalAttributes = null;
boolean dumb = isTerminalDumb();
try {
this.maskingCallback = maskingCallback;
/*
* This is the accumulator for VI-mode repeat count. That is, while in
* move mode, if you type 30x it will delete 30 characters. This is
* where the "30" is accumulated until the command is struck.
*/
repeatCount = 0;
mult = 1;
regionActive = RegionType.NONE;
regionMark = -1;
smallTerminalOffset = 0;
state = State.NORMAL;
modifiedHistory.clear();
setPrompt(prompt);
setRightPrompt(rightPrompt);
buf.clear();
if (buffer != null) {
buf.write(buffer);
}
if (nextCommandFromHistory && nextHistoryId > 0) {
if (history.size() > nextHistoryId) {
history.moveTo(nextHistoryId);
} else {
history.moveTo(history.last());
}
buf.write(history.current());
} else {
nextHistoryId = -1;
}
nextCommandFromHistory = false;
undo.clear();
parsedLine = null;
keyMap = MAIN;
if (history != null) {
history.attach(this);
}
try {
lock.lock();
this.reading = true;
previousIntrHandler = terminal.handle(Signal.INT, signal -> readLineThread.interrupt());
previousWinchHandler = terminal.handle(Signal.WINCH, this::handleSignal);
previousContHandler = terminal.handle(Signal.CONT, this::handleSignal);
originalAttributes = terminal.enterRawMode();
doDisplay();
// Move into application mode
if (!dumb) {
terminal.puts(Capability.keypad_xmit);
if (isSet(Option.AUTO_FRESH_LINE)) callWidget(FRESH_LINE);
if (isSet(Option.MOUSE)) terminal.trackMouse(Terminal.MouseTracking.Normal);
if (isSet(Option.BRACKETED_PASTE)) terminal.writer().write(BRACKETED_PASTE_ON);
}
callWidget(CALLBACK_INIT);
if (!isSet(Option.DISABLE_UNDO)) undo.newState(buf.copy());
// Draw initial prompt
redrawLine();
redisplay();
} finally {
lock.unlock();
}
while (true) {
KeyMap<Binding> local = null;
if (isInViCmdMode() && regionActive != RegionType.NONE) {
local = keyMaps.get(VISUAL);
}
Binding o = readBinding(getKeys(), local);
if (o == null) {
throw new EndOfFileException().partialLine(buf.length() > 0 ? buf.toString() : null);
}
Log.trace("Binding: ", o);
if (buf.length() == 0
&& getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) {
throw new EndOfFileException();
}
// If this is still false after handling the binding, then
// we reset our repeatCount to 0.
isArgDigit = false;
// Every command that can be repeated a specified number
// of times, needs to know how many times to repeat, so
// we figure that out here.
count = ((repeatCount == 0) ? 1 : repeatCount) * mult;
// Reset undo/redo flag
isUndo = false;
// Reset region after a paste
if (regionActive == RegionType.PASTE) {
regionActive = RegionType.NONE;
}
try {
lock.lock();
// Get executable widget
Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE)
? buf.copy()
: null;
Widget w = getWidget(o);
if (!w.apply()) {
beep();
}
if (!isSet(Option.DISABLE_UNDO)
&& !isUndo
&& copy != null
&& buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE)
&& !copy.toString().equals(buf.toString())) {
undo.newState(buf.copy());
}
switch (state) {
case DONE:
return finishBuffer();
case IGNORE:
return "";
case EOF:
throw new EndOfFileException();
case INTERRUPT:
throw new UserInterruptException(buf.toString());
}
if (!isArgDigit) {
/*
* If the operation performed wasn't a vi argument
* digit, then clear out the current repeatCount;
*/
repeatCount = 0;
mult = 1;
}
if (!dumb) {
redisplay();
}
} finally {
lock.unlock();
}
}
} catch (IOError e) {
if (e.getCause() instanceof InterruptedIOException) {
throw new UserInterruptException(buf.toString());
} else {
throw e;
}
} finally {
AtomicBoolean interrupted = new AtomicBoolean(Thread.interrupted());
try {
lock.lock();
this.reading = false;
Terminal.SignalHandler tmpHandler = terminal.handle(Signal.INT, s -> interrupted.set(true));
if (previousIntrHandler == null) {
previousIntrHandler = tmpHandler;
}
cleanup();
if (originalAttributes != null) {
terminal.setAttributes(originalAttributes);
}
if (previousIntrHandler != null) {
terminal.handle(Signal.INT, previousIntrHandler);
}
if (previousWinchHandler != null) {
terminal.handle(Signal.WINCH, previousWinchHandler);
}
if (previousContHandler != null) {
terminal.handle(Signal.CONT, previousContHandler);
}
} finally {
lock.unlock();
startedReading.set(false);
if (interrupted.get()) {
Thread.currentThread().interrupt();
}
}
}
}
Çok teşekkürler hocam yeni bir şey kattın.Ya Scanner kullan ya Console. Ikisini birden kullanma. System.console().readLine() yaptigindan itibaren Windows'un terminal input modu degisiyor. Scanner dogru bi sekilde line editleri takip edemez hale geliyor. Console yerine sadece Scanner kullandigimda okumalar bozulmuyor. Sadece console kullandigimda da bozulmuyor. Ikisini birden kullandiginda bozuluyor.
Bunun sebebi Windows'ta Java, default olarak JLine kullaniyor. JLine napiyorda Scanner'i bozuyor diyorsan, inan bi fikrim yok ama bozuyor. Eger programi;-Djdk.console=java.baseVM secenegiyle baslatirsan duzgun calisiyor.
Eki Görüntüle 183341
Yerinde olsam ikisini de kullanmam, direkt JLine kullanirim. Daha gelismis bir arac. Oto tamamlama, gecmis vs ozellikleri de sunacak sana. Platform belirsizliginden kurtulmus olurum. Daha iyi toollar olur elimde. Merak ediyorsan kendin oturup JLine.readLine yaparken ne yapiyor inceleyebilirsin. Kodu bayagi uzundu. Usendim okumaya.
Not: Bahsi gecen her seyi JDK 24 ile test ettim. Daha onceki versiyonlar icin dogru olmayabilir. JDK 22'den beri JLine default haline gelmis.
Asagidaki kodun bulundugu paket;package jdk.internal.org.jline.reader.impl;(GitHub)
Java:public String readLine(String prompt, String rightPrompt, MaskingCallback maskingCallback, String buffer) throws UserInterruptException, EndOfFileException { // prompt may be null // maskingCallback may be null // buffer may be null if (!commandsBuffer.isEmpty()) { String cmd = commandsBuffer.remove(0); boolean done = false; do { try { parser.parse(cmd, cmd.length() + 1, ParseContext.ACCEPT_LINE); done = true; } catch (EOFError e) { if (commandsBuffer.isEmpty()) { throw new IllegalArgumentException("Incompleted command: \n" + cmd); } cmd += "\n"; cmd += commandsBuffer.remove(0); } catch (SyntaxError e) { done = true; } catch (Exception e) { commandsBuffer.clear(); throw new IllegalArgumentException(e.getMessage()); } } while (!done); AttributedStringBuilder sb = new AttributedStringBuilder(); sb.styled(AttributedStyle::bold, cmd); sb.toAttributedString().println(terminal); terminal.flush(); return finish(cmd); } if (!startedReading.compareAndSet(false, true)) { throw new IllegalStateException(); } Thread readLineThread = Thread.currentThread(); SignalHandler previousIntrHandler = null; SignalHandler previousWinchHandler = null; SignalHandler previousContHandler = null; Attributes originalAttributes = null; boolean dumb = isTerminalDumb(); try { this.maskingCallback = maskingCallback; /* * This is the accumulator for VI-mode repeat count. That is, while in * move mode, if you type 30x it will delete 30 characters. This is * where the "30" is accumulated until the command is struck. */ repeatCount = 0; mult = 1; regionActive = RegionType.NONE; regionMark = -1; smallTerminalOffset = 0; state = State.NORMAL; modifiedHistory.clear(); setPrompt(prompt); setRightPrompt(rightPrompt); buf.clear(); if (buffer != null) { buf.write(buffer); } if (nextCommandFromHistory && nextHistoryId > 0) { if (history.size() > nextHistoryId) { history.moveTo(nextHistoryId); } else { history.moveTo(history.last()); } buf.write(history.current()); } else { nextHistoryId = -1; } nextCommandFromHistory = false; undo.clear(); parsedLine = null; keyMap = MAIN; if (history != null) { history.attach(this); } try { lock.lock(); this.reading = true; previousIntrHandler = terminal.handle(Signal.INT, signal -> readLineThread.interrupt()); previousWinchHandler = terminal.handle(Signal.WINCH, this::handleSignal); previousContHandler = terminal.handle(Signal.CONT, this::handleSignal); originalAttributes = terminal.enterRawMode(); doDisplay(); // Move into application mode if (!dumb) { terminal.puts(Capability.keypad_xmit); if (isSet(Option.AUTO_FRESH_LINE)) callWidget(FRESH_LINE); if (isSet(Option.MOUSE)) terminal.trackMouse(Terminal.MouseTracking.Normal); if (isSet(Option.BRACKETED_PASTE)) terminal.writer().write(BRACKETED_PASTE_ON); } callWidget(CALLBACK_INIT); if (!isSet(Option.DISABLE_UNDO)) undo.newState(buf.copy()); // Draw initial prompt redrawLine(); redisplay(); } finally { lock.unlock(); } while (true) { KeyMap<Binding> local = null; if (isInViCmdMode() && regionActive != RegionType.NONE) { local = keyMaps.get(VISUAL); } Binding o = readBinding(getKeys(), local); if (o == null) { throw new EndOfFileException().partialLine(buf.length() > 0 ? buf.toString() : null); } Log.trace("Binding: ", o); if (buf.length() == 0 && getLastBinding().charAt(0) == originalAttributes.getControlChar(ControlChar.VEOF)) { throw new EndOfFileException(); } // If this is still false after handling the binding, then // we reset our repeatCount to 0. isArgDigit = false; // Every command that can be repeated a specified number // of times, needs to know how many times to repeat, so // we figure that out here. count = ((repeatCount == 0) ? 1 : repeatCount) * mult; // Reset undo/redo flag isUndo = false; // Reset region after a paste if (regionActive == RegionType.PASTE) { regionActive = RegionType.NONE; } try { lock.lock(); // Get executable widget Buffer copy = buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) ? buf.copy() : null; Widget w = getWidget(o); if (!w.apply()) { beep(); } if (!isSet(Option.DISABLE_UNDO) && !isUndo && copy != null && buf.length() <= getInt(FEATURES_MAX_BUFFER_SIZE, DEFAULT_FEATURES_MAX_BUFFER_SIZE) && !copy.toString().equals(buf.toString())) { undo.newState(buf.copy()); } switch (state) { case DONE: return finishBuffer(); case IGNORE: return ""; case EOF: throw new EndOfFileException(); case INTERRUPT: throw new UserInterruptException(buf.toString()); } if (!isArgDigit) { /* * If the operation performed wasn't a vi argument * digit, then clear out the current repeatCount; */ repeatCount = 0; mult = 1; } if (!dumb) { redisplay(); } } finally { lock.unlock(); } } } catch (IOError e) { if (e.getCause() instanceof InterruptedIOException) { throw new UserInterruptException(buf.toString()); } else { throw e; } } finally { AtomicBoolean interrupted = new AtomicBoolean(Thread.interrupted()); try { lock.lock(); this.reading = false; Terminal.SignalHandler tmpHandler = terminal.handle(Signal.INT, s -> interrupted.set(true)); if (previousIntrHandler == null) { previousIntrHandler = tmpHandler; } cleanup(); if (originalAttributes != null) { terminal.setAttributes(originalAttributes); } if (previousIntrHandler != null) { terminal.handle(Signal.INT, previousIntrHandler); } if (previousWinchHandler != null) { terminal.handle(Signal.WINCH, previousWinchHandler); } if (previousContHandler != null) { terminal.handle(Signal.CONT, previousContHandler); } } finally { lock.unlock(); startedReading.set(false); if (interrupted.get()) { Thread.currentThread().interrupt(); } } } }
Rica ederim. Sorunu nasil tespit ettigime dair sureci anlatacak olursam;Çok teşekkürler hocam yeni bir şey kattın.
private record Session(String username, int clearance) {}
public static void testMenuLoop() throws IOException {
Session session = new Session("charlie", 3);
FileSystem app = new FileSystem();
app.loadStoreIfPresent();
app.menuLoop(session);
}
Hocam çok makbule geçti, gidiş yolunu verdiğiniz için de teşekkür ederim, bu bilgiyi kullanacağım. Geçen senelerde yeşil forumda yine bir Java problemimi çözmüştünüz diye hatırlıyorum.Rica ederim. Sorunu nasil tespit ettigime dair sureci anlatacak olursam;
Username girerken, girilen metni editleyebilirken, menuLoop icerisinde girilen metni editlemeye kalktigimda backspace icin ^H gordugumde, readPassword'den kaynaklandigini dusunerek, loginFlow'u atladim;
Dogrudur, olabilir. Orda en cok mesaj attigim kategori Programlama kategorisiydi.Hocam çok makbule geçti, gidiş yolunu verdiğiniz için de teşekkür ederim, bu bilgiyi kullanacağım. Geçen senelerde yeşil forumda yine bir Java problemimi çözmüştünüz diye hatırlıyorum.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?