Current section

Files

Jump to
pane lib viewer.ex
Raw

lib/viewer.ex

defmodule Pane.Viewer do
@moduledoc false
defstruct pages: [], total_pages: 0, index: 0
use GenServer
@doc ~S"""
Starts a `Pane.Viewer` with given opts.
## Examples
iex> {:ok, pid} = Pane.Viewer.start_link(data: "test")
iex> is_pid(pid)
true
"""
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
def stop, do: GenServer.stop(__MODULE__)
@doc ~S"""
Returns a `Pane.Viewer` struct with given opts.
## Examples
iex> Pane.Viewer.init(data: "test")
{:ok, %Pane.Viewer{
index: 0,
total_pages: 1,
pages: [
%Pane.Page{
data: "test",
index: 0
}
]
}}
"""
def init(opts) do
pages = opts[:data] |> Pane.Page.paginate(max_lines() - 2)
state = %__MODULE__{
index: 0,
total_pages: Enum.count(pages),
pages: pages
}
{:ok, state}
end
def first_page, do: GenServer.call(__MODULE__, :first_page)
def last_page, do: GenServer.call(__MODULE__, :last_page)
def next_page, do: GenServer.call(__MODULE__, :next_page)
def prev_page, do: GenServer.call(__MODULE__, :prev_page)
def current_page, do: GenServer.call(__MODULE__, :current_page)
def prompt, do: GenServer.call(__MODULE__, :prompt)
def handle_call(:first_page, _from, state) do
state = %{state | index: 0}
current = current_page(state)
IO.puts(current.data)
{:reply, current, state}
end
def handle_call(:last_page, _from, state) do
state = %{state | index: last_page_index(state)}
current = current_page(state)
IO.puts(current.data)
{:reply, current, state}
end
def handle_call(:next_page, _from, state) do
state = inc_page(state)
current = current_page(state)
IO.puts(current.data)
{:reply, current, state}
end
def handle_call(:prev_page, _from, state) do
state = dec_page(state)
current = current_page(state)
IO.puts(current.data)
{:reply, current, state}
end
def handle_call(:current_page, _from, state) do
{:reply, current_page(state), state}
end
def handle_call(:prompt, _from, state), do: {:reply, prompt(state), state}
def current_page(state), do: Enum.at(state.pages, state.index)
def last_page_index(state), do: Enum.count(state.pages) - 1
def inc_page(%{index: i, total_pages: total} = state) when i < total - 1 do
%{state | index: state.index + 1}
end
def inc_page(state), do: state
def dec_page(%{index: i} = state) when i > 0 do
%{state | index: i - 1}
end
def dec_page(state), do: state
def page_description(state) do
"#{state.index + 1} of #{last_page_index(state) + 1}"
end
def prompt(state) do
"[#{page_description(state)}] (j)next (k)prev (f)first (l)last (q)quit "
end
def max_lines do
case System.cmd("tput", ["lines"]) do
{count, 0} -> count |> String.trim() |> String.to_integer()
end
end
end