001    /*
002     * Copyright (C) 2012 eXo Platform SAS.
003     *
004     * This is free software; you can redistribute it and/or modify it
005     * under the terms of the GNU Lesser General Public License as
006     * published by the Free Software Foundation; either version 2.1 of
007     * the License, or (at your option) any later version.
008     *
009     * This software is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012     * Lesser General Public License for more details.
013     *
014     * You should have received a copy of the GNU Lesser General Public
015     * License along with this software; if not, write to the Free
016     * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017     * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018     */
019    
020    package org.crsh.cli.impl.lang;
021    
022    import java.io.IOException;
023    import java.lang.reflect.Array;
024    import java.util.Arrays;
025    import java.util.Iterator;
026    import java.util.NoSuchElementException;
027    import java.util.regex.Matcher;
028    import java.util.regex.Pattern;
029    
030    public class Util {
031    
032      /** . */
033      static final Pattern INDENT_PATTERN = Pattern.compile("(?<=^|\\n)[ \\t\\x0B\\f\\r]*(?=\\S)");
034    
035      /** . */
036      public static final String MAN_TAB = _tab(7);
037    
038      /** . */
039      public static final String MAN_TAB_EXTRA = _tab(7 + 4);
040    
041      /** . */
042      static final String[] tabIndex;
043    
044      static {
045        String[] tmp = new String[20];
046        for (int i = 0;i < tmp.length;i++) {
047          tmp[i] = _tab(i);
048        }
049        tabIndex = tmp;
050      }
051    
052      static String tab(int size) {
053        if (size < 0) {
054          throw new IllegalArgumentException();
055        }
056        if (size < tabIndex.length) {
057          return tabIndex[size];
058        } else {
059          return _tab(size);
060        }
061      }
062    
063      private static String _tab(int size) {
064        char[] tmp = new char[size];
065        Arrays.fill(tmp, ' ');
066        return new String(tmp);
067      }
068    
069      public static <A extends Appendable> A indent(int tab, CharSequence s, A appendable) throws IOException {
070        return indent(tab(tab), s, appendable);
071      }
072    
073      public static <A extends Appendable> A indent(String tab, CharSequence s, A appendable) throws IOException {
074        Matcher matcher = INDENT_PATTERN.matcher(s);
075        int prev = 0;
076        while (matcher.find()) {
077          int start = matcher.start();
078          appendable.append(s, prev, start);
079          appendable.append(tab);
080          prev = matcher.end();
081        }
082        appendable.append(s, prev, s.length());
083        return appendable;
084      }
085    
086      public static <T> Iterable<T[]> tuples(final Class<T> type, final Iterable<? extends T>... iterables) {
087        return new Iterable<T[]>() {
088          public Iterator<T[]> iterator() {
089            return new Iterator<T[]>() {
090              private final Iterator<?>[] iterators = new Iterator<?>[iterables.length];
091              private T[] next;
092              {
093                for (int i = 0;i < iterables.length;i++) {
094                  iterators[i] = iterables[i].iterator();
095                }
096              }
097              public boolean hasNext() {
098                if (next == null) {
099                  T[] tuple = (T[])Array.newInstance(type, 2);
100                  for (int i = 0;i < iterators.length;i++) {
101                    Iterator iterator = iterators[i];
102                    if (iterator.hasNext()) {
103                      tuple[i] = type.cast(iterator.next());
104                    } else {
105                      return false;
106                    }
107                  }
108                  next = tuple;
109                }
110                return true;
111              }
112              public T[] next() {
113                if (!hasNext()) {
114                  throw new NoSuchElementException();
115                }
116                T[] tmp = next;
117                next = null;
118                return tmp;
119              }
120              public void remove() {
121                throw new UnsupportedOperationException();
122              }
123            };
124          }
125        };
126      }
127    
128      public static <T> Iterable<? extends T> join(final Iterable<? extends T>... iterables) {
129        return new Iterable<T>() {
130          public Iterator<T> iterator() {
131            return new Iterator<T>() {
132              int index;
133              Iterator<? extends T> current;
134              T next;
135              public boolean hasNext() {
136                if (next == null) {
137                  while ((current == null || !current.hasNext()) && index < iterables.length) {
138                    current = iterables[index++].iterator();
139                  }
140                  if (current != null && current.hasNext()) {
141                    next = current.next();
142                  }
143                }
144                return next != null;
145              }
146              public T next() {
147                if (!hasNext()) {
148                  throw new NoSuchElementException();
149                }
150                T tmp = next;
151                next = null;
152                return tmp;
153              }
154              public void remove() {
155                throw new UnsupportedOperationException();
156              }
157            };
158          }
159        };
160      }
161    }