mirror of
https://github.com/amix/vimrc
synced 2025-07-08 09:35:00 +08:00
add vim-minimap
This commit is contained in:
417
sources_non_forked/vim-minimap/autoload/drawille/drawille.py
Normal file
417
sources_non_forked/vim-minimap/autoload/drawille/drawille.py
Normal file
@ -0,0 +1,417 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# drawille is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# drawille is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with drawille. If not, see < http://www.gnu.org/licenses/ >.
|
||||
#
|
||||
# (C) 2014- by Adam Tauber, <asciimoo@gmail.com>
|
||||
|
||||
import math
|
||||
import os
|
||||
from sys import version_info
|
||||
from collections import defaultdict
|
||||
from time import sleep
|
||||
import curses
|
||||
|
||||
IS_PY3 = version_info[0] == 3
|
||||
|
||||
if IS_PY3:
|
||||
unichr = chr
|
||||
|
||||
"""
|
||||
|
||||
http://www.alanwood.net/unicode/braille_patterns.html
|
||||
|
||||
dots:
|
||||
,___,
|
||||
|1 4|
|
||||
|2 5|
|
||||
|3 6|
|
||||
|7 8|
|
||||
`````
|
||||
"""
|
||||
|
||||
pixel_map = ((0x01, 0x08),
|
||||
(0x02, 0x10),
|
||||
(0x04, 0x20),
|
||||
(0x40, 0x80))
|
||||
|
||||
# braille unicode characters starts at 0x2800
|
||||
braille_char_offset = 0x2800
|
||||
|
||||
|
||||
# http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python
|
||||
def getTerminalSize():
|
||||
"""Returns terminal width, height
|
||||
"""
|
||||
env = os.environ
|
||||
|
||||
def ioctl_GWINSZ(fd):
|
||||
try:
|
||||
import fcntl, termios, struct
|
||||
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
|
||||
except:
|
||||
return
|
||||
return cr
|
||||
|
||||
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
||||
|
||||
if not cr:
|
||||
try:
|
||||
fd = os.open(os.ctermid(), os.O_RDONLY)
|
||||
cr = ioctl_GWINSZ(fd)
|
||||
os.close(fd)
|
||||
except:
|
||||
pass
|
||||
|
||||
if not cr:
|
||||
cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
|
||||
|
||||
return int(cr[1]), int(cr[0])
|
||||
|
||||
|
||||
def normalize(coord):
|
||||
coord_type = type(coord)
|
||||
|
||||
if coord_type == int:
|
||||
return coord
|
||||
elif coord_type == float:
|
||||
return int(round(coord))
|
||||
else:
|
||||
raise TypeError("Unsupported coordinate type <{0}>".format(type(coord)))
|
||||
|
||||
|
||||
def intdefaultdict():
|
||||
return defaultdict(int)
|
||||
|
||||
|
||||
def get_pos(x, y):
|
||||
"""Convert x, y to cols, rows"""
|
||||
return normalize(x) // 2, normalize(y) // 4
|
||||
|
||||
|
||||
class Canvas(object):
|
||||
"""This class implements the pixel surface."""
|
||||
|
||||
def __init__(self, line_ending=os.linesep):
|
||||
super(Canvas, self).__init__()
|
||||
self.clear()
|
||||
self.line_ending = line_ending
|
||||
|
||||
|
||||
def clear(self):
|
||||
"""Remove all pixels from the :class:`Canvas` object."""
|
||||
self.chars = defaultdict(intdefaultdict)
|
||||
|
||||
|
||||
def set(self, x, y):
|
||||
"""Set a pixel of the :class:`Canvas` object.
|
||||
|
||||
:param x: x coordinate of the pixel
|
||||
:param y: y coordinate of the pixel
|
||||
"""
|
||||
x = normalize(x)
|
||||
y = normalize(y)
|
||||
col, row = get_pos(x, y)
|
||||
|
||||
if type(self.chars[row][col]) != int:
|
||||
return
|
||||
|
||||
self.chars[row][col] |= pixel_map[y % 4][x % 2]
|
||||
|
||||
|
||||
def unset(self, x, y):
|
||||
"""Unset a pixel of the :class:`Canvas` object.
|
||||
|
||||
:param x: x coordinate of the pixel
|
||||
:param y: y coordinate of the pixel
|
||||
"""
|
||||
x = normalize(x)
|
||||
y = normalize(y)
|
||||
col, row = get_pos(x, y)
|
||||
|
||||
if type(self.chars[row][col]) == int:
|
||||
self.chars[row][col] &= ~pixel_map[y % 4][x % 2]
|
||||
|
||||
if type(self.chars[row][col]) != int or self.chars[row][col] == 0:
|
||||
del(self.chars[row][col])
|
||||
|
||||
if not self.chars.get(row):
|
||||
del(self.chars[row])
|
||||
|
||||
|
||||
def toggle(self, x, y):
|
||||
"""Toggle a pixel of the :class:`Canvas` object.
|
||||
|
||||
:param x: x coordinate of the pixel
|
||||
:param y: y coordinate of the pixel
|
||||
"""
|
||||
x = normalize(x)
|
||||
y = normalize(y)
|
||||
col, row = get_pos(x, y)
|
||||
|
||||
if type(self.chars[row][col]) != int or self.chars[row][col] & pixel_map[y % 4][x % 2]:
|
||||
self.unset(x, y)
|
||||
else:
|
||||
self.set(x, y)
|
||||
|
||||
|
||||
def set_text(self, x, y, text):
|
||||
"""Set text to the given coords.
|
||||
|
||||
:param x: x coordinate of the text start position
|
||||
:param y: y coordinate of the text start position
|
||||
"""
|
||||
col, row = get_pos(x, y)
|
||||
|
||||
for i,c in enumerate(text):
|
||||
self.chars[row][col+i] = c
|
||||
|
||||
|
||||
def get(self, x, y):
|
||||
"""Get the state of a pixel. Returns bool.
|
||||
|
||||
:param x: x coordinate of the pixel
|
||||
:param y: y coordinate of the pixel
|
||||
"""
|
||||
x = normalize(x)
|
||||
y = normalize(y)
|
||||
dot_index = pixel_map[y % 4][x % 2]
|
||||
col, row = get_pos(x, y)
|
||||
char = self.chars.get(row, {}).get(col)
|
||||
|
||||
if not char:
|
||||
return False
|
||||
|
||||
if type(char) != int:
|
||||
return True
|
||||
|
||||
return bool(char & dot_index)
|
||||
|
||||
|
||||
def rows(self, min_x=None, min_y=None, max_x=None, max_y=None):
|
||||
"""Returns a list of the current :class:`Canvas` object lines.
|
||||
|
||||
:param min_x: (optional) minimum x coordinate of the canvas
|
||||
:param min_y: (optional) minimum y coordinate of the canvas
|
||||
:param max_x: (optional) maximum x coordinate of the canvas
|
||||
:param max_y: (optional) maximum y coordinate of the canvas
|
||||
"""
|
||||
|
||||
if not self.chars.keys():
|
||||
return []
|
||||
|
||||
minrow = min_y // 4 if min_y != None else min(self.chars.keys())
|
||||
maxrow = (max_y - 1) // 4 if max_y != None else max(self.chars.keys())
|
||||
mincol = min_x // 2 if min_x != None else min(min(x.keys()) for x in self.chars.values())
|
||||
maxcol = (max_x - 1) // 2 if max_x != None else max(max(x.keys()) for x in self.chars.values())
|
||||
ret = []
|
||||
|
||||
for rownum in range(minrow, maxrow+1):
|
||||
if not rownum in self.chars:
|
||||
ret.append('')
|
||||
continue
|
||||
|
||||
maxcol = (max_x - 1) // 2 if max_x != None else max(self.chars[rownum].keys())
|
||||
row = []
|
||||
|
||||
for x in range(mincol, maxcol+1):
|
||||
char = self.chars[rownum].get(x)
|
||||
|
||||
if not char:
|
||||
row.append(' ')
|
||||
elif type(char) != int:
|
||||
row.append(char)
|
||||
else:
|
||||
row.append(unichr(braille_char_offset+char))
|
||||
|
||||
ret.append(''.join(row))
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def frame(self, min_x=None, min_y=None, max_x=None, max_y=None):
|
||||
"""String representation of the current :class:`Canvas` object pixels.
|
||||
|
||||
:param min_x: (optional) minimum x coordinate of the canvas
|
||||
:param min_y: (optional) minimum y coordinate of the canvas
|
||||
:param max_x: (optional) maximum x coordinate of the canvas
|
||||
:param max_y: (optional) maximum y coordinate of the canvas
|
||||
"""
|
||||
ret = self.line_ending.join(self.rows(min_x, min_y, max_x, max_y))
|
||||
|
||||
if IS_PY3:
|
||||
return ret
|
||||
|
||||
return ret.encode('utf-8')
|
||||
|
||||
|
||||
def line(x1, y1, x2, y2):
|
||||
"""Returns the coords of the line between (x1, y1), (x2, y2)
|
||||
|
||||
:param x1: x coordinate of the startpoint
|
||||
:param y1: y coordinate of the startpoint
|
||||
:param x2: x coordinate of the endpoint
|
||||
:param y2: y coordinate of the endpoint
|
||||
"""
|
||||
|
||||
x1 = normalize(x1)
|
||||
y1 = normalize(y1)
|
||||
x2 = normalize(x2)
|
||||
y2 = normalize(y2)
|
||||
|
||||
xdiff = max(x1, x2) - min(x1, x2)
|
||||
ydiff = max(y1, y2) - min(y1, y2)
|
||||
xdir = 1 if x1 <= x2 else -1
|
||||
ydir = 1 if y1 <= y2 else -1
|
||||
|
||||
r = max(xdiff, ydiff)
|
||||
|
||||
for i in range(r+1):
|
||||
x = x1
|
||||
y = y1
|
||||
|
||||
if ydiff:
|
||||
y += (float(i) * ydiff) / r * ydir
|
||||
if xdiff:
|
||||
x += (float(i) * xdiff) / r * xdir
|
||||
|
||||
yield (x, y)
|
||||
|
||||
|
||||
def polygon(center_x=0, center_y=0, sides=4, radius=4):
|
||||
degree = float(360) / sides
|
||||
|
||||
for n in range(sides):
|
||||
a = n * degree
|
||||
b = (n + 1) * degree
|
||||
x1 = (center_x + math.cos(math.radians(a))) * (radius + 1) / 2
|
||||
y1 = (center_y + math.sin(math.radians(a))) * (radius + 1) / 2
|
||||
x2 = (center_x + math.cos(math.radians(b))) * (radius + 1) / 2
|
||||
y2 = (center_y + math.sin(math.radians(b))) * (radius + 1) / 2
|
||||
|
||||
for x, y in line(x1, y1, x2, y2):
|
||||
yield x, y
|
||||
|
||||
|
||||
class Turtle(Canvas):
|
||||
"""Turtle graphics interface
|
||||
http://en.wikipedia.org/wiki/Turtle_graphics
|
||||
"""
|
||||
|
||||
def __init__(self, pos_x=0, pos_y=0):
|
||||
self.pos_x = pos_x
|
||||
self.pos_y = pos_y
|
||||
self.rotation = 0
|
||||
self.brush_on = True
|
||||
super(Turtle, self).__init__()
|
||||
|
||||
|
||||
def up(self):
|
||||
"""Pull the brush up."""
|
||||
self.brush_on = False
|
||||
|
||||
|
||||
def down(self):
|
||||
"""Push the brush down."""
|
||||
self.brush_on = True
|
||||
|
||||
|
||||
def forward(self, step):
|
||||
"""Move the turtle forward.
|
||||
|
||||
:param step: Integer. Distance to move forward.
|
||||
"""
|
||||
x = self.pos_x + math.cos(math.radians(self.rotation)) * step
|
||||
y = self.pos_y + math.sin(math.radians(self.rotation)) * step
|
||||
prev_brush_state = self.brush_on
|
||||
self.brush_on = True
|
||||
self.move(x, y)
|
||||
self.brush_on = prev_brush_state
|
||||
|
||||
|
||||
def move(self, x, y):
|
||||
"""Move the turtle to a coordinate.
|
||||
|
||||
:param x: x coordinate
|
||||
:param y: y coordinate
|
||||
"""
|
||||
if self.brush_on:
|
||||
for lx, ly in line(self.pos_x, self.pos_y, x, y):
|
||||
self.set(lx, ly)
|
||||
|
||||
self.pos_x = x
|
||||
self.pos_y = y
|
||||
|
||||
|
||||
def right(self, angle):
|
||||
"""Rotate the turtle (positive direction).
|
||||
|
||||
:param angle: Integer. Rotation angle in degrees.
|
||||
"""
|
||||
self.rotation += angle
|
||||
|
||||
|
||||
def left(self, angle):
|
||||
"""Rotate the turtle (negative direction).
|
||||
|
||||
:param angle: Integer. Rotation angle in degrees.
|
||||
"""
|
||||
self.rotation -= angle
|
||||
|
||||
|
||||
def back(self, step):
|
||||
"""Move the turtle backwards.
|
||||
|
||||
:param step: Integer. Distance to move backwards.
|
||||
"""
|
||||
self.forward(-step)
|
||||
|
||||
|
||||
# aliases
|
||||
pu = up
|
||||
pd = down
|
||||
fd = forward
|
||||
mv = move
|
||||
rt = right
|
||||
lt = left
|
||||
bk = back
|
||||
|
||||
|
||||
def animate(canvas, fn, delay=1./24, *args, **kwargs):
|
||||
"""Animation automatition function
|
||||
|
||||
:param canvas: :class:`Canvas` object
|
||||
:param fn: Callable. Frame coord generator
|
||||
:param delay: Float. Delay between frames.
|
||||
:param *args, **kwargs: optional fn parameters
|
||||
"""
|
||||
|
||||
# python2 unicode curses fix
|
||||
if not IS_PY3:
|
||||
import locale
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
|
||||
def animation(stdscr):
|
||||
|
||||
for frame in fn(*args, **kwargs):
|
||||
for x,y in frame:
|
||||
canvas.set(x,y)
|
||||
|
||||
f = canvas.frame()
|
||||
stdscr.addstr(0, 0, '{0}\n'.format(f))
|
||||
stdscr.refresh()
|
||||
if delay:
|
||||
sleep(delay)
|
||||
canvas.clear()
|
||||
|
||||
curses.wrapper(animation)
|
Reference in New Issue
Block a user