Class DefaultHistory

  • All Implemented Interfaces:
    java.lang.Iterable<History.Entry>, History

    public class DefaultHistory
    extends java.lang.Object
    implements History
    Default implementation of History with file-based persistent storage.

    This class provides a complete implementation of the History interface with the following features:

    • In-memory storage of history entries with configurable size limits
    • Persistent storage in a text file with configurable location and size limits
    • Support for timestamped history entries
    • Filtering of entries based on patterns defined in the LineReader.HISTORY_IGNORE variable
    • Options to ignore duplicates, reduce blanks, and ignore commands starting with spaces
    • Incremental saving of history entries
    • History navigation (previous/next, first/last, etc.)

    The history file format is either plain text with one command per line, or if LineReader.Option.HISTORY_TIMESTAMPED is set, each line starts with a timestamp in milliseconds since epoch, followed by a colon and the command text.

    Applications using this class should install a shutdown hook to call save() to ensure history is saved to disk when the application exits.

    Example usage:

     LineReader reader = LineReaderBuilder.builder()
         .variable(LineReader.HISTORY_FILE, Paths.get(System.getProperty("user.home"), ".myapp_history"))
         .build();
     // History is automatically attached to the reader
    
     // To save history manually:
     ((DefaultHistory) reader.getHistory()).save();
     
    See Also:
    History, LineReader.HISTORY_FILE, LineReader.HISTORY_SIZE, LineReader.HISTORY_FILE_SIZE, LineReader.Option.HISTORY_TIMESTAMPED, LineReader.Option.HISTORY_IGNORE_SPACE, LineReader.Option.HISTORY_IGNORE_DUPS, LineReader.Option.HISTORY_REDUCE_BLANKS
    • Field Summary

      Fields 
      Modifier and Type Field Description
      static int DEFAULT_HISTORY_FILE_SIZE
      Default maximum number of history entries to keep in the history file.
      static int DEFAULT_HISTORY_SIZE
      Default maximum number of history entries to keep in memory.
    • Constructor Summary

      Constructors 
      Constructor Description
      DefaultHistory()
      Creates a new DefaultHistory instance.
      DefaultHistory​(LineReader reader)
      Creates a new DefaultHistory instance and attaches it to the specified LineReader.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void add​(java.time.Instant time, java.lang.String line)
      Adds a new entry to the history.
      protected void addHistoryLine​(java.nio.file.Path path, java.lang.String line)
      Adds a history line to the specified history file.
      protected void addHistoryLine​(java.nio.file.Path path, java.lang.String line, boolean checkDuplicates)
      Adds a history line to the specified history file with an option to check for duplicates.
      void append​(java.nio.file.Path file, boolean incremental)
      Appends history entries to the specified file.
      void attach​(LineReader reader)
      Attaches this history to a LineReader.
      protected DefaultHistory.EntryImpl createEntry​(int index, java.time.Instant time, java.lang.String line)
      Create a history entry.
      java.lang.String current()
      Returns the text of the history entry at the current cursor position.
      int first()
      Returns the index of the first element in the history.
      java.lang.String get​(int index)
      Returns the history item at the specified index.
      int index()
      Returns the current index in the history.
      protected void internalAdd​(java.time.Instant time, java.lang.String line)
      Adds a line to the history with the specified timestamp.
      protected void internalAdd​(java.time.Instant time, java.lang.String line, boolean checkDuplicates)
      Adds a line to the history with the specified timestamp and an option to check for duplicates.
      boolean isEmpty()
      Checks if the history is empty.
      java.util.ListIterator<History.Entry> iterator​(int index)
      Returns a list iterator over the history entries starting at the specified index.
      int last()
      Returns the index of the last element in the history.
      void load()
      Loads history from the file specified by the LineReader.HISTORY_FILE variable.
      protected boolean matchPatterns​(java.lang.String patterns, java.lang.String line)
      Checks if a line matches any of the specified patterns.
      boolean moveTo​(int index)
      Moves the history cursor to the specified index.
      void moveToEnd()
      Moves the history cursor to the end of the history buffer.
      boolean moveToFirst()
      Moves the history cursor to the first entry.
      boolean moveToLast()
      Moves the history cursor to the last entry.
      boolean next()
      Moves the history cursor to the next (newer) entry.
      boolean previous()
      Moves the history cursor to the previous (older) entry.
      void purge()
      Clears the history and deletes the history file.
      void read​(java.nio.file.Path file, boolean checkDuplicates)
      Reads history entries from the specified file and adds them to the current history.
      void resetIndex()
      Reset index after remove
      void save()
      Saves the history to the default history file.
      int size()
      Returns the number of items in the history.
      java.util.Spliterator<History.Entry> spliterator()  
      java.lang.String toString()  
      protected void trimHistory​(java.nio.file.Path path, int max)
      Trims the history file to the specified maximum number of entries.
      void write​(java.nio.file.Path file, boolean incremental)
      Writes the history to the specified file, optionally replacing the existing file.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
      • Methods inherited from interface java.lang.Iterable

        forEach
    • Field Detail

      • DEFAULT_HISTORY_SIZE

        public static final int DEFAULT_HISTORY_SIZE
        Default maximum number of history entries to keep in memory. This value is used when the LineReader.HISTORY_SIZE variable is not set.
        See Also:
        Constant Field Values
      • DEFAULT_HISTORY_FILE_SIZE

        public static final int DEFAULT_HISTORY_FILE_SIZE
        Default maximum number of history entries to keep in the history file. This value is used when the LineReader.HISTORY_FILE_SIZE variable is not set.
        See Also:
        Constant Field Values
    • Constructor Detail

      • DefaultHistory

        public DefaultHistory()
        Creates a new DefaultHistory instance.
      • DefaultHistory

        public DefaultHistory​(LineReader reader)
        Creates a new DefaultHistory instance and attaches it to the specified LineReader.
        Parameters:
        reader - the LineReader to attach to
    • Method Detail

      • attach

        public void attach​(LineReader reader)
        Attaches this history to a LineReader.

        This method associates the history with a LineReader and loads the history from the file specified by the LineReader.HISTORY_FILE variable. If the history is already attached to the given reader, this method does nothing.

        Specified by:
        attach in interface History
        Parameters:
        reader - the LineReader to attach this history to
      • load

        public void load()
                  throws java.io.IOException
        Loads history from the file specified by the LineReader.HISTORY_FILE variable.

        This method clears the current history and loads entries from the history file. If the file doesn't exist or can't be read, the history will be cleared. If individual lines in the history file are malformed, they will be skipped.

        Specified by:
        load in interface History
        Throws:
        java.io.IOException - if an I/O error occurs while reading the history file
      • read

        public void read​(java.nio.file.Path file,
                         boolean checkDuplicates)
                  throws java.io.IOException
        Reads history entries from the specified file and adds them to the current history.

        Unlike load(), this method does not clear the existing history before adding entries from the file. If the file doesn't exist or can't be read, the history will be cleared. If individual lines in the history file are malformed, they will be skipped.

        Specified by:
        read in interface History
        Parameters:
        file - the file to read history from, or null to use the default history file
        checkDuplicates - whether to check for and skip duplicate entries
        Throws:
        java.io.IOException - if an I/O error occurs while reading the history file
      • addHistoryLine

        protected void addHistoryLine​(java.nio.file.Path path,
                                      java.lang.String line)
        Adds a history line to the specified history file.
        Parameters:
        path - the path to the history file
        line - the line to add
      • addHistoryLine

        protected void addHistoryLine​(java.nio.file.Path path,
                                      java.lang.String line,
                                      boolean checkDuplicates)
        Adds a history line to the specified history file with an option to check for duplicates.
        Parameters:
        path - the path to the history file
        line - the line to add
        checkDuplicates - whether to check for duplicate entries
      • purge

        public void purge()
                   throws java.io.IOException
        Clears the history and deletes the history file.

        This method removes all history entries from memory and deletes the history file if it exists.

        Specified by:
        purge in interface History
        Throws:
        java.io.IOException - if an I/O error occurs while deleting the history file
      • write

        public void write​(java.nio.file.Path file,
                          boolean incremental)
                   throws java.io.IOException
        Writes the history to the specified file, optionally replacing the existing file.

        If the file exists, it will be deleted and recreated. If incremental is true, only entries that haven't been saved before will be written.

        Specified by:
        write in interface History
        Parameters:
        file - the file to write history to, or null to use the default history file
        incremental - whether to write only new entries (true) or all entries (false)
        Throws:
        java.io.IOException - if an I/O error occurs while writing the history file
      • append

        public void append​(java.nio.file.Path file,
                           boolean incremental)
                    throws java.io.IOException
        Appends history entries to the specified file.

        Unlike write(Path, boolean), this method does not delete the existing file before writing. If incremental is true, only entries that haven't been saved before will be appended.

        Specified by:
        append in interface History
        Parameters:
        file - the file to append history to, or null to use the default history file
        incremental - whether to append only new entries (true) or all entries (false)
        Throws:
        java.io.IOException - if an I/O error occurs while appending to the history file
      • save

        public void save()
                  throws java.io.IOException
        Saves the history to the default history file.

        This method appends any new history entries (those that haven't been saved before) to the history file. It's typically called when the application exits to ensure that history is preserved.

        Specified by:
        save in interface History
        Throws:
        java.io.IOException - if an I/O error occurs while saving the history file
      • trimHistory

        protected void trimHistory​(java.nio.file.Path path,
                                   int max)
                            throws java.io.IOException
        Trims the history file to the specified maximum number of entries.
        Parameters:
        path - the path to the history file
        max - the maximum number of entries to keep
        Throws:
        java.io.IOException - if an I/O error occurs
      • createEntry

        protected DefaultHistory.EntryImpl createEntry​(int index,
                                                       java.time.Instant time,
                                                       java.lang.String line)
        Create a history entry. Subclasses may override to use their own entry implementations.
        Parameters:
        index - index of history entry
        time - entry creation time
        line - the entry text
        Returns:
        entry object
      • size

        public int size()
        Description copied from interface: History
        Returns the number of items in the history.
        Specified by:
        size in interface History
        Returns:
        the number of history items
      • isEmpty

        public boolean isEmpty()
        Description copied from interface: History
        Checks if the history is empty.
        Specified by:
        isEmpty in interface History
        Returns:
        true if the history contains no items
      • index

        public int index()
        Description copied from interface: History
        Returns the current index in the history.
        Specified by:
        index in interface History
        Returns:
        the current index
      • first

        public int first()
        Description copied from interface: History
        Returns the index of the first element in the history.
        Specified by:
        first in interface History
        Returns:
        the index of the first history item
      • last

        public int last()
        Description copied from interface: History
        Returns the index of the last element in the history.
        Specified by:
        last in interface History
        Returns:
        the index of the last history item
      • get

        public java.lang.String get​(int index)
        Description copied from interface: History
        Returns the history item at the specified index.
        Specified by:
        get in interface History
        Parameters:
        index - the index of the history item to retrieve
        Returns:
        the history item at the specified index
      • add

        public void add​(java.time.Instant time,
                        java.lang.String line)
        Adds a new entry to the history.

        This method adds a new entry to the history with the specified timestamp and command text. The entry may be filtered based on various criteria such as:

        If LineReader.Option.HISTORY_INCREMENTAL is set, the history will be saved to disk after adding the entry.

        Specified by:
        add in interface History
        Parameters:
        time - the timestamp for the new entry
        line - the command text for the new entry
        Throws:
        java.lang.NullPointerException - if time or line is null
      • matchPatterns

        protected boolean matchPatterns​(java.lang.String patterns,
                                        java.lang.String line)
        Checks if a line matches any of the specified patterns.
        Parameters:
        patterns - the patterns to match against, separated by '|'
        line - the line to check
        Returns:
        true if the line matches any of the patterns
      • internalAdd

        protected void internalAdd​(java.time.Instant time,
                                   java.lang.String line)
        Adds a line to the history with the specified timestamp.
        Parameters:
        time - the timestamp for the history entry
        line - the line to add
      • internalAdd

        protected void internalAdd​(java.time.Instant time,
                                   java.lang.String line,
                                   boolean checkDuplicates)
        Adds a line to the history with the specified timestamp and an option to check for duplicates.
        Parameters:
        time - the timestamp for the history entry
        line - the line to add
        checkDuplicates - whether to check for duplicate entries
      • iterator

        public java.util.ListIterator<History.Entry> iterator​(int index)
        Description copied from interface: History
        Returns a list iterator over the history entries starting at the specified index.
        Specified by:
        iterator in interface History
        Parameters:
        index - the index to start iterating from
        Returns:
        a list iterator over the history entries
      • spliterator

        public java.util.Spliterator<History.Entry> spliterator()
        Specified by:
        spliterator in interface java.lang.Iterable<History.Entry>
      • resetIndex

        public void resetIndex()
        Description copied from interface: History
        Reset index after remove
        Specified by:
        resetIndex in interface History
      • moveToLast

        public boolean moveToLast()
        Moves the history cursor to the last entry.

        This positions the cursor at the most recent history entry, which is one position before the position set by moveToEnd(). This is typically used when starting to navigate backward through history.

        Specified by:
        moveToLast in interface History
        Returns:
        true if the cursor was moved, false if there were no history entries or the cursor was already at the last entry
      • moveTo

        public boolean moveTo​(int index)
        Moves the history cursor to the specified index.

        This positions the cursor at the history entry with the given index, if it exists. The index is absolute, taking into account the offset of the history buffer.

        Specified by:
        moveTo in interface History
        Parameters:
        index - the absolute index to move to
        Returns:
        true if the cursor was moved, false if the index was out of range
      • moveToFirst

        public boolean moveToFirst()
        Moves the history cursor to the first entry.

        This positions the cursor at the oldest history entry in the buffer. This is typically used when starting to navigate forward through history.

        Specified by:
        moveToFirst in interface History
        Returns:
        true if the cursor was moved, false if there were no history entries or the cursor was already at the first entry
      • moveToEnd

        public void moveToEnd()
        Moves the history cursor to the end of the history buffer.

        This positions the cursor after the last history entry, which represents the current input line (not yet in history). This is the default position when not navigating through history.

        Specified by:
        moveToEnd in interface History
      • current

        public java.lang.String current()
        Returns the text of the history entry at the current cursor position.

        If the cursor is at the end of the history (after the last entry), this method returns an empty string.

        Specified by:
        current in interface History
        Returns:
        the text of the current history entry, or an empty string if at the end
      • previous

        public boolean previous()
        Moves the history cursor to the previous (older) entry.

        This is typically called when the user presses the up arrow key to navigate backward through history. If the cursor is already at the first entry, this method does nothing and returns false.

        Specified by:
        previous in interface History
        Returns:
        true if the cursor was moved, false if already at the first entry
      • next

        public boolean next()
        Moves the history cursor to the next (newer) entry.

        This is typically called when the user presses the down arrow key to navigate forward through history. If the cursor is already at the end of history, this method does nothing and returns false.

        Specified by:
        next in interface History
        Returns:
        true if the cursor was moved, false if already at the end of history
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object