Commits

Steve Losh committed e63372b

Type-hint the shit out of everything.

  • Participants
  • Parent commits 3bbb970

Comments (0)

Files changed (8)

docs/1-installation.markdown

 
 Add this to your `project.clj`:
 
-    [clojure-lanterna "0.9.2"]
+    [clojure-lanterna "0.9.3"]
 
 That's it.

docs/4-reference.markdown

 * `:unix` - Force a UNIX text-based console.
 * `:cygwin` - Force a Cygwin text-based console.
 
+### Palettes
+
+When creating a Swing Terminal or Screen, you can choose the color palette to
+use.  Text-based Terminals and Screens will use the user's color scheme, of
+course.
+
+The following palettes are supported:
+
+* `:gnome` - Gnome Terminal's colors.
+* `:windows-xp` - The colors of the Windows XP command prompt.
+* `:xterm` - Xterm's colors.
+* `:putty` - Putty's colors.
+* `:mac-os-x` - The colors of Mac OS X's Terminal.app.
+
+### Font Names
+
+When giving a font name, it should be a string naming a font family on your
+system.  For example: `"Consolas"`, `"Courier New"`, or `"Monaco"`.
+
+To see a the fonts available on your system you can call
+[`get-available-fonts`](#lanternaterminalget-available-fonts).
+
 Terminals
 ---------
 
 * `:resize-listener` - A function to call when the terminal is resized.  This
   function should take two parameters: the new number of columns, and the new
   number of rows.
+*
 
-The `:rows`, `:cols`, and `:charset` options are really just a suggestion!
+The `:rows`, `:cols`, `:font`, `:font-size`, `:palette` and `:charset` options
+are really just a suggestion!
 
-The text-based terminals will ignore rows and columns and will be the size of
-the user's window.
+The text-based terminals will ignore rows, columns, fonts and palettes.  They
+will be determined by the user's terminal window.
 
-The Swing terminal will start out at this size but can be resized later by the
-user, and will ignore the charset entirely.
+The Swing terminal will start out at the given size but can be resized later by
+the user, and will ignore the charset entirely.
 
 God only know what Cygwin will do.
 
 when you call [`get-terminal`](#lanternaterminalget-terminal).  It's here if you
 *do* need it though.
 
+### lanterna.terminal/get-available-fonts
+
+    :::clojure
+    (get-available-fonts)
+
+Return a set of strings of the names of available fonts on the current system.
+
 Screens
 -------
 
   :license {:name "LGPL"}
   :dependencies [[org.clojure/clojure "1.4.0"]
                  [com.googlecode.lanterna/lanterna "2.0.1"]]
+  :java-source-paths ["./java"]
   ; :repositories {"sonatype-snapshots" "https://oss.sonatype.org/content/repositories/snapshots"}
   )

src/README.markdown

Empty file added.

src/lanterna/common.clj

 (ns lanterna.common
+  (:import com.googlecode.lanterna.input.Key)
   (:require [lanterna.constants :as c]))
 
 
-(defn parse-key [k]
+(defn parse-key [^Key k]
   (when k
     (let [kind (c/key-codes (.getKind k))]
       (if (= kind :normal)

src/lanterna/constants.clj

            com.googlecode.lanterna.screen.Screen
            com.googlecode.lanterna.terminal.Terminal
            com.googlecode.lanterna.screen.ScreenCharacterStyle
+           com.googlecode.lanterna.terminal.swing.TerminalPalette
            com.googlecode.lanterna.input.Key))
 
 
    com.googlecode.lanterna.input.Key$Kind/CursorLocation :cursor-location})
 
 
+(def palettes
+  {:gnome      TerminalPalette/GNOME_TERMINAL
+   :vga        TerminalPalette/STANDARD_VGA
+   :windows-xp TerminalPalette/WINDOWS_XP_COMMAND_PROMPT
+   :mac-os-x   TerminalPalette/MAC_OS_X_TERMINAL_APP
+   :xterm      TerminalPalette/PUTTY
+   :putty      TerminalPalette/XTERM})
+
 (def enter-styles
   {:bold com.googlecode.lanterna.terminal.Terminal$SGR/ENTER_BOLD
    :reverse com.googlecode.lanterna.terminal.Terminal$SGR/ENTER_REVERSE

src/lanterna/screen.clj

 (ns lanterna.screen
-  (:import com.googlecode.lanterna.screen.Screen)
+  (:import com.googlecode.lanterna.screen.Screen
+           com.googlecode.lanterna.terminal.Terminal)
   (:use [lanterna.common :only [parse-key]])
   (:require [lanterna.constants :as c]
             [lanterna.terminal :as t]))
   TODO: Add remove-resize-listener.
 
   "
-  [screen listener-fn]
+  [^Screen screen listener-fn]
   (t/add-resize-listener (.getTerminal screen)
                          listener-fn))
 
   :resize-listener - A function to call when the screen is resized.  This
                      function should take two parameters: the new number of
                      columns, and the new number of rows.
+  :font      - A string containing the name of the font to use.
+  :font-size - An int of the size of the font to use.
 
   NOTE: The options are really just a suggestion!
 
   This must be called before you do anything else to the screen.
 
   "
-  [screen]
+  [^Screen screen]
   (.startScreen screen))
 
 (defn stop
   TODO: Figure out if it's safe to start, stop, and then restart a screen.
 
   "
-  [screen]
+  [^Screen screen]
   (.stopScreen screen))
 
 
 
 (defn get-size
   "Return the current size of the screen as [cols rows]."
-  [screen]
+  [^Screen screen]
   (let [size (.getTerminalSize screen)
         cols (.getColumns size)
         rows (.getRows size)]
   need to call this for any of your changes to actually show up.
 
   "
-  [screen]
+  [^Screen screen]
   (.refresh screen))
 
 
   appears in a specific place.
 
   "
-  [screen x y]
+  [^Screen screen x y]
   (.setCursorPosition screen x y))
 
 (defn put-string
   (default #{})
 
   "
-  ([screen x y s] (put-string screen x y s {}))
-  ([screen x y s {:as opts
-                  :keys [fg bg styles]
-                  :or {fg :default
-                       bg :default
-                       styles #{}}}]
-   (let [styles (set (map c/styles styles))]
-     (.putString screen x y s
-                 (c/colors fg)
-                 (c/colors bg)
-                 styles))))
+  ([^Screen screen x y s] (put-string screen x y s {}))
+  ([^Screen screen x y ^String s {:as opts
+                                  :keys [fg bg styles]
+                                  :or {fg :default
+                                       bg :default
+                                       styles #{}}}]
+   (let [styles ^clojure.lang.PersistentHashSet (set (map c/styles styles))
+         x (int x)
+         y (int y)
+         fg ^com.googlecode.lanterna.terminal.Terminal$Color (c/colors fg)
+         bg ^com.googlecode.lanterna.terminal.Terminal$Color (c/colors bg)]
+     (.putString screen x y s fg bg styles))))
 
 (defn put-sheet
   "EXPERIMENTAL!  Turn back now!
   the screen to see the effect.
 
   "
-  [screen]
+  [^Screen screen]
   (.clear screen))
 
 
   want to wait for user input, use get-key-blocking instead.
 
   "
-  [screen]
+  [^Screen screen]
   (parse-key (.readInput screen)))
 
 (defn get-key-blocking
   TODO: Add a timeout option.
 
   "
-  [screen]
+  [^Screen screen]
   (let [k (get-key screen)]
     (if (nil? k)
       (do

src/lanterna/terminal.clj

 (ns lanterna.terminal
   (:import com.googlecode.lanterna.TerminalFacade
-           com.googlecode.lanterna.terminal.Terminal)
+           com.googlecode.lanterna.terminal.Terminal
+           com.googlecode.lanterna.terminal.swing.SwingTerminal
+           com.googlecode.lanterna.terminal.swing.TerminalAppearance
+           com.googlecode.lanterna.terminal.swing.TerminalPalette
+           java.awt.GraphicsEnvironment
+           java.awt.Font)
   (:use [lanterna.common :only [parse-key]])
   (:require [lanterna.constants :as c]))
 
 
+
 (defn add-resize-listener
   "Create a listener that will call the supplied fn when the terminal is resized.
 
   TODO: Add remove-resize-listener.
 
   "
-  [terminal listener-fn]
+  [^Terminal terminal listener-fn]
   (let [listener (reify com.googlecode.lanterna.terminal.Terminal$ResizeListener
                    (onResized [this newSize]
                      (listener-fn (.getColumns newSize)
     listener))
 
 
+(defn get-available-fonts []
+  (set (.getAvailableFontFamilyNames
+         (GraphicsEnvironment/getLocalGraphicsEnvironment))))
+
+(defn- get-font-name [font]
+  (let [fonts (if (coll? font) font [font])
+        fonts (concat fonts ["Monospaced"])
+        available (get-available-fonts)]
+    (first (filter available fonts))))
+
+
+(defn- get-swing-terminal [cols rows
+                           {:as opts
+                            :keys [font font-size palette]
+                            :or {font ["Menlo" "Consolas" "Monospaced"]
+                                 font-size 14
+                                 palette :mac-os-x}}]
+  (let [font (get-font-name font)
+        appearance (new TerminalAppearance
+                        (new Font font Font/PLAIN font-size)
+                        (new Font font Font/BOLD font-size)
+                        (c/palettes palette) true)]
+    (new SwingTerminal appearance cols rows)))
+
 (defn get-terminal
   "Get a terminal object.
 
   :resize-listener - A function to call when the terminal is resized.  This
                      function should take two parameters: the new number of
                      columns, and the new number of rows.
+  :font      - Font to use.  String or sequence of strings.
+               Use (lanterna.terminal/get-available-fonts) to see your options.
+               Will fall back to a basic monospaced font if none of the given
+               names are available.
+  :font-size - Font size (default 14).
+  :palette   - Color palette to use. Can be any of
+               (keys lanterna.constants/palettes) (default :mac-os-x).
 
   NOTE: The options are really just a suggestion!
 
-  The console terminal will ignore rows and columns and will be the size of the
-  user's window.
+  The console terminal will ignore rows and columns and fonts and colors.
 
   The Swing terminal will start out at this size but can be resized later by the
   user, and will ignore the charset entirely.
          charset (c/charsets charset)
          terminal (case kind
                     :auto   (TerminalFacade/createTerminal charset)
-                    :swing  (TerminalFacade/createSwingTerminal cols rows)
+                    :swing  (get-swing-terminal cols rows opts)
                     :text   (TerminalFacade/createTextTerminal in out charset)
                     :unix   (TerminalFacade/createUnixTerminal in out charset)
                     :cygwin (TerminalFacade/createCygwinTerminal in out charset))]
 
 (defn start
   "Start the terminal.  Consider using in-terminal instead."
-  [terminal]
+  [^Terminal terminal]
   (.enterPrivateMode terminal))
 
 (defn stop
   "Stop the terminal.  Consider using in-terminal instead."
-  [terminal]
+  [^Terminal terminal]
   (.exitPrivateMode terminal))
 
 
 
 (defn get-size
   "Return the current size of the terminal as [cols rows]."
-  [terminal]
+  [^Terminal terminal]
   (let [size (.getTerminalSize terminal)
         cols (.getColumns size)
         rows (.getRows size)]
 
 (defn move-cursor
   "Move the cursor to a specific location on the screen."
-  [terminal x y]
+  [^Terminal terminal x y]
   (.moveCursor terminal x y))
 
 (defn put-character
   output next to each other.
 
   "
-  ([terminal ch]
+  ([^Terminal terminal ch]
    (.putCharacter terminal ch))
-  ([terminal ch x y]
+  ([^Terminal terminal ch x y]
    (move-cursor terminal x y)
    (put-character terminal ch)))
 
   The cursor will end up at the position directly after the string.
 
   "
-  ([terminal s]
+  ([^Terminal terminal s]
    (dorun (map (partial put-character terminal)
                s)))
   ([terminal s x y]
   The cursor will be at 0 0 afterwards.
 
   "
-  [terminal]
+  [^Terminal terminal]
   (.clearScreen terminal)
   (move-cursor terminal 0 0))
 
 
-(defn set-fg-color [terminal color]
+(defn set-fg-color [^Terminal terminal color]
   (.applyForegroundColor terminal (c/colors color)))
 
-(defn set-bg-color [terminal color]
+(defn set-bg-color [^Terminal terminal color]
   (.applyBackgroundColor terminal (c/colors color)))
 
 
 ; TODO: Fix these.
 (defn set-style
   "Borked.  Don't use this."
-  [terminal style]
+  [^Terminal terminal style]
   (.applySGR terminal (c/enter-styles style)))
 
 (defn remove-style
   "Borked.  Don't use this."
-  [terminal style]
+  [^Terminal terminal style]
   (.applySGR terminal (c/exit-styles style)))
 
 (defn reset-styles
   "Borked.  Don't use this."
-  [terminal]
+  [^Terminal terminal]
   (.applySGR terminal c/reset-style))
 
 
   want to wait for user input, use get-key-blocking instead.
 
   "
-  [terminal]
+  [^Terminal terminal]
   (parse-key (.readInput terminal)))
 
 (defn get-key-blocking
   TODO: Add a timeout option.
 
   "
-  [terminal]
+  [^Terminal terminal]
   (let [k (get-key terminal)]
     (if (nil? k)
       (do
         (Thread/sleep 50)
         (recur terminal))
       k)))
+
+
+(comment
+
+  (def t (get-terminal :swing
+                       {:cols 40 :rows 30
+                        :font ["Menlo"]
+                        :font-size 24
+                        :palette :gnome}))
+  (start t)
+  (set-fg-color t :yellow)
+  (put-string t "Hello, world!")
+  (stop t)
+
+  )