Merge branch 'nadrad:main' into main

This commit is contained in:
CPM/VX 2022-09-16 23:15:01 +02:00 committed by GitHub
commit 891f6f45b7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 174 additions and 107 deletions

252
h-m-m
View file

@ -19,6 +19,7 @@ $mm['question_color'] = "\033[38;5;168m";
$mm['changes'] = [];
$mm['change_active_node'] = [];
$mm['change_index'] = 0;
$mm['change_max_steps'] = 24;
mb_regex_encoding("UTF-8");
mb_internal_encoding("UTF-8");
@ -49,6 +50,8 @@ function load_settings(&$mm)
case 'line_spacing': $mm['line_spacing'] = max( round($value), 0 ); break;
case 'initial_depth': $mm['initial_depth'] = max( round($value), 1 ); break;
case 'undo_steps': $mm['change_max_steps'] = max( round($value), 0 ); break;
case 'active_node_color': $mm['active_node_color'] = $value; break;
case 'message_color': $mm['message_color'] = $value; break;
@ -125,12 +128,16 @@ const insert_child = 1;
const ctrl_p = "\020";
const ctrl_c = "\003";
const ctrl_r = "\022";
const ctrl_f = "\006";
const ctrl_v = "\026";
const arr_down = "\033\133\102";
const arr_right = "\033\133\103";
const arr_up = "\033\133\101";
const arr_left = "\033\133\104";
const del = "\033\133\063\176";
const reset_page = "\033[2J\033[0;0f";
const reset_color = "\033[0m";
@ -315,11 +322,16 @@ function decode_tree($lines, $root_id, $start_id)
foreach ($lines as $lid=>$line)
{
$lines[$lid] =
str_replace
mb_ereg_replace
(
[ "\t", "\n", "\r", BOM ]
,[ " ", " ", " ", "" ]
,$lines[$lid]
"[\000-\010\013-\037\177".BOM."]"
,''
,str_replace
(
[ "\t", "\n", "\r" ]
,[ " ", " ", " " ]
,$lines[$lid]
)
)
;
@ -1015,7 +1027,6 @@ function push_node_down(&$mm, $id)
if ($id==0) return;
push_change($mm);
$mm['modified'] = true;
if (isset($mm['nodes'][$id+1]))
@ -1052,6 +1063,7 @@ function insert_node(&$mm, $type)
if ($mm['active_node']==$mm['root'])
$type=insert_child;
push_change($mm);
$mm['modified'] = true;
if ($type==insert_sibling)
@ -1099,46 +1111,10 @@ function insert_node(&$mm, $type)
// }}}
// {{{ edit node
// {{{ magic readline!
function show_line(&$mm, $title, $cursor, $shift)
function magic_readline(&$mm, $title)
{
$output = mb_substr($title,$shift,$mm['terminal_width']-1);
$output .= str_repeat( ' ' ,$mm['terminal_width'] - mb_strlen($output) );
// showing the cursor
$output =
mb_substr
(
$output
,0
,$cursor-$shift-1
)
.invert_on
.mb_substr
(
$output
,$cursor-$shift-1
,1
)
.invert_off
.mb_substr
(
$output
,$cursor-$shift
);
put(0,$mm['terminal_height'],$mm['active_node_color'].$output);
}
function edit_node(&$mm, $rewrite = false)
{
push_change($mm);
$title = $rewrite ? '' : $mm['nodes'][ $mm['active_node'] ]['title'];
if ($mm['active_node']==0 && $title=='root') $title='';
$in = '';
$cursor = mb_strlen($title)+1;
$shift = max( 0, $cursor - $mm['terminal_width'] );
@ -1147,8 +1123,12 @@ function edit_node(&$mm, $rewrite = false)
while(true)
{
usleep(10000);
$in = fread(STDIN, 9);
usleep(5000);
$in = fread(STDIN, 66666);
// normally, the longest sequence we have is 13 bytes,
// but if ctrl+shift+v is used, the whole text will be passed!
// In other words, we don't receive a ctrl+shift+v input,
// but the actual content. Was that a confusing behavior? Of course!!!
if ($in != '')
{
@ -1157,7 +1137,7 @@ function edit_node(&$mm, $rewrite = false)
{
display($mm);
message($mm, 'Editing cancelled');
return;
return false;
}
// up arrow and home
@ -1262,32 +1242,19 @@ function edit_node(&$mm, $rewrite = false)
// enter
elseif ($in=="\012")
{
$title = trim($title);
$mm['nodes'][ $mm['active_node'] ]['title'] = $title;
$original['nodes'][ $mm['active_node'] ]['title'] = $title;
$mm['modified'] = true;
build_map($mm);
display($mm);
return;
}
return trim($title);
// ctrl+v
elseif ($in=="\026")
elseif ($in==ctrl_v)
{
$content =
trim
(
str_replace
(
"\n",
" ",
str_replace
(
"\t",
" ",
get_from_clipboard($mm)
)
["\n", "\r", "\t"]
,[" ", "", " " ]
,get_from_clipboard($mm)
)
);
@ -1326,10 +1293,13 @@ function edit_node(&$mm, $rewrite = false)
(
$title
,$cursor-1
);
)
;
$title = str_replace(BOM,'',$title);
$cursor++;
$title = mb_ereg_replace("[\000-\010\013-\037\177".BOM."]",'',$title);
$cursor += mb_strlen($in);
// the input content can be longer than one character if
// the user uses ctrl+shift+v to paste.
}
// adjusting the position and shift
@ -1343,6 +1313,65 @@ function edit_node(&$mm, $rewrite = false)
}
function show_line(&$mm, $title, $cursor, $shift)
{
$output = mb_substr($title,$shift,$mm['terminal_width']-1);
$output .= str_repeat( ' ' ,$mm['terminal_width'] - mb_strlen($output) );
// showing the cursor
$output =
mb_substr
(
$output
,0
,$cursor-$shift-1
)
.invert_on
.mb_substr
(
$output
,$cursor-$shift-1
,1
)
.invert_off
.mb_substr
(
$output
,$cursor-$shift
);
put(0,$mm['terminal_height'],$mm['active_node_color'].$output);
}
// }}}
// {{{ edit node
function edit_node(&$mm, $rewrite = false)
{
$title = $rewrite ? '' : $mm['nodes'][ $mm['active_node'] ]['title'];
if ($mm['active_node']==0 && $title=='root') $title='';
$output = magic_readline($mm, $title);
if ($output === false)
{
display($mm);
message($mm, 'Editing cancelled');
return;
}
$mm['nodes'][ $mm['active_node'] ]['title'] = $output;
push_change($mm);
$mm['modified'] = true;
build_map($mm);
display($mm);
}
// }}}
// {{{ center active node
@ -1411,12 +1440,7 @@ function go_to_bottom(&$mm)
function search(&$mm)
{
put(0,$mm['terminal_height'],$mm['active_node_color'].str_repeat(' ',$mm['terminal_width']));
move(0,$mm['terminal_height']);
system("stty sane");
$mm['query'] = readline('Search for: ');
system('stty cbreak -echo');
$mm['query'] = magic_readline($mm,'');
if (empty($mm['query']))
{
@ -1426,6 +1450,7 @@ function search(&$mm)
if (!next_search_result($mm))
previous_search_result($mm);
}
function previous_search_result(&$mm)
@ -1453,7 +1478,10 @@ function previous_search_result(&$mm)
}
if ($nid<0)
{
display($mm);
return false;
}
$mm['active_node'] = $nid;
display($mm);
@ -1499,7 +1527,6 @@ function move_active_node_down(&$mm)
if ($mm['active_node']==0) return;
push_change($mm);
$mm['modified'] = true;
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
@ -1536,7 +1563,6 @@ function move_active_node_up(&$mm)
if ($mm['active_node']==0) return;
push_change($mm);
$mm['modified'] = true;
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
@ -1683,26 +1709,18 @@ function export_html_node(&$mm, $parent_id)
function save(&$mm, $new_name = false)
{
if (empty($mm['filename']))
$new_name = true;
if ($new_name)
if ($new_name || empty($mm['filename']))
{
$path = exec('pwd');
put(0,$mm['terminal_height'],$mm['active_node_color'].str_repeat(' ',$mm['terminal_width']));
put(0,$mm['terminal_height']," $path -- new path and file name: ");
$new_name = magic_readline($mm, empty($mm['filename']) ? exec('pwd') : $mm['filename']);
system("stty sane");
$mm['filename'] = trim(readline());
system('stty cbreak -echo');
if ($mm['filename']=='')
if ($new_name === false)
{
display($mm);
message($mm, 'Saving cancelled');
return;
}
$mm['filename'] = $new_name;
$ext = mb_substr( $mm['filename'], mb_strrpos($mm['filename'],'.') + 1);
if ($ext!='hmm')
@ -1791,7 +1809,18 @@ function push_change(&$mm)
{
// flush any redo chain
while(count($mm['changes']) > $mm['change_index'])
{
array_pop($mm['changes']);
array_pop($mm['change_active_node']);
}
// removing the old history if it's getting bigger than the maximum
if (count($mm['changes']) >= $mm['change_max_steps'])
{
array_shift($mm['changes']);
array_shift($mm['change_active_node']);
$mm['change_index']--;
}
array_push($mm['changes'], $mm['nodes']);
array_push($mm['change_active_node'], $mm['active_node']);
@ -1986,7 +2015,15 @@ function encode_tree(&$mm, $id, $exclude_parent = false, $base = 0)
function append(&$mm)
{
$mm['nodes'][ $mm['active_node'] ]['title'] .=
' '. str_replace("\n",' ',str_replace("\t",' ',trim(get_from_clipboard($mm))));
' '
.str_replace
(
["\n","\r","\t"]
,[' ','', ' ']
,trim(get_from_clipboard($mm))
)
;
build_map($mm);
display($mm);
}
@ -2001,10 +2038,6 @@ function paste_sub_tree(&$mm, $as_sibling )
if ($as_sibling && $mm['active_node']==$mm['root']) return;
push_change($mm);
$mm['modified'] = true;
if ($as_sibling)
$parent_id = $mm['nodes'][ $mm['active_node'] ]['parent'];
else
@ -2024,8 +2057,12 @@ function paste_sub_tree(&$mm, $as_sibling )
)
;
$mm['nodes'] += $st;
if ($st==[]) return;
push_change($mm);
$mm['modified'] = true;
$mm['nodes'] += $st;
// doing it like this, in case the sub-tree has more than
// one top-level element.
@ -2083,7 +2120,14 @@ function copy_to_clipboard(&$mm, $text)
function get_from_clipboard(&$mm)
{
return str_replace(BOM,'',shell_exec($mm['clipboard']['read']));
return
mb_ereg_replace
(
"[\000-\010\013-\037\177".BOM."]"
,''
,shell_exec($mm['clipboard']['read'])
)
;
}
@ -2114,14 +2158,15 @@ function yank_node(&$mm, $exclude_parent = false )
// }}}
// {{{ delete
function delete_node(&$mm, $exclude_parent = false )
function delete_node(&$mm, $exclude_parent = false, $dont_copy_to_clipboard = false )
{
if ($mm['active_node']==$mm['root'])
$exclude_parent = true;
if (!$dont_copy_to_clipboard)
copy_to_clipboard($mm, encode_tree($mm, $mm['active_node'], $exclude_parent) );
push_change($mm);
if ($mm['active_node']==$mm['root']) $exclude_parent = true;
copy_to_clipboard($mm, encode_tree($mm, $mm['active_node'], $exclude_parent) );
$mm['modified'] = true;
delete_node_internal($mm, $mm['active_node'], $exclude_parent);
@ -2129,7 +2174,8 @@ function delete_node(&$mm, $exclude_parent = false )
build_map($mm);
display($mm);
message($mm, 'Item(s) are cut and placed into the clipboard.');
if (!$dont_copy_to_clipboard)
message($mm, 'Item(s) are cut and placed into the clipboard.');
}
@ -2565,6 +2611,7 @@ function monitor_key_presses(&$mm)
case 'd': delete_node($mm); break;
case 'D': delete_node($mm, true); break;
case del: delete_node($mm, false, true); break;
case 'e': edit_node($mm); break;
case 'E': edit_node($mm, true); break;
@ -2644,7 +2691,10 @@ function monitor_key_presses(&$mm)
case '~': go_to_root($mm); break;
case ' ': toggle($mm); break;
case '/': search($mm); break;
case '?': search($mm); break;
case ctrl_f: search($mm); break;
case "\n": insert_node($mm, insert_sibling); break;
case "\t": insert_node($mm, insert_child); break;

View file

@ -10,19 +10,20 @@
Adding, removing, and editing nodes:
* `o` or `enter` - create a new sibling to the active node
* `O` or `tab` - create a new child for the active node
* `o` or `Enter` - create a new sibling to the active node
* `O` or `Tab` - create a new child for the active node
* `y` - yanks (copies) the active node and its descendants
* `Y` - yanks (copies) the descendants of the active node
* `d` - deletes (cuts) the active node and its descendants
* `D` - deletes (cuts) the descendants of the active node
* `Delete` - deletes the active node and its descendants without putting them in the clipboard
* `p` - pastes as descendants of the active node
* `P` - pastes as siblings of the active node
* `ctrl+p` - appends the clipboard text at the end of the active node's title
* `Ctrl+p` - appends the clipboard text at the end of the active node's title
* `e`, `i`, or `a` - edits the active node
* `E`, `I`, or `A` - edits the active node, ignoring the existing text
* `u` - undo
* `ctrl+r` - redo
* `Ctrl+r` - redo
Relative navigating and moving:
@ -47,7 +48,7 @@ Adjusting the view:
Collapsing and expanding:
* `space` - toggles the active node
* `Space` - toggles the active node
* `v` - collapses everything other than the first-level nodes
* `b` - expands all nodes
* `1` to `9` - collapse the nth level and expand those before
@ -58,7 +59,7 @@ Collapsing and expanding:
Search:
* `/` - searches for a phrase
* `/`, `?`, or `Ctrl+f` - searches for a phrase
* `n` - goes to the next search result
* `N` - goes to the previous search result
@ -70,6 +71,21 @@ Save, export, and quit:
* `q` - quits (if the changes were already saved)
* `Q` - quits, ignoring the changes
In the text editor:
* `↓` - move the cursor to the end of the line
* `↑` - move the cursor to the beginning of the line
* `←` or `Home` - move the cursor to the left
* `→` or `End` - move the cursor to the right
* `Ctrl+Left` or `Shift+Left` - move cursor to the previous word
* `Ctrl+Right` or `Shift+right` - move cursor to the next word
* `Delete` - delete character
* `Ctrl+Delete` - delete word
* `Backspace` - delete previous character
* `ctrl+Backspace` - delete previous word
* `Ctrl+v` or `Ctrl+Shift+v` - paste
* `Esc` - cancel editing
* `Enter` - wanna guess? ;)
# Configuration
@ -84,6 +100,7 @@ You can create an `h-m-m.conf` file in the same directory as the application and
message_color = "\033[38;5;0m\033[48;5;141m\033[1m"
center_lock = false
focus_lock = false
undo_steps = 24
The colors are ASCII escape codes.