1
0
Fork 0
mirror of synced 2024-11-30 04:35:35 -05:00

add vim-minimap

This commit is contained in:
huhuaishun 2016-10-05 20:17:49 +08:00 committed by Huaishun Hu
parent 7762fafeb7
commit 54f1c0f3d0
26 changed files with 1742 additions and 1 deletions

View file

@ -1,5 +1,5 @@
if has("mac") || has("macunix") if has("mac") || has("macunix")
set gfn=Hack:h24,Source\ Code\ Pro:h24,Menlo:h24 set gfn=Hack:h16,Source\ Code\ Pro:h16,Menlo:h16
elseif has("win16") || has("win32") elseif has("win16") || has("win32")
set gfn=Hack:h18,Source\ Code\ Pro:h16,Bitstream\ Vera\ Sans\ Mono:h15 set gfn=Hack:h18,Source\ Code\ Pro:h16,Bitstream\ Vera\ Sans\ Mono:h15
elseif has("gui_gtk2") elseif has("gui_gtk2")
@ -37,6 +37,9 @@ set softtabstop=2
set cmdheight=1 set cmdheight=1
set number set number
" yank to the system register (*) by default
set clipboard=unnamed
" Mark, highlight multiple words " Mark, highlight multiple words
source ~/.vim_runtime/sources_non_forked/Mark/plugin/mark.vim source ~/.vim_runtime/sources_non_forked/Mark/plugin/mark.vim
let g:mwDefaultHighlightingPalette = 'maximum' let g:mwDefaultHighlightingPalette = 'maximum'

View file

@ -0,0 +1 @@
*.pyc

View file

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2016 Séverin Lemaignan and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,83 @@
A code minimap for Vim
======================
The Sublime text-editor can display an useful overview of the code as a
*minimap* sidebar.
We can implement the same thing in Vim, relying on the [Drawille
library](https://github.com/asciimoo/drawille) to 'draw' in text mode.
![minimap in action](http://picdrop.t3lab.com/qqpdtsbTow.gif)
This code is made available under a MIT license. See [LICENSE](LICENSE) for
details.
Features
--------
- displays the minimap of the currently active buffer (and updates when
switching to a different buffer)
- synchronized scrolling
- live update while typing
Installation
------------
Note that this extension requires Vim with Python support.
### Vundle
With [vundle](https://github.com/gmarik/Vundle.vim), simply add: `Plugin
'severin-lemaignan/vim-minimap'` to your `.vimrc` and run `:PluginInstall` from
vim.
### Janus
With Janus just clone inside ```.janus```.
```
cd ~/.janus
git clone https://github.com/severin-lemaignan/vim-minimap.git vim-minimap
```
Usage
-----
`:Minimap` to show the minimap, `:MinimapClose` to hide it.
Default mappings: `<Leader>mm` to display the minimap, `<Leader>mc` to close it.
To overwrite the default keybindings, using following settings in ``.vimrc'':
```
let g:minimap_show='<leader>ms'
let g:minimap_update='<leader>mu'
let g:minimap_close='<leader>gc'
let g:minimap_toggle='<leader>gt'
```
Settings
--------
You can customize the color of the highlighting by setting `g:minimap_highlight` in your vimrc:
`let g:minimap_highlight='Visual'`
Note: To find out which highlights are available on your vim installation use :hi to get the list.
Troubleshooting
---------------
- Weird display
Certain fonts do not display plain dots and empty spaces, but
plain dots and circles for braille characters. As a result, you may want to use
any other font that display braille characters in a way that suit the minimap
plugin, like `Ubuntu Mono`, or `Droid Sans Mono`.
For example, with `Inconsolata`:
![image](https://cloud.githubusercontent.com/assets/7250745/8083430/c48e5c44-0f84-11e5-9cba-20d7e2eac0c5.png)
With `Ubuntu Mono`
![image](https://cloud.githubusercontent.com/assets/7250745/8083436/d4aaf9d4-0f84-11e5-9383-cb02bba384bc.png)

View file

@ -0,0 +1,131 @@
DRAWILLE
========
Drawing in terminal with Unicode [Braille][] characters
[Braille]: http://en.wikipedia.org/wiki/Braille
[![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=asciimoo&url=https://github.com/asciimoo/drawille&title=drawille&language=&tags=github&category=software)
![Drawille](docs/images/drawille_01.png)
![Drawille](docs/images/xkcd.png)
![Drawille](docs/images/sine_tracking.gif)
![Drawille](docs/images/rotating_cube.gif)
### USAGE
```python
from __future__ import print_function
from drawille import Canvas
from math import sin, radians
c = Canvas()
for x in range(0, 1800, 10):
c.set(x / 10, 10 + sin(radians(x)) * 10)
print(c.frame())
```
![Usage](docs/images/usage.png)
```python
from drawille import Turtle
t = Turtle()
for _ in range(36):
t.right(10)
for _ in range(36):
t.right(10)
t.forward(8)
print(t.frame())
```
![Turtle](docs/images/turtle.png)
### Installation
To install drawille, simply:
```bash
$ pip install drawille
```
or
```bash
$ easy_install drawille
```
### Bugs
Bugs or suggestions? Visit the [issue tracker](https://github.com/asciimoo/drawille/issues).
Tested fonts
| Font | Works |
| ----- | ----- |
| Fixed | Yes |
Tested terminals
| Terminal | Works |
| ------------ | ----- |
| rxvt-unicode | Yes |
### LICENSE
```
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>
```
### Other implementations / similar projects
* [https://github.com/madbence/node-drawille](https://github.com/madbence/node-drawille) (nodejs)
* [https://github.com/exrook/drawille-go](https://github.com/exrook/drawille-go) (go)
* [https://github.com/maerch/ruby-drawille](https://github.com/maerch/ruby-drawille) (ruby)
* [https://github.com/sunetos/TextPlots.jl](https://github.com/sunetos/TextPlots.jl) (julia)
* [https://github.com/mkremins/drawille-clj](https://github.com/mkremins/drawille-clj) (clojure)
* [https://github.com/mydzor/bash-drawille](https://github.com/mydzor/bash-drawille) (bash)
* [https://github.com/hoelzro/term-drawille](https://github.com/hoelzro/term-drawille) (perl 5)
* [https://github.com/whatthejeff/php-drawille](https://github.com/whatthejeff/php-drawille) (PHP)
* [https://github.com/yamadapc/haskell-drawille](https://github.com/yamadapc/haskell-drawille) (haskell)
* [https://github.com/P1start/drawille-rs](https://github.com/P1start/drawille-rs) (rust)
* [https://github.com/liam-middlebrook/drawille-sharp](https://github.com/liam-middlebrook/drawille-sharp) (C#)
* [https://github.com/asciimoo/lua-drawille](https://github.com/asciimoo/lua-drawille) (Lua)
### Further reading
* [HackerNews](https://news.ycombinator.com/item?id=7776112)
* [Reddit](http://www.reddit.com/r/programming/comments/263opn/drawille_pixel_graphics_in_a_terminal_using/)
* [ohloh](http://www.ohloh.net/p/drawille)
* [xkcd comics in Braille using drawille](http://blog.yjl.im/2014/04/xkcd-comics-in-braille-using-drawille.html)
* [Braille unicode pixelation](http://blog.jverkamp.com/2014/05/30/braille-unicode-pixelation/)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View 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)

View file

@ -0,0 +1,39 @@
from __future__ import print_function
from drawille import Canvas
import math
s = Canvas()
for x in range(1800):
s.set(x/10, math.sin(math.radians(x)) * 10)
print(s.frame())
s.clear()
for x in range(0, 1800, 10):
s.set(x/10, 10 + math.sin(math.radians(x)) * 10)
s.set(x/10, 10 + math.cos(math.radians(x)) * 10)
print(s.frame())
s.clear()
for x in range(0, 3600, 20):
s.set(x/20, 4 + math.sin(math.radians(x)) * 4)
print(s.frame())
s.clear()
for x in range(0, 360, 4):
s.set(x/4, 30 + math.sin(math.radians(x)) * 30)
for x in range(30):
for y in range(30):
s.set(x,y)
s.toggle(x+30, y+30)
s.toggle(x+60, y)
print(s.frame())

View file

@ -0,0 +1,207 @@
# -*- coding: utf-8 -*-
import curses
from drawille import Canvas, line
from time import sleep
from thread import start_new_thread
from Queue import Queue
import locale
from random import randint
locale.setlocale(locale.LC_ALL,"")
stdscr = curses.initscr()
stdscr.refresh()
keys = Queue()
speed = 0.0
fps = 20
frame_no = 0
score = 0
delta = frame_no / fps
height = 100
width = 100
position = height / 2
bird_map = [
#1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
[0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,0], #1
[0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0], #2
[0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0], #3
[0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,1,0,0,0], #4
[0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,1,0,0], #5
[0,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,0,1,0,0], #6
[1,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0], #7
[1,0,0,0,0,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,0], #8
[1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1], #9
[1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,1,0], #0
[0,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0], #1
[0,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0], #2
[0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0], #3
]
bird = []
for y, row in enumerate(bird_map):
for x,col in enumerate(row):
if col:
bird.append((x, y))
def read_keys(stdscr):
while 1:
c = stdscr.getch()
keys.put(c)
class Bar():
def __init__(self, bar_width, cap_height=4, space=3*13):
self.height = randint(cap_height+space+1, height-1-cap_height)
self.width = bar_width
self.cap_height = cap_height
self.x = width - bar_width - 1
self.space = space
def draw(self):
for x,y in line(self.x,
self.height,
self.x+self.width,
self.height):
yield x, y
for x,y in line(self.x,
self.height,
self.x,
self.height+self.cap_height):
yield x, y
for x,y in line(self.x+self.width,
self.height,
x+self.width,
self.height+self.cap_height):
yield x, y
for x,y in line(self.x,
self.height+self.cap_height,
self.x+2,
self.height+self.cap_height):
yield x, y
for x,y in line(self.x+self.width-2,
self.height+self.cap_height,
self.x+self.width,
self.height+self.cap_height):
yield x, y
for x,y in line(self.x+2,
self.height+self.cap_height,
self.x+2,
height):
yield x, y
for x,y in line(self.x+self.width-2,
self.height+self.cap_height,
self.x+self.width-2,
height):
yield x, y
for x,y in line(self.x,
self.height-self.space,
self.x+self.width,
self.height-self.space):
yield x, y
for x,y in line(self.x,
self.height-self.space,
self.x,
self.height-self.cap_height-self.space):
yield x, y
for x,y in line(self.x+self.width,
self.height-self.space,
x+self.width,
self.height-self.cap_height-self.space):
yield x, y
for x,y in line(self.x,
self.height-self.cap_height-self.space,
self.x+2,
self.height-self.cap_height-self.space):
yield x, y
for x,y in line(self.x+self.width-2,
self.height-self.cap_height-self.space,
self.x+self.width,
self.height-self.cap_height-self.space):
yield x, y
for x,y in line(self.x+2,
self.height-self.cap_height-self.space,
self.x+2,
0):
yield x, y
for x,y in line(self.x+self.width-2,
self.height-self.cap_height-self.space,
self.x+self.width-2,
0):
yield x, y
def check_collision(bird_pos, bar):
# TODO more efficient collision detection
if bar.x > 21:
return False
if bar.height <= bird_pos-13 and bar.height+bar.space > bird_pos:
return False
for bar_x, bar_y in bar.draw():
for bird_x, bird_y in bird:
if int(bird_x) == int(bar_x) and int(bird_y+bird_pos) == int(bar_y):
return True
return False
def main(stdscr):
global frame_no, speed, position, score
c = Canvas()
bar_width = 16
bars = [Bar(bar_width)]
stdscr.refresh()
while True:
frame_no += 1
for bar in bars:
if check_collision(position, bar):
return
while not keys.empty():
if keys.get() == 113:
return
speed = 32.0
c.set(0,0)
c.set(width, height)
if frame_no % 50 == 0:
bars.append(Bar(bar_width))
for x,y in bird:
c.set(x,y+position)
for bar_index, bar in enumerate(bars):
if bar.x < 1:
bars.pop(bar_index)
score += 1
else:
bars[bar_index].x -= 1
for x,y in bar.draw():
c.set(x,y)
f = c.frame()+'\n'
stdscr.addstr(0, 0, f)
stdscr.addstr(height/4+1, 0, 'score: {0}'.format(score))
stdscr.refresh()
c.clear()
speed -= 2
position -= speed/10
if position < 0:
position = 0
speed = 0.0
elif position > height-13:
position = height-13
speed = 0.0
sleep(1.0/fps)
if __name__ == '__main__':
start_new_thread(read_keys, (stdscr,))
curses.wrapper(main)
print('Final score: {0}'.format(score))

View file

@ -0,0 +1,121 @@
# example:
# $ PYTHONPATH=`pwd` python examples/image2term.py http://fc00.deviantart.net/fs71/f/2011/310/5/a/giant_nyan_cat_by_daieny-d4fc8u1.png -t 100 -r 0.01
try:
from PIL import Image
except:
from sys import stderr
stderr.write('[E] PIL not installed\n')
exit(1)
from drawille import Canvas
from StringIO import StringIO
import urllib2
def getTerminalSize():
import os
env = os.environ
def ioctl_GWINSZ(fd):
import fcntl
import termios
import struct
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
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 image2term(image, threshold=128, ratio=None, invert=False):
if image.startswith('http://') or image.startswith('https://'):
i = Image.open(StringIO(urllib2.urlopen(image).read())).convert('L')
else:
i = Image.open(open(image)).convert('L')
w, h = i.size
if ratio:
w = int(w * ratio)
h = int(h * ratio)
i = i.resize((w, h), Image.ANTIALIAS)
else:
tw = getTerminalSize()[0]
tw *= 2
if tw < w:
ratio = tw / float(w)
w = tw
h = int(h * ratio)
i = i.resize((w, h), Image.ANTIALIAS)
can = Canvas()
x = y = 0
try:
i_converted = i.tobytes()
except AttributeError:
i_converted = i.tostring()
for pix in i_converted:
if invert:
if ord(pix) > threshold:
can.set(x, y)
else:
if ord(pix) < threshold:
can.set(x, y)
x += 1
if x >= w:
y += 1
x = 0
return can.frame(0, 0)
def argparser():
import argparse
from sys import stdout
argp = argparse.ArgumentParser(description='drawille - image to terminal example script')
argp.add_argument('-o', '--output'
,help = 'Output file - default is STDOUT'
,metavar = 'FILE'
,default = stdout
,type = argparse.FileType('w')
)
argp.add_argument('-r', '--ratio'
,help = 'Image resize ratio'
,default = None
,action = 'store'
,type = float
,metavar = 'N'
)
argp.add_argument('-t', '--threshold'
,help = 'Color threshold'
,default = 128
,action = 'store'
,type = int
,metavar = 'N'
)
argp.add_argument('-i', '--invert'
,help = 'Invert colors'
,default = False
,action = 'store_true'
)
argp.add_argument('image'
,metavar = 'FILE'
,help = 'Image file path/url'
)
return vars(argp.parse_args())
def __main__():
args = argparser()
args['output'].write(image2term(args['image'], args['threshold'], args['ratio'], args['invert']))
args['output'].write('\n')
if __name__ == '__main__':
__main__()

View file

@ -0,0 +1,108 @@
from drawille import Canvas, line
import curses
import math
from time import sleep
import locale
locale.setlocale(locale.LC_ALL,"")
stdscr = curses.initscr()
stdscr.refresh()
class Point3D:
def __init__(self, x = 0, y = 0, z = 0):
self.x, self.y, self.z = float(x), float(y), float(z)
def rotateX(self, angle):
""" Rotates the point around the X axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
y = self.y * cosa - self.z * sina
z = self.y * sina + self.z * cosa
return Point3D(self.x, y, z)
def rotateY(self, angle):
""" Rotates the point around the Y axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
z = self.z * cosa - self.x * sina
x = self.z * sina + self.x * cosa
return Point3D(x, self.y, z)
def rotateZ(self, angle):
""" Rotates the point around the Z axis by the given angle in degrees. """
rad = angle * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
x = self.x * cosa - self.y * sina
y = self.x * sina + self.y * cosa
return Point3D(x, y, self.z)
def project(self, win_width, win_height, fov, viewer_distance):
""" Transforms this 3D point to 2D using a perspective projection. """
factor = fov / (viewer_distance + self.z)
x = self.x * factor + win_width / 2
y = -self.y * factor + win_height / 2
return Point3D(x, y, 1)
vertices = [
Point3D(-20,20,-20),
Point3D(20,20,-20),
Point3D(20,-20,-20),
Point3D(-20,-20,-20),
Point3D(-20,20,20),
Point3D(20,20,20),
Point3D(20,-20,20),
Point3D(-20,-20,20)
]
# Define the vertices that compose each of the 6 faces. These numbers are
# indices to the vertices list defined above.
faces = [(0,1,2,3),(1,5,6,2),(5,4,7,6),(4,0,3,7),(0,4,5,1),(3,2,6,7)]
def __main__(stdscr, projection=False):
angleX, angleY, angleZ = 0, 0, 0
c = Canvas()
while 1:
# Will hold transformed vertices.
t = []
for v in vertices:
# Rotate the point around X axis, then around Y axis, and finally around Z axis.
p = v.rotateX(angleX).rotateY(angleY).rotateZ(angleZ)
if projection:
# Transform the point from 3D to 2D
p = p.project(50, 50, 50, 50)
#Put the point in the list of transformed vertices
t.append(p)
for f in faces:
for x,y in line(t[f[0]].x, t[f[0]].y, t[f[1]].x, t[f[1]].y):
c.set(x,y)
for x,y in line(t[f[1]].x, t[f[1]].y, t[f[2]].x, t[f[2]].y):
c.set(x,y)
for x,y in line(t[f[2]].x, t[f[2]].y, t[f[3]].x, t[f[3]].y):
c.set(x,y)
for x,y in line(t[f[3]].x, t[f[3]].y, t[f[0]].x, t[f[0]].y):
c.set(x,y)
f = c.frame(-40, -40, 80, 80)
stdscr.addstr(0, 0, '{0}\n'.format(f))
stdscr.refresh()
angleX += 2
angleY += 3
angleZ += 5
sleep(1.0/20)
c.clear()
if __name__ == '__main__':
from sys import argv
projection = False
if '-p' in argv:
projection = True
curses.wrapper(__main__, projection)

View file

@ -0,0 +1,28 @@
from __future__ import print_function
from drawille import Canvas, line, animate
import math
def __main__():
i = 0
height = 40
while True:
frame = []
frame.extend([coords for coords in
line(0,
height,
180,
math.sin(math.radians(i)) * height + height)])
frame.extend([(x/2, height + math.sin(math.radians(x+i)) * height)
for x in range(0, 360, 2)])
yield frame
i += 2
if __name__ == '__main__':
animate(Canvas(), __main__, 1./60)

View file

@ -0,0 +1,24 @@
from drawille import Canvas
from timeit import timeit
c = Canvas()
frames = 1000 * 10
sizes = ((0, 0),
(10, 10),
(20, 20),
(20, 40),
(40, 20),
(40, 40),
(100, 100))
for x, y in sizes:
c.set(0, 0)
for i in range(y):
c.set(x, i)
r = timeit(c.frame, number=frames)
print('{0}x{1}\t{2}'.format(x, y, r))
c.clear()

View file

@ -0,0 +1,11 @@
from drawille import Turtle
t = Turtle()
for _ in range(36):
t.right(10)
for _ in range(36):
t.right(10)
t.forward(8)
print(t.frame())

View file

@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
from sys import argv
try:
from PIL import Image
except:
from sys import stderr
stderr.write('[E] PIL not installed')
exit(1)
from StringIO import StringIO
import urllib2
import re
from drawille import Canvas
def getTerminalSize():
import os
env = os.environ
def ioctl_GWINSZ(fd):
import fcntl
import termios
import struct
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
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 usage():
print('Usage: %s <url/id>')
exit()
if __name__ == '__main__':
if len(argv) < 2:
url = 'http://xkcd.com/'
elif argv[1] in ['-h', '--help']:
usage()
elif argv[1].startswith('http'):
url = argv[1]
else:
url = 'http://xkcd.com/%s/' % argv[1]
c = urllib2.urlopen(url).read()
img_url = re.findall('http:\/\/imgs.xkcd.com\/comics\/[^"\']+', c)[0]
i = Image.open(StringIO(urllib2.urlopen(img_url).read())).convert('L')
w, h = i.size
tw, th = getTerminalSize()
tw *= 2
th *= 2
if tw < w:
ratio = tw / float(w)
w = tw
h = int(h * ratio)
i = i.resize((w, h), Image.ANTIALIAS)
can = Canvas()
x = y = 0
try:
i_converted = i.tobytes()
except AttributeError:
i_converted = i.tostring()
for pix in i_converted:
if ord(pix) < 128:
can.set(x, y)
x += 1
if x >= w:
y += 1
x = 0
print(can.frame())

View file

@ -0,0 +1,34 @@
from setuptools import setup, find_packages
setup(
name = 'drawille',
version = '0.0.4',
author = 'Adam Tauber',
author_email = 'asciimoo@gmail.com',
description = ('Drawing in terminal with unicode braille characters'),
license = 'AGPLv3+',
keywords = "terminal braille drawing canvas console",
url = 'https://github.com/asciimoo/drawille',
scripts = [],
py_modules = ['drawille'],
packages = find_packages(),
install_requires = [],
download_url = 'https://github.com/asciimoo/drawille/tarball/master',
# TODO
#entry_points={
# "console_scripts": ["drawille=drawille:__main__"]
#},
classifiers = [
"Development Status :: 4 - Beta",
"Topic :: Utilities",
'Environment :: Console',
'License :: OSI Approved :: GNU Affero General Public License v3',
'Intended Audience :: Developers',
'Natural Language :: English',
'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
],
)

View file

@ -0,0 +1,130 @@
# -*- coding: utf-8 -*-
from drawille import Canvas, line, Turtle
from unittest import TestCase, main
class CanvasTestCase(TestCase):
def test_set(self):
c = Canvas()
c.set(0, 0)
self.assertTrue(0 in c.chars and 0 in c.chars[0])
def test_unset_empty(self):
c = Canvas()
c.set(1, 1)
c.unset(1, 1)
self.assertEqual(len(c.chars), 0)
def test_unset_nonempty(self):
c = Canvas()
c.set(0, 0)
c.set(0, 1)
c.unset(0, 1)
self.assertEqual(c.chars[0][0], 1)
def test_clear(self):
c = Canvas()
c.set(1, 1)
c.clear()
self.assertEqual(c.chars, dict())
def test_toggle(self):
c = Canvas()
c.toggle(0, 0)
self.assertEqual(c.chars, {0: {0: 1}})
c.toggle(0, 0)
self.assertEqual(c.chars, dict())
def test_set_text(self):
c = Canvas()
c.set_text(0, 0, "asdf")
self.assertEqual(c.frame(), "asdf")
def test_frame(self):
c = Canvas()
self.assertEqual(c.frame(), '')
c.set(0, 0)
self.assertEqual(c.frame(), '')
def test_max_min_limits(self):
c = Canvas()
c.set(0, 0)
self.assertEqual(c.frame(min_x=2), '')
self.assertEqual(c.frame(max_x=0), '')
def test_get(self):
c = Canvas()
self.assertEqual(c.get(0, 0), False)
c.set(0, 0)
self.assertEqual(c.get(0, 0), True)
self.assertEqual(c.get(0, 1), False)
self.assertEqual(c.get(1, 0), False)
self.assertEqual(c.get(1, 1), False)
class LineTestCase(TestCase):
def test_single_pixel(self):
self.assertEqual(list(line(0, 0, 0, 0)), [(0, 0)])
def test_row(self):
self.assertEqual(list(line(0, 0, 1, 0)), [(0, 0), (1, 0)])
def test_column(self):
self.assertEqual(list(line(0, 0, 0, 1)), [(0, 0), (0, 1)])
def test_diagonal(self):
self.assertEqual(list(line(0, 0, 1, 1)), [(0, 0), (1, 1)])
class TurtleTestCase(TestCase):
def test_position(self):
t = Turtle()
self.assertEqual(t.pos_x, 0)
self.assertEqual(t.pos_y, 0)
t.move(1, 1)
self.assertEqual(t.pos_x, 1)
self.assertEqual(t.pos_y, 1)
def test_rotation(self):
t = Turtle()
self.assertEqual(t.rotation, 0)
t.right(30)
self.assertEqual(t.rotation, 30)
t.left(30)
self.assertEqual(t.rotation, 0)
def test_brush(self):
t = Turtle()
self.assertFalse(t.get(t.pos_x, t.pos_y))
t.forward(1)
self.assertTrue(t.get(0, 0))
self.assertTrue(t.get(t.pos_x, t.pos_y))
t.up()
t.move(2, 0)
self.assertFalse(t.get(t.pos_x, t.pos_y))
t.down()
t.move(3, 0)
self.assertTrue(t.get(t.pos_x, t.pos_y))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,214 @@
# -* coding: utf-8 -*-
# vim-minimap 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.
#
# vim-minimap 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 vim-minimap. If not, see < http://www.gnu.org/licenses/ >.
#
# (C) 2014- by Séverin Lemaignan for the VIM integration, <severin@guakamole.org>
# (C) 2014- by Adam Tauber for the Drawille part, <asciimoo@gmail.com>
import os
import sys
PY3 = sys.version_info[0] == 3
import vim
# Add the library to the Python path.
for p in vim.eval("&runtimepath").split(','):
plugin_dir = os.path.join(p, "autoload", "drawille")
if os.path.exists(plugin_dir):
if plugin_dir not in sys.path:
sys.path.append(plugin_dir)
break
from drawille import *
WIDTH = 20
MINIMAP = "vim-minimap"
def getmmwindow():
for b in vim.buffers:
if b.name.endswith(MINIMAP):
for w in vim.windows:
if w.buffer == b:
return w
return None
def getmainwindow():
for b in vim.buffers:
if not b.name.endswith(MINIMAP) and not "NERD_tree" in b.name:
for w in vim.windows:
if w.buffer == b:
return w
return None
def setmmautocmd(clear = False):
vim.command(":augroup minimap_group")
vim.command(":autocmd!")
if not clear:
# Properly close the minimap when quitting VIM (ie, when minimap is the last remaining window
vim.command(":autocmd WinEnter <buffer> if winnr('$') == 1|q|endif")
vim.command(':autocmd CursorMoved,CursorMovedI,TextChanged,TextChangedI,BufWinEnter * MinimapUpdate')
vim.command(":augroup END")
def toggleminimap():
minimap = getmmwindow()
if minimap:
closeminimap()
else:
showminimap()
def showminimap():
minimap = getmmwindow()
# If the minimap window does not yet exist, create it
if not minimap:
# Save the currently active window to restore it later
src = vim.current.window
vim.command(":botright vnew %s" % MINIMAP)
# make the new buffer 'temporary'
vim.command(":setlocal buftype=nofile bufhidden=wipe noswapfile nobuflisted")
# make ensure our buffer is uncluttered
vim.command(":setlocal nonumber norelativenumber nolist")
# set all autocmds in a group
setmmautocmd()
minimap = vim.current.window
minimap.width = WIDTH
# fixed size
vim.command(":set wfw")
# Restore the active window
vim.current.window = src
vim.command(":call minimap#UpdateMinimap()")
def updateminimap():
minimap = getmmwindow()
src = vim.current.window
HORIZ_SCALE = 0.2
if not hasattr(src, 'buffer'):
return
# Ignore NERD_tree Buffers
# TODO make configurable
if "NERD_tree" in src.buffer.name:
return
if minimap and src.buffer == minimap.buffer:
mainwindow = getmainwindow()
if mainwindow is None:
return
if src.buffer != mainwindow.buffer:
position_in_minimap = src.cursor[0]
ratio = float(len(minimap.buffer)) / float(len(mainwindow.buffer))
new_position = int(float(position_in_minimap) / ratio)
if new_position > len(mainwindow.buffer):
new_position = len(mainwindow.buffer)
mainwindow.cursor = (new_position, 0) # move to top left
vim.current.window = mainwindow
updateminimap()
if minimap and src.buffer != minimap.buffer:
mode = vim.eval("mode()")
cursor = src.cursor
vim.command("normal! H")
topline = src.cursor[0]
vim.command("normal! L")
bottomline = src.cursor[0]
def draw(lengths,indents, startline=0):
c = Canvas()
for y, l in enumerate(lengths):
indent = int(indents[y] * HORIZ_SCALE)
for x in range(2 * min(int(l * HORIZ_SCALE), WIDTH)):
if(x>=indent):
c.set(x, y)
# pad with spaces to ensure uniform block highlighting
if PY3:
return [line.ljust(WIDTH, u'\u00A0') for line in c.rows()]
else:
return [unicode(line).ljust(WIDTH, u'\u00A0') for line in c.rows()]
if minimap:
vim.current.window = minimap
highlight_group = vim.eval("g:minimap_highlight")
lengths = []
indents = []
for line in range(len(src.buffer)):
linestring = src.buffer[line]
indents.append(len(linestring) - len(linestring.lstrip()))
lengths.append(len(linestring))
vim.command(":setlocal modifiable")
minimap.buffer[:] = draw(lengths,indents)
# Highlight the current visible zone
top = int(topline / 4)
bottom = int(bottomline / 4 + 1)
vim.command("match {0} /\\%>0v\\%<{1}v\\%>{2}l\\%<{3}l./".format(
highlight_group, WIDTH + 1, top, bottom))
# center the highlighted zone
height = int(vim.eval("winheight(0)"))
# first, put the cursor at the top of the buffer
vim.command("normal! gg")
# then, jump so that the active zone is centered
if (top + (bottom - top) / 2) > height / 2:
jump = min(top + (bottom - top) / 2 + height / 2, len(minimap.buffer))
vim.command("normal! %dgg" % jump)
# prevent any further modification
vim.command(":setlocal nomodifiable")
vim.current.window = src
# restore the current selection if we were in visual mode.
if mode in ('v', 'V', '\026'):
vim.command("normal! gv")
src.cursor = cursor
def closeminimap():
minimap = getmmwindow()
src = vim.current.window
if minimap:
vim.current.window = minimap
# clear the minimap autocmds
setmmautocmd(True)
vim.command(":quit!")
# try the last window, but sometimes this one was already closed
# (ex. tagbar toggle) which will lead to an exception
try:
vim.current.window = src
except:
vim.current.window = vim.windows[0]

View file

@ -0,0 +1,62 @@
" vim-minimap 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.
"
" vim-minimap 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 vim-minimap. If not, see < http://www.gnu.org/licenses/ >.
"
" (C) 2014- by Séverin Lemaignan for the VIM integration, <severin@guakamole.org>
" (C) 2014- by Adam Tauber for the Drawille part, <asciimoo@gmail.com>
if has('python') || has('python3')
" By default Highlight the current screen as a visual selection.
if !exists('g:minimap_highlight')
let g:minimap_highlight = 'Visual'
endif
let python_module = fnameescape(globpath(&runtimepath, 'autoload/minimap.py'))
if has('python')
exe 'pyfile ' . python_module
elseif has('python3')
exe 'py3file ' . python_module
endif
end
function! minimap#ShowMinimap()
if has('python')
python showminimap()
elseif has('python3')
python3 showminimap()
endif
endfunction
function! minimap#UpdateMinimap()
if has('python')
python updateminimap()
elseif has('python3')
python3 updateminimap()
endif
endfunction
function! minimap#CloseMinimap()
if has('python')
python closeminimap()
elseif has('python3')
python3 closeminimap()
endif
endfunction
function! minimap#ToggleMinimap()
if has('python')
python toggleminimap()
elseif has('python3')
python3 toggleminimap()
endif
endfunction

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

View file

@ -0,0 +1,28 @@
if exists('loaded_minimap')
finish
endif
let loaded_minimap = 1
command! MinimapToggle call minimap#ToggleMinimap()
command! Minimap call minimap#ShowMinimap()
command! MinimapClose call minimap#CloseMinimap()
command! MinimapUpdate call minimap#UpdateMinimap()
let g:minimap_show =
\ get( g:, 'minimap_show', '<leader>mm' )
let g:minimap_update =
\ get( g:, 'minimap_update', '<leader>mu' )
let g:minimap_close =
\ get( g:, 'minimap_close', '<leader>mc' )
let g:minimap_toggle =
\ get( g:, 'minimap_toggle', '<leader>mt' )
execute "nnoremap " . " <silent> " .
\ g:minimap_show . " :Minimap<CR>"
execute "nnoremap " . " <silent> " .
\ g:minimap_update . " :MinimapUpdate<CR>"
execute "nnoremap " . " <silent> " .
\ g:minimap_close . " :MinimapClose<CR>"
execute "nnoremap " . " <silent> " .
\ g:minimap_toggle . " :MinimapToggle<CR>"