markup support.
- [X] history: Make it possible to search through history. Maybe Alt-p only shows
lines containing current content.
-- [ ] emacs: Num-C-l doesn't work if it would require part of a wrapped line
+- [X] emacs: Num-C-l doesn't work if it would require part of a wrapped line
off top of screen
- [ ] emacs: :C-q to recognise names of Unicode chars: e.g. WASTEBASKET
Possibly matches a list which continued :C-q cycles through
Core features
-------------
+- [ ] Send global notify before/after refresh. LOG must suspend
+ logging (or notifications at least) during refresh if is visible
+ anywhere
- [ ] Do I want "Display" as in "Display:close", or "window" as in
"window:notify". Decide, and make everything consistent.
- [ ] Do I really need global-multicall- or can I just use
### emacs
-- [ ] Num-C-l doesn't work if it would require part of a wrapped line
+- [X] Num-C-l doesn't work if it would require part of a wrapped line
off top of screen
- [ ] :C-q to recognise names of Unicode chars: e.g. WASTEBASKET
Possibly matches a list which continued :C-q cycles through
### git-mode
-- [ ] log view which uses --max-count and --skip to only collect enough
- log entries to fill the display
+- [ ] log view (:C-c l?) which uses --max-count and --skip to only
+ collect enough log entries to fill the display. Or better: have a
+ shell mode which only reads from pipe if insertion position is
+ visible.
+- [ ] from log-view, view a commit. From a commit, view the file
+ at that time. Maybe 'save' creates a fixup commit which is
+ added to the log.
+- [ ] Have a list of paths are top of log and any commit which doesn't
+ touch the paths is greyed out. "git log --oneline --stat"
+ provides the info, some of which we hide.
+- [ ] when a git-managed file is saved, if there is a "diff" view, it is
+ updated. Maybe show both cached and uncached in different colours.
- [ ] action from log-view to reword and commit - with auto rebase and
update of the view
- [ ] actions to re-arrange and deleted the commits. Integrate with
- git-rebase.
-- [ ] git-commit command which presents the patch and allows it to be
- edited (with consistency checks and number updates). On :Commit
- the patch is applied with "git apply --cached" an if successful
- the message is added with "| git commit -F"
+ git-rebase... or simulate git-rebase with "git worktree add
+ --no-checkout" on the most recent unchanged commit, then adding
+ each required commit with git-apply--cached and git-commit
+- [ ] diff-mode editing enhancements:
+ - kill the file marker (+++) kills all chunks in the file
+ - kill the chunk marker (@@) kills the whole chunk
+ - insert line in chunk gets '+' prefix and updates line counts
+ - delete line in chunk updates line counts
+ - editing in chunk re-runs word-diff
+- [ ] git-commit command (:Commit) which presents the patch and allows
+ it to be edited (with consistency checks and number updates). On
+ :Commit the patch is applied with "git apply --cached" an if
+ successful the message is added with "| git commit -F"
### lang-python
- [ ] c-mode to use tabs or spaces for indent
- [ ] c-mode: use only spaces for bracket-alignment, or tabs as well
- [ ] shell command regex to choose parsing: diff, git-log, grep/make
+- [ ] shift width for auto and manual left/right display shift
+- [ ] tab width ??
- [ ] colours of whitespace: tab, at-eol, tab-after-space, past-col ....
- [ ] whitespace max-col (per-line??)
then the loop header and the if condition would be displayed if at all
possible.
-### git-mode
-
-Git adds an extra dimension to editing code - the dimension of history.
-Somethings that the editor can help with:
-
-- creating a commit, including writing the comment message and selection
- which files, or which lines in which files, should be added to the commit.
-- browsing history - a bit like gitk. So from a 'git log --oneline', open
- a view on a patch, or on a file at the time of the commit. This might
- only fetch 100 lines - or only since origin/master, and fetch more
- only when it is accessed. Including rebase functionality here would
- be cool.
-- editing history - using "git rebase --interactive" or similar.
- The editor could open either a file or a diff at the time of a commit
- and allow them to be editing. For smaller changes, editing the diff
- directly would be nice. In either case, having one auto-update when the
- other is edited would be cool
-- editing just the comments of recent commits is useful.
-- Showing a current 'diff' which is dynamically updated and which distinguishes
- between staged and unstaged changes - and lets them be toggled - would be
- part of this.
-
-A view on "git log" would only show the first page until you scroll down. Then
-more would be requested and displayed. So we don't generate thousands of commits
-unless that are actually wanted. i.e. "git log --max-count=100 --skip=N"
-This could collect but hide the commit message, and allow them to be seen later.
-The commit-ids could be marked edit, reword, etc and then rebase run.
-Would be useful to limit to certain files.
-
-
### a “reflection” document so I can view the internal data structures.
When developing a new pane things go wrong, but it is hard to see what.
short *y_prep safe, short *y_postp safe,
short *lines_above safe, short *lines_below safe,
int found_start, int found_end,
- int line_height_pre, int line_height_post)
+ int line_height_pre, int line_height_post,
+ bool line_at_a_time)
{
int y_pre = *y_prep;
int y_post = *y_postp;
int above, below;
if (consume > p->h - y)
consume = p->h - y;
+ if (line_at_a_time && consume > 2*line_height_pre &&
+ line_height_pre > 0)
+ consume = 2*line_height_pre;
+ if (line_at_a_time && consume > 2*line_height_post &&
+ line_height_post > 0)
+ consume = 2*line_height_post;
if (y_pre > y_post) {
above = consume - (consume/2);
below = consume/2;
int consume = p->h - y;
if (consume > y_pre)
consume = y_pre;
+ if (line_at_a_time && consume > line_height_pre &&
+ line_height_pre > 0)
+ consume = line_height_pre;
y_pre -= consume;
y += consume;
*lines_above += consume / (line_height_pre?:1);
int consume = p->h - y;
if (consume > y_post)
consume = y_post;
+ if (line_at_a_time && consume > line_height_post &&
+ line_height_post > 0)
+ consume = line_height_post;
y_post -= consume;
y += consume;
*lines_below += consume / (line_height_post?:1);
*
* If we decide to stop moving in both directions, but have not
* reached EOF or full height of display, keep moving downwards.
+ *
+ * "start" is a mark at the start of the first line we currently
+ * intend to display, and y_pre is the number of pixel from the top
+ * of the display of that line, to the top pixel that will be displayed.
+ * We only move 'start' backward when y_pre is zero, and initially y_pre
+ * is the full height of that line.
+ *
+ * Similarly "end" is the start of the last line we currently intend
+ * to display, and y_post is the number of pixel from the bottom of that display
+ * up to the point we currently intend to display. We only move "end" forward
+ * when y_post is zero, and when we do we set y_post to the full height of the
+ * line.
+ *
+ * Until we decide on the start or end (found_start, found_end), we
+ * repeatedly add equal parts of y_pre and y_post into the total to
+ * be display - consume_space() does this. The space removed from y_pre
+ * and y_post is added to 'y' - the total height.
+ * It is also included into lines_above and lines_below which count text lines,
+ * rather than pixels, using line_height_pre and line_height_post as scale
+ * factors. These are used to determine when vline or rl->margin requirements
+ * have been met.
*/
static void find_lines(struct mark *pm safe, struct pane *p safe,
struct pane *focus safe,
int vline)
{
struct rl_data *rl = p->data;
+ /* orig_top/bot bound what is currently displayed and
+ * are used to determine if the display has been repositioned.
+ * orig_bot is *after* the last displayed line. Its ->mdata
+ * will be NULL.
+ */
struct mark *orig_top, *orig_bot;
- struct mark *top, *bot; // boundary of previous display
+ /* top and bot are used to enhance stability. They are NULL
+ * if vline is given, else they match orig_top/bot.
+ */
+ struct mark *top, *bot;
struct mark *m;
+ /* Current estimate of new display. From y_pre pixels down
+ * from the top of line at 'start', to y_post pixels up
+ * from the end of the line before 'end' there are 'y'
+ * pixel lines that we have committed to display.
+ */
struct mark *start, *end; // current estimate for new display
+ short y_pre = 0, y_post = 0;
short y = 0;
+ /* Number of text-lines in the committed region above or below
+ * the baseline of the line containing pm. These lines might not
+ * all be the same height. line_height_pre/post are the heights of
+ * start and end-1 so changes in y_pre/y_post can be merged into these
+ * counts.
+ */
short lines_above = 0, lines_below = 0; /* distance from start/end
* to pm.
*/
- short offset; // pos of pm in rendering of that line
- bool found_start = False, found_end = False;
- /* y_pre and y_post are measurement from start/end that
- * haven't yet been included into lines_above/lines_below.
- */
- short y_pre = 0, y_post = 0;
short line_height_pre = 1, line_height_post = 1;
+ short offset; // pos of pm while measureing the line holding the cursor.
+ /* We set found_start we we don't want to consider anything above the
+ * top that we currently intend to display. Once it is set,
+ * 'start', y_pre, lines_above are all frozen.
+ * Similarly once found_end is set we freeze end, y_pos, lines_below,
+ * but we mught unfreeze those if there is room for more text at end of
+ * display.
+ * found_start is set:
+ * - when y_pre is zero and start is at top of file
+ * - when lines_above reaches positive vline
+ * - when intended display has grown down into the previous
+ * display. This means we have added enough lines above and
+ * don't want to scroll the display more than we need.
+ * - When we hit unexpected errors moving backwards
+ * found_end is set:
+ * - when we hit end-of-file
+ * - when lines_below reached -vline
+ * - when the top of the intended display overlaps the
+ * previous display.
+ */
+ bool found_start = False, found_end = False;
+
orig_top = vmark_first(focus, rl->typenum, p);
orig_bot = vmark_last(focus, rl->typenum, p);
/* Protect top/bot from being freed by call_render_line */
start = vmark_new(focus, rl->typenum, p);
if (!start)
goto abort;
+ /* FIXME why is this here. We set ->repositioned at the end
+ * if the marks move. Maybe we need to check if y_pre moves too.
+ */
rl->repositioned = 1;
mark_to_mark(start, pm);
start = call_render_line_prev(focus, start, 0, &rl->top_sol);
if (!start)
goto abort;
+
+ /* Render the cursor line, and find where the cursor is. */
offset = call_render_line_to_point(focus, pm, start);
call_render_line(p, focus, start, NULL);
end = vmark_next(start);
if (!rl->shift_locked)
rl->shift_left = 0;
- /* ->cy is top of cursor, we want to measure from bottom */
if (start->mdata) {
struct pane *hp = start->mdata;
int curs_width;
curs_width = pane_attr_get_int(
start->mdata, "curs_width", 1);
- while (!rl->do_wrap && !rl->shift_locked && curs_width > 0 &&
+ if (curs_width < 0)
+ curs_width = 1;
+ while (!rl->do_wrap && !rl->shift_locked &&
hp->cx + curs_width >= p->w) {
int shift = 8 * curs_width;
if (shift > hp->cx)
rl->shift_left += shift;
measure_line(p, focus, start, offset);
}
+ /* ->cy is top of cursor, we want to measure from bottom */
line_height_pre = attr_find_int(start->mdata->attrs, "line-height");
if (line_height_pre < 1)
line_height_pre = 1;
y_post = 0;
}
if (!end) {
+ /* When cursor at EOF, leave 10% height of display
+ * blank at bottom to make this more obvious - unless
+ * the display is so small that might push the last line partly
+ * off display at the top.
+ */
if (p->h > line_height_pre * 2)
y_post += p->h / 10;
else {
y = rl->header->mdata->h;
/* We have start/end of the focus line. When rendered this,
- * plus header and eof-footed would use y_pre + y + y_post
+ * plus header and eof-footer would use y_pre + y + y_post
* vertical space.
*/
y = consume_space(p, y, &y_pre, &y_post,
&lines_above, &lines_below,
found_start, found_end,
- line_height_pre, line_height_post);
+ line_height_pre, line_height_post,
+ vline && vline != NO_NUMERIC);
}
/* We might need to continue downwards even after found_end
* if there is more space.
y = consume_space(p, y, &y_pre, &y_post,
&lines_above, &lines_below,
found_start, found_end,
- line_height_pre, line_height_post);
+ line_height_pre, line_height_post,
+ vline && vline != NO_NUMERIC);
}
if (start->mdata && start->mdata->h <= y_pre) {