src/jdk.internal.le/share/classes/jdk/internal/jline/console/KillRing.java
changeset 53333 fd6de53a0d6e
parent 53332 ab474ef0a0ac
parent 53010 086dfcfc3731
child 53334 b94283cb226b
equal deleted inserted replaced
53332:ab474ef0a0ac 53333:fd6de53a0d6e
     1 /*
       
     2  * Copyright (c) 2002-2016, the original author or authors.
       
     3  *
       
     4  * This software is distributable under the BSD license. See the terms of the
       
     5  * BSD license in the documentation provided with this software.
       
     6  *
       
     7  * http://www.opensource.org/licenses/bsd-license.php
       
     8  */
       
     9 package jdk.internal.jline.console;
       
    10 
       
    11 /**
       
    12  * The kill ring class keeps killed text in a fixed size ring. In this
       
    13  * class we also keep record of whether or not the last command was a
       
    14  * kill or a yank. Depending on this, the class may behave
       
    15  * different. For instance, two consecutive kill-word commands fill
       
    16  * the same slot such that the next yank will return the two
       
    17  * previously killed words instead that only the last one. Likewise
       
    18  * yank pop requires that the previous command was either a yank or a
       
    19  * yank-pop.
       
    20  */
       
    21 public final class KillRing {
       
    22 
       
    23     /**
       
    24      * Default size is 60, like in emacs.
       
    25      */
       
    26     private static final int DEFAULT_SIZE = 60;
       
    27 
       
    28     private final String[] slots;
       
    29     private int head = 0;
       
    30     private boolean lastKill = false;
       
    31     private boolean lastYank = false;
       
    32 
       
    33     /**
       
    34      * Creates a new kill ring of the given size.
       
    35      */
       
    36     public KillRing(int size) {
       
    37         slots = new String[size];
       
    38     }
       
    39 
       
    40     /**
       
    41      * Creates a new kill ring of the default size. See {@link #DEFAULT_SIZE}.
       
    42      */
       
    43     public KillRing() {
       
    44         this(DEFAULT_SIZE);
       
    45     }
       
    46 
       
    47     /**
       
    48      * Resets the last-yank state.
       
    49      */
       
    50     public void resetLastYank() {
       
    51         lastYank = false;
       
    52     }
       
    53 
       
    54     /**
       
    55      * Resets the last-kill state.
       
    56      */
       
    57     public void resetLastKill() {
       
    58         lastKill = false;
       
    59     }
       
    60 
       
    61     /**
       
    62      * Returns {@code true} if the last command was a yank.
       
    63      */
       
    64     public boolean lastYank() {
       
    65         return lastYank;
       
    66     }
       
    67 
       
    68     /**
       
    69      * Adds the string to the kill-ring. Also sets lastYank to false
       
    70      * and lastKill to true.
       
    71      */
       
    72     public void add(String str) {
       
    73         lastYank = false;
       
    74 
       
    75         if (lastKill) {
       
    76             if (slots[head] != null) {
       
    77                 slots[head] += str;
       
    78                 return;
       
    79             }
       
    80         }
       
    81 
       
    82         lastKill = true;
       
    83         next();
       
    84         slots[head] = str;
       
    85     }
       
    86 
       
    87     /**
       
    88      * Adds the string to the kill-ring product of killing
       
    89      * backwards. If the previous command was a kill text one then
       
    90      * adds the text at the beginning of the previous kill to avoid
       
    91      * that two consecutive backwards kills followed by a yank leaves
       
    92      * things reversed.
       
    93      */
       
    94     public void addBackwards(String str) {
       
    95         lastYank = false;
       
    96 
       
    97         if (lastKill) {
       
    98             if (slots[head] != null) {
       
    99                 slots[head] = str + slots[head];
       
   100                 return;
       
   101             }
       
   102         }
       
   103 
       
   104         lastKill = true;
       
   105         next();
       
   106         slots[head] = str;
       
   107     }
       
   108 
       
   109     /**
       
   110      * Yanks a previously killed text. Returns {@code null} if the
       
   111      * ring is empty.
       
   112      */
       
   113     public String yank() {
       
   114         lastKill = false;
       
   115         lastYank = true;
       
   116         return slots[head];
       
   117     }
       
   118 
       
   119     /**
       
   120      * Moves the pointer to the current slot back and returns the text
       
   121      * in that position. If the previous command was not yank returns
       
   122      * null.
       
   123      */
       
   124     public String yankPop() {
       
   125         lastKill = false;
       
   126         if (lastYank) {
       
   127             prev();
       
   128             return slots[head];
       
   129         }
       
   130         return null;
       
   131     }
       
   132 
       
   133     /**
       
   134      * Moves the pointer to the current slot forward. If the end of
       
   135      * the slots is reached then points back to the beginning.
       
   136      */
       
   137     private void next() {
       
   138         if (head == 0 && slots[0] == null) {
       
   139             return;
       
   140         }
       
   141         head++;
       
   142         if (head == slots.length) {
       
   143             head = 0;
       
   144         }
       
   145     }
       
   146 
       
   147     /**
       
   148      * Moves the pointer to the current slot backwards. If the
       
   149      * beginning of the slots is reached then traverses the slot
       
   150      * backwards until one with not null content is found.
       
   151      */
       
   152     private void prev() {
       
   153         head--;
       
   154         if (head == -1) {
       
   155             int x = slots.length - 1;
       
   156             for (; x >= 0; x--) {
       
   157                 if (slots[x] != null) {
       
   158                     break;
       
   159                 }
       
   160             }
       
   161             head = x;
       
   162         }
       
   163     }
       
   164 }