<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 070new-stream.subx</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="none">
<meta name="settings" content="number_lines,use_css,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.subxComment { color: #005faf; }
.subxS2Comment { color: #8a8a8a; }
.LineNr { }
.subxS1Comment { color: #0000af; }
.subxFunction { color: #af5f00; text-decoration: underline; }
.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; }
.Constant { color: #008787; }
.subxTest { color: #5f8700; }
-->
</style>
<script type='text/javascript'>
<!--
/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
var lineNum;
lineNum = window.location.hash;
lineNum = lineNum.substr(1); /* strip off '#' */
if (lineNum.indexOf('L') == -1) {
lineNum = 'L'+lineNum;
}
var lineElem = document.getElementById(lineNum);
/* Always jump to new location even if the line was hidden inside a fold, or
* we corrected the raw number to a line ID.
*/
if (lineElem) {
lineElem.scrollIntoView(true);
}
return true;
}
if ('onhashchange' in window) {
window.onhashchange = JumpToLine;
}
-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/070new-stream.subx'>https://github.com/akkartik/mu/blob/master/070new-stream.subx</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="subxComment"># Helper to allocate a stream on the heap.</span>
<span id="L2" class="LineNr"> 2 </span>
<span id="L3" class="LineNr"> 3 </span>== code
<span id="L4" class="LineNr"> 4 </span><span class="subxComment"># instruction effective address register displacement immediate</span>
<span id="L5" class="LineNr"> 5 </span><span class="subxS1Comment"># . op subop mod rm32 base index scale r32</span>
<span id="L6" class="LineNr"> 6 </span><span class="subxS1Comment"># . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes</span>
<span id="L7" class="LineNr"> 7 </span>
<span id="L8" class="LineNr"> 8 </span><span class="subxFunction">new-stream</span>: <span class="subxComment"># ad : (address allocation-descriptor), length : int, elemsize : int -> address/eax</pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */# -*- coding: utf-8 -*-
# Copyright (C) 2009-2013 Roman Zimbelmann <hut@hut.pm>
# This software is distributed under the terms of the GNU GPL version 3.
"""The BrowserColumn widget displays the contents of a directory or file."""
import curses
import stat
from time import time
from . import Widget
from .pager import Pager
from ranger.ext.widestring import WideString
from ranger.gui.color import *
class BrowserColumn(Pager):
main_column = False
display_infostring = False
display_vcsstate = True
scroll_begin = 0
target = None
last_redraw_time = -1
ellipsis = { False: '~', True: '…' }
old_dir = None
old_thisfile = None
def __init__(self, win, level):
"""Initializes a Browser Column Widget
win = the curses window object of the BrowserView
level = what to display?
level >0 => previews
level 0 => current file/directory
level <0 => parent directories
"""
Pager.__init__(self, win)
Widget.__init__(self, win)
self.level = level
self.original_level = level
self.settings.signal_bind('setopt.display_size_in_main_column',
self.request_redraw, weak=True)
def request_redraw(self):
self.need_redraw = True
def resize(self, y, x, hei, wid):
Widget.resize(self, y, x, hei, wid)
def click(self, event):
"""Handle a MouseEvent"""
direction = event.mouse_wheel_direction()
if not (event.pressed(1) or event.pressed(3) or direction):
return False
if self.target is None:
pass
elif self.target.is_directory:
if self.target.accessible and self.target.content_loaded:
index = self.scroll_begin + event.y - self.y
if direction:
if self.level == -1:
self.fm.move_parent(direction)
else:
return False
elif event.pressed(1):
if not self.main_column:
self.fm.enter_dir(self.target.path)
if index < len(self.target):
self.fm.move(to=index)
elif event.pressed(3):
try:
clicked_file = self.target.files[index]
if clicked_file.is_directory:
self.fm.enter_dir(clicked_file.path)
elif self.level == 0:
self.fm.thisdir.move_to_obj(clicked_file)
self.fm.execute_file(clicked_file)
except:
pass
else:
if self.level > 0 and not direction:
self.fm.move(right=0)
return True
def execute_curses_batch(self, line, commands):
"""Executes a list of "commands" which can be easily cached.
"commands" is a list of lists. Each element contains
a text and an attribute. First, the attribute will be
set with attrset, then the text is printed.
Example:
execute_curses_batch(0, [["hello ", 0], ["world", curses.A_BOLD]])
"""
try:
self.win.move(line, 0)
except:
return
for entry in commands:
text, attr = entry
self.addstr(text, attr)
def has_preview(self):
if self.target is None:
return False
if self.target.is_file:
if not self.target.has_preview():
return False
if self.target.is_directory:
if self.level > 0 and not self.settings.preview_directories:
return False
return True
def level_shift(self, amount):
self.level = self.original_level + amount
def level_restore(self):
self.level = self.original_level
def poke(self):
Widget.poke(self)
self.target = self.fm.thistab.at_level(self.level)
def draw(self):
"""Call either _draw_file() or _draw_directory()"""
if self.target != self.old_dir:
self.need_redraw = True
self.old_dir = self.target
if self.target: # don't garbage collect this directory please
self.target.use()
if self.target and self.target.is_directory \
and (self.level <= 0 or self.settings.preview_directories):
if self.target.pointed_obj != self.old_thisfile:
self.need_redraw = True
self.old_thisfile = self.target.pointed_obj
if self.target.load_content_if_outdated() \
or self.target.sort_if_outdated() \
or self.last_redraw_time < self.target.last_update_time:
self.need_redraw = True
if self.need_redraw:
self.win.erase()
if self.target is None:
pass
elif self.target.is_file:
Pager.open(self)
self._draw_file()
elif self.target.is_directory:
self._draw_directory()
Widget.draw(self)
self.need_redraw = False
self.last_redraw_time = time()
def _draw_file(self):
"""Draw a preview of the file, if the settings allow it"""
self.win.move(0, 0)
if not self.target.accessible:
self.addnstr("not accessible", self.wid)
Pager.close(self)
return
if self.target is None or not self.target.has_preview():
Pager.close(self)
return
if self.fm.settings.preview_images and self.target.image:
self.set_image(self.target.realpath)
Pager.draw(self)
else:
f = self.target.get_preview_source(self.wid, self.hei)
if f is None:
Pager.close(self)
else:
if self.target.is_image_preview():
self.set_image(f)
else:
self.set_source(f)
Pager.draw(self)
def _draw_directory(self):
"""Draw the contents of a directory"""
if self.image:
self.image = None
self.need_clear_image = True
Pager.clear_image(self)
if self.level > 0 and not self.settings.preview_directories:
return
base_color = ['in_browser']
self.win.move(0, 0)
if not self.target.content_loaded:
self.color(tuple(base_color))
self.addnstr("...", self.wid)
self.color_reset()
return
if self.main_column:
base_color.append('main_column')
if not self.target.accessible:
self.color(tuple(base_color + ['error']))
self.addnstr("not accessible", self.wid)
self.color_reset()
return
if self.target.empty():
self.color(tuple(base_color + ['empty']))
self.addnstr("empty", self.wid)
self.color_reset()
return
self._set_scroll_begin()
copied = [f.path for f in self.fm.copy_buffer]
selected_i = self.target.pointer
for line in range(self.hei):
i = line + self.scroll_begin
if line > self.hei:
break
try:
drawn = self.target.files[i]
except IndexError:
break
tagged = self.fm.tags and drawn.realpath in self.fm.tags
if tagged:
tagged_marker = self.fm.tags.marker(drawn.realpath)
else:
tagged_marker = " "
# Extract linemode-related information from the drawn object
paperinfo = None
use_linemode = drawn._linemode
if use_linemode == "papertitle":
paperinfo = self.fm.metadata.get_metadata(drawn.path)
if not paperinfo.title:
use_linemode = "filename"
key = (self.wid, selected_i == i, drawn.marked, self.main_column,
drawn.path in copied, tagged_marker, drawn.infostring,
drawn.vcsfilestatus, drawn.vcsremotestatus, self.fm.do_cut,
use_linemode)
if key in drawn.display_data:
self.execute_curses_batch(line, drawn.display_data[key])
self.color_reset()
continue
# Deal with the line mode
if use_linemode == "papertitle":
if paperinfo.year:
text = "%s - %s" % (paperinfo.year, paperinfo.title)
else:
text = paperinfo.title
if use_linemode == "filename":
text = drawn.drawn_basename
elif use_linemode == "permissions":
text = "%s %s %s %s" % (drawn.get_permission_string(),
drawn.user, drawn.group, drawn.drawn_basename)
if drawn.marked and (self.main_column or \
self.settings.display_tags_in_all_columns):
text = " " + text
# Computing predisplay data. predisplay contains a list of lists
# [string, colorlst] where string is a piece of string to display,
# and colorlst a list of contexts that we later pass to the
# colorscheme, to compute the curses attribute.
predisplay_left = []
predisplay_right = []
space = self.wid
# selection mark
tagmark = self._draw_tagged_display(tagged, tagged_marker)
tagmarklen = self._total_len(tagmark)
if space - tagmarklen > 2:
predisplay_left += tagmark
space -= tagmarklen
# vcs data
vcsstring = self._draw_vcsstring_display(drawn)
vcsstringlen = self._total_len(vcsstring)
if space - vcsstringlen > 2:
predisplay_right += vcsstring
space -= vcsstringlen
# info string
infostring = []
infostringlen = 0
if use_linemode == "filename":
infostring = self._draw_infostring_display(drawn, space)
elif use_linemode == "papertitle":
if paperinfo and paperinfo.authors:
authorstring = paperinfo.authors
if ',' in authorstring:
authorstring = authorstring[0:authorstring.find(",")]
infostring.append([" " + authorstring + " ", ["infostring"]])
if infostring:
infostringlen = self._total_len(infostring)
if space - infostringlen > 2:
predisplay_right = infostring + predisplay_right
space -= infostringlen
textstring = self._draw_text_display(text, space)
textstringlen = self._total_len(textstring)
predisplay_left += textstring
space -= textstringlen
if space > 0:
predisplay_left.append([' ' * space, []])
elif space < 0:
raise Exception("Error: there is not enough space to write "
"the text. I have computed spaces wrong.")
# Computing display data. Now we compute the display_data list
# ready to display in curses. It is a list of lists [string, attr]
this_color = base_color + list(drawn.mimetype_tuple) + \
self._draw_directory_color(i, drawn, copied)
display_data = []
drawn.display_data[key] = display_data
predisplay = predisplay_left + predisplay_right
for txt, color in predisplay:
attr = self.settings.colorscheme.get_attr(*(this_color + color))
display_data.append([txt, attr])
self.execute_curses_batch(line, display_data)
self.color_reset()
def _total_len(self, predisplay):
return sum([len(WideString(s)) for s, L in predisplay])
def _draw_text_display(self, text, space):
wtext = WideString(text)
wellip = WideString(self.ellipsis[self.settings.unicode_ellipsis])
if len(wtext) > space:
wtext = wtext[:max(0, space - len(wellip))] + wellip
return [[str(wtext), []]]
def _draw_tagged_display(self, tagged, tagged_marker):
tagged_display = []
if (self.main_column or self.settings.display_tags_in_all_columns) \
and self.wid > 2:
if tagged:
tagged_display.append([tagged_marker, ['tag_marker']])
else:
tagged_display.append([" ", ['tag_marker']])
return tagged_display
def _draw_infostring_display(self, drawn, space):
infostring_display = []
if self.display_infostring and drawn.infostring \
and self.settings.display_size_in_main_column:
infostring = str(drawn.infostring) + " "
if len(infostring) <= space:
infostring_display.append([infostring, ['infostring']])
return infostring_display
def _draw_vcsstring_display(self, drawn):
vcsstring_display = []
if self.settings.vcs_aware and (drawn.vcsfilestatus or \
drawn.vcsremotestatus):
if drawn.vcsfilestatus:
vcsstr, vcscol = self.vcsfilestatus_symb[drawn.vcsfilestatus]
else:
vcsstr = " "
vcscol = []
vcsstring_display.append([vcsstr, ['vcsfile'] + vcscol])
if drawn.vcsremotestatus:
vcsstr, vcscol = self.vcsremotestatus_symb[
drawn.vcsremotestatus]
else:
vcsstr = " "
vcscol = []
vcsstring_display.append([vcsstr, ['vcsremote'] + vcscol])
elif self.target.has_vcschild:
vcsstring_display.append([" ", []])
return vcsstring_display
def _draw_directory_color(self, i, drawn, copied):
this_color = []
if i == self.target.pointer:
this_color.append('selected')
if drawn.marked:
this_color.append('marked')
if self.fm.tags and drawn.realpath in self.fm.tags:
this_color.append('tagged')
if drawn.is_directory:
this_color.append('directory')
else:
this_color.append('file')
if drawn.stat:
mode = drawn.stat.st_mode
if mode & stat.S_IXUSR:
this_color.append('executable')
if stat.S_ISFIFO(mode):
this_color.append('fifo')
if stat.S_ISSOCK(mode):
this_color.append('socket')
if drawn.is_device:
this_color.append('device')
if drawn.path in copied:
this_color.append('cut' if self.fm.do_cut else 'copied')
if drawn.is_link:
this_color.append('link')
this_color.append(drawn.exists and 'good' or 'bad')
return this_color
def _get_scroll_begin(self):
"""Determines scroll_begin (the position of the first displayed file)"""
offset = self.settings.scroll_offset
dirsize = len(self.target)
winsize = self.hei
halfwinsize = winsize // 2
index = self.target.pointer or 0
original = self.target.scroll_begin
projected = index - original
upper_limit = winsize - 1 - offset
lower_limit = offset
if original < 0:
return 0
if dirsize < winsize:
return 0
if halfwinsize < offset:
return min( dirsize - winsize, max( 0, index - halfwinsize ))
if original > dirsize - winsize:
self.target.scroll_begin = dirsize - winsize
return self._get_scroll_begin()
if projected < upper_limit and projected > lower_limit:
return original
if projected > upper_limit:
return min( dirsize - winsize,
original + (projected - upper_limit))
if projected < upper_limit:
return max( 0,
original - (lower_limit - projected))
return original
def _set_scroll_begin(self):
"""Updates the scroll_begin value"""
self.scroll_begin = self._get_scroll_begin()
self.target.scroll_begin = self.scroll_begin
def scroll(self, n):
"""scroll down by n lines"""
self.need_redraw = True
self.target.move(down=n)
self.target.scroll_begin += 3 * n
def __str__(self):
return self.__class__.__name__ + ' at level ' + str(self.level)