From b1bac93edf8b21798e01c049ee4998978f8b7a23 Mon Sep 17 00:00:00 2001 From: dariober Date: Sun, 4 Aug 2024 15:43:31 +0100 Subject: [PATCH] Add sessionDelete --- CHANGELOG.md | 2 + src/main/java/commandHelp/Command.java | 1 + src/main/java/commandHelp/CommandList.java | 14 ++++ .../java/samTextViewer/InteractiveInput.java | 61 ++++++++++++++++- src/main/java/session/SessionHandler.java | 43 ++++++++---- .../samTextViewer/InteractiveInputTest.java | 66 ++++++++++++------- src/test/java/session/SessionHandlerTest.java | 21 ++++-- 7 files changed, 165 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f10b97..09df434 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ New in 1.19.0 * `sessionList` + * `sessionDelete` + * Move ASCIIGenome files and settings to `~/.asciigenome` directory. * `print` command does not decode the URL escapes for line feed and carriage diff --git a/src/main/java/commandHelp/Command.java b/src/main/java/commandHelp/Command.java index 9e8e4fd..3830cb1 100644 --- a/src/main/java/commandHelp/Command.java +++ b/src/main/java/commandHelp/Command.java @@ -46,6 +46,7 @@ public enum Command { sessionOpen("sessionOpen"), sessionSave("sessionSave"), sessionList("sessionList"), + sessionDelete("sessionDelete"), reload("reload"), recentlyOpened("recentlyOpened"), dropTracks("dropTracks"), diff --git a/src/main/java/commandHelp/CommandList.java b/src/main/java/commandHelp/CommandList.java index bc32cc3..4cedda2 100644 --- a/src/main/java/commandHelp/CommandList.java +++ b/src/main/java/commandHelp/CommandList.java @@ -1485,6 +1485,19 @@ public static final List commandHelpList() + "* :code:`-n` List up to this many sessions. Default 10"); cmdList.add(cmd); + cmd = new CommandHelp(); + cmd.setName("sessionDelete"); + cmd.setArgs("[-f session.yml] "); + cmd.inSection = Section.SESSION; + cmd.setBriefDescription("Delete session by name."); + cmd.setAdditionalDescription( + "\n" + + "* :code:`-f` List sessions in this file. Default: " + + " :code:`\\~/.asciigenome/session.yaml`\n" + + "\n" + + "* :code:`sessionName` Session name to delete"); + cmdList.add(cmd); + cmd = new CommandHelp(); cmd.setName("reload"); cmd.setArgs("[track_regex = .*]..."); @@ -1774,6 +1787,7 @@ public static final List cmds() { paramList.add("sessionOpen"); paramList.add("sessionSave"); paramList.add("sessionList"); + paramList.add("sessionDelete"); paramList.add("reload"); paramList.add("recentlyOpened"); paramList.add("dropTracks"); diff --git a/src/main/java/samTextViewer/InteractiveInput.java b/src/main/java/samTextViewer/InteractiveInput.java index 9814192..520b687 100755 --- a/src/main/java/samTextViewer/InteractiveInput.java +++ b/src/main/java/samTextViewer/InteractiveInput.java @@ -1,5 +1,7 @@ package samTextViewer; +import static session.SessionHandler.writeSessions; + import colouring.Config; import colouring.ConfigKey; import com.google.common.base.Joiner; @@ -180,7 +182,14 @@ protected TrackProcessor processInput(String cmdConcatInput, TrackProcessor proc System.out.print("\033[0m"); console.clearScreen(); console.flush(); - SessionHandler.saveAs(SessionHandler.DEFAULT_SESSION_FILE, proc.toSession(), ""); + try { + SessionHandler.saveAs(SessionHandler.DEFAULT_SESSION_FILE, proc.toSession(), ""); + } catch (Exception e) { + System.err.println( + "Error saving session to file: " + SessionHandler.DEFAULT_SESSION_FILE); + System.err.println(e.getMessage()); + System.exit(1); + } System.exit(0); // * These commands change the GenomicCoordinates (navigate) but do not touch the tracks. @@ -290,6 +299,11 @@ protected TrackProcessor processInput(String cmdConcatInput, TrackProcessor proc args.remove(0); this.setInteractiveInputExitCode(this.listSessions(args, proc)); + } else if (cmdTokens.get(0).equals("sessionDelete")) { + List args = new ArrayList<>(cmdTokens); + args.remove(0); + this.setInteractiveInputExitCode(this.deleteSession(args, proc)); + } else if (cmdTokens.get(0).equals("setGenome")) { this.setGenome(cmdTokens, proc); @@ -891,6 +905,51 @@ private ExitCode listSessions(List args, TrackProcessor proc) return ExitCode.CLEAN_NO_FLUSH; } + private ExitCode deleteSession(List args, TrackProcessor proc) + throws InvalidGenomicCoordsException, IOException, InvalidCommandLineException { + File sessionYamlFile = + new File( + Utils.getArgForParam( + args, "-f", SessionHandler.DEFAULT_SESSION_FILE.getAbsolutePath())); + SessionHandler sh; + if (this.sessionHandler == null) { + try { + sh = new SessionHandler(sessionYamlFile); + } catch (Exception e) { + this.messages.add( + "Failed to process session file '" + sessionYamlFile + "':\n" + e.getMessage()); + return ExitCode.ERROR; + } + } else { + sh = this.sessionHandler; + } + if (args.size() == 0) { + this.messages.add("Please provide the name of the session to delete"); + return ExitCode.ERROR; + } + if (args.size() > 1) { + this.messages.add("Please provide only one session to delete"); + return ExitCode.ERROR; + } + String sessionName = args.get(0); + boolean found = sh.hasSessionName(sessionName); + if (!found) { + this.messages.add( + "No session with name '" + sessionName + "' found in file '" + sessionYamlFile + "'"); + return ExitCode.ERROR; + } + boolean deleted = sh.deleteSession(sessionName); + if (deleted) { + System.err.println( + Utils.padEndMultiLine("Session '" + sessionName + "' deleted", proc.getWindowSize())); + } else { + this.messages.add("Failed to delete session '" + sessionName + "'"); + return ExitCode.ERROR; + } + writeSessions(sh.getSessions(), sessionYamlFile); + return ExitCode.CLEAN_NO_FLUSH; + } + private void openSession(List args, TrackProcessor proc) throws IOException, InvalidCommandLineException { File sessionYamlFile = diff --git a/src/main/java/session/SessionHandler.java b/src/main/java/session/SessionHandler.java index 076371e..bde1329 100644 --- a/src/main/java/session/SessionHandler.java +++ b/src/main/java/session/SessionHandler.java @@ -10,10 +10,7 @@ import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; import com.google.common.base.Joiner; import exceptions.SessionException; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -75,6 +72,16 @@ private static void addOrReplaceSession(List sessions, Session session) sortSessionsByLastRead(sessions); } + public static void writeSessions(List sessions, File sessionFile) throws IOException { + YAMLFactory yf = new YAMLFactory(); + yf.configure(WRITE_DOC_START_MARKER, false); + ObjectMapper mapper = new ObjectMapper(yf); + FileOutputStream fos = new FileOutputStream(sessionFile); + SequenceWriter sw = mapper.writerWithDefaultPrettyPrinter().writeValues(fos); + sw.write(sessions); + sw.close(); + } + public static void saveAs(File sessionFile, Session session, String sessionName) throws IOException, SessionException { session.setSessionName(sessionName); @@ -83,13 +90,7 @@ public static void saveAs(File sessionFile, Session session, String sessionName) sessions = read(sessionFile); } addOrReplaceSession(sessions, session); - YAMLFactory yf = new YAMLFactory(); - yf.configure(WRITE_DOC_START_MARKER, false); - ObjectMapper mapper = new ObjectMapper(yf); - FileOutputStream fos = new FileOutputStream(sessionFile); - SequenceWriter sw = mapper.writerWithDefaultPrettyPrinter().writeValues(fos); - sw.write(sessions); - sw.close(); + writeSessions(sessions, sessionFile); } private static void sortSessionsByLastRead(List sessions) { @@ -134,6 +135,15 @@ public void setSessionFile(File sessionFile) { this.sessionFile = sessionFile; } + public boolean hasSessionName(String sessionName) { + for (Session x : this.getSessions()) { + if (x.getSessionName().equals(sessionName)) { + return true; + } + } + return false; + } + public String print(int upto, boolean mostRecentLast) throws IOException { List out = new ArrayList<>(); int i = 0; @@ -155,4 +165,15 @@ public String print(int upto, boolean mostRecentLast) throws IOException { out.add("Session file: " + this.getSessionFile()); return Joiner.on("\n").join(out); } + + public boolean deleteSession(String sessionName) { + Session ss; + try { + ss = this.get(sessionName); + } catch (SessionException e) { + return false; + } + this.getSessions().remove(ss); + return true; + } } diff --git a/src/test/java/samTextViewer/InteractiveInputTest.java b/src/test/java/samTextViewer/InteractiveInputTest.java index 6207e7a..2b8f4d1 100644 --- a/src/test/java/samTextViewer/InteractiveInputTest.java +++ b/src/test/java/samTextViewer/InteractiveInputTest.java @@ -36,12 +36,7 @@ public static class ProcessInput { } public ProcessInput processInput(InteractiveInput ip, String cmd, TrackProcessor p) - throws SQLException, - InvalidGenomicCoordsException, - InvalidCommandLineException, - IOException, - ClassNotFoundException, - InvalidRecordException { + throws InvalidGenomicCoordsException, IOException { ByteArrayOutputStream err = new ByteArrayOutputStream(); System.setErr(new PrintStream(err)); ip.processInput(cmd, p); @@ -116,6 +111,42 @@ public void canListCurrentSessionNameAndFile() assertTrue(pi.stderr.contains("Current session: no-fastafile")); } + @Test + public void canDeleteSession() + throws IOException, + InvalidConfigException, + SQLException, + InvalidGenomicCoordsException, + ClassNotFoundException, + InvalidRecordException, + InvalidCommandLineException { + new Config(null); + TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); + InteractiveInput ip = new InteractiveInput(new ConsoleReader(), 1); + + ProcessInput pi = processInput(ip, "sessionDelete", proc); + pi = processInput(ip, "sessionDelete -f test_data/session.yaml", proc); + assertEquals(ExitCode.ERROR, ip.getInteractiveInputExitCode()); + assertEquals("Please provide the name of the session to delete", pi.stderr.trim()); + + pi = processInput(ip, "sessionDelete", proc); + assertEquals(ExitCode.ERROR, ip.getInteractiveInputExitCode()); + assertEquals("Please provide the name of the session to delete", pi.stderr.trim()); + + File f = new File("tmp.yml"); + f.delete(); + Files.copy(Paths.get("test_data/session.yaml"), Paths.get("tmp.yml")); + + processInput(ip, "sessionDelete -f tmp.yml newSession", proc); + assertEquals(ExitCode.CLEAN_NO_FLUSH, ip.getInteractiveInputExitCode()); + String txt = new String(Files.readAllBytes(Paths.get("tmp.yml"))); + assertTrue(!txt.contains("newSession")); + + processInput(ip, "sessionDelete -f tmp.yml newSession", proc); + assertEquals(ExitCode.ERROR, ip.getInteractiveInputExitCode()); + f.delete(); + } + @Test public void canSaveCurrentSessionInPlace() throws IOException, @@ -124,7 +155,6 @@ public void canSaveCurrentSessionInPlace() InvalidGenomicCoordsException, ClassNotFoundException, InvalidRecordException, - InvalidCommandLineException, SessionException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); @@ -165,7 +195,6 @@ public void canReplaceGenome() IOException, ClassNotFoundException, InvalidRecordException, - InvalidCommandLineException, InvalidConfigException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); @@ -187,8 +216,7 @@ public void canOpenSessionWithFileMissing() SQLException, InvalidGenomicCoordsException, ClassNotFoundException, - InvalidRecordException, - InvalidCommandLineException { + InvalidRecordException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); @@ -213,8 +241,7 @@ public void canOpenSessionWithFastaFileMissing() SQLException, InvalidGenomicCoordsException, ClassNotFoundException, - InvalidRecordException, - InvalidCommandLineException { + InvalidRecordException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); @@ -275,8 +302,7 @@ public void canOpenSession() SQLException, InvalidGenomicCoordsException, ClassNotFoundException, - InvalidRecordException, - InvalidCommandLineException { + InvalidRecordException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); InteractiveInput ip = new InteractiveInput(new ConsoleReader(), 1); @@ -321,7 +347,6 @@ public void canSaveSession() InvalidGenomicCoordsException, ClassNotFoundException, InvalidRecordException, - InvalidCommandLineException, SessionException { new Config(null); TrackProcessor proc = gimmeTrackProcessor("chr7:1001-1800", 80); @@ -341,8 +366,7 @@ public void canPrintGenome() ClassNotFoundException, InvalidGenomicCoordsException, InvalidRecordException, - SQLException, - InvalidCommandLineException { + SQLException { new Config(null); TrackProcessor proc; InteractiveInput ip = new InteractiveInput(new ConsoleReader(), 1); @@ -358,7 +382,6 @@ public void canMovePositionByColumn() InvalidRecordException, ClassNotFoundException, SQLException, - InvalidCommandLineException, InvalidConfigException { new Config(null); @@ -422,12 +445,7 @@ public void canMovePositionByColumn() @Test public void canPrintHelp() - throws InvalidGenomicCoordsException, - IOException, - ClassNotFoundException, - InvalidRecordException, - SQLException, - InvalidCommandLineException { + throws InvalidGenomicCoordsException, IOException, InvalidRecordException { InteractiveInput ip = new InteractiveInput(null, 1); diff --git a/src/test/java/session/SessionHandlerTest.java b/src/test/java/session/SessionHandlerTest.java index bc79d74..bf21184 100644 --- a/src/test/java/session/SessionHandlerTest.java +++ b/src/test/java/session/SessionHandlerTest.java @@ -1,7 +1,6 @@ package session; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import colouring.Config; import exceptions.InvalidColourException; @@ -27,11 +26,19 @@ public class SessionHandlerTest { @Test - public void testGetSessionByNameOrIndex() - throws IOException, - SessionException, - InvalidGenomicCoordsException, - InvalidTrackTypeException { + public void canDeleteSession() throws IOException, SessionException { + InputStream yaml = Files.newInputStream(Paths.get("test_data/session.yaml")); + SessionHandler sh = new SessionHandler(new File("test_data/session.yaml")); + sh.get("newSession"); + boolean deleted = sh.deleteSession("newSession"); + assertTrue(deleted); + + deleted = sh.deleteSession("newSession"); + assertFalse(deleted); + } + + @Test + public void testGetSessionByNameOrIndex() throws IOException, SessionException { InputStream yaml = Files.newInputStream(Paths.get("test_data/session.yaml")); SessionHandler sh = new SessionHandler(new File("test_data/session.yaml")); assertEquals("no-fastafile", sh.get("1").getSessionName());