mirror of
https://github.com/nadrad/h-m-m.git
synced 2024-06-08 03:52:12 +02:00
Merge branch 'nadrad:main' into main
This commit is contained in:
commit
891f6f45b7
244
h-m-m
244
h-m-m
|
@ -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,12 +322,17 @@ function decode_tree($lines, $root_id, $start_id)
|
|||
foreach ($lines as $lid=>$line)
|
||||
{
|
||||
$lines[$lid] =
|
||||
str_replace
|
||||
mb_ereg_replace
|
||||
(
|
||||
[ "\t", "\n", "\r", BOM ]
|
||||
,[ " ", " ", " ", "" ]
|
||||
"[\000-\010\013-\037\177".BOM."]"
|
||||
,''
|
||||
,str_replace
|
||||
(
|
||||
[ "\t", "\n", "\r" ]
|
||||
,[ " ", " ", " " ]
|
||||
,$lines[$lid]
|
||||
)
|
||||
)
|
||||
;
|
||||
|
||||
$indentation = mb_strlen($lines[$lid]) - mb_strlen(ltrim($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 )
|
||||
{
|
||||
push_change($mm);
|
||||
|
||||
if ($mm['active_node']==$mm['root']) $exclude_parent = true;
|
||||
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);
|
||||
$mm['modified'] = true;
|
||||
|
||||
delete_node_internal($mm, $mm['active_node'], $exclude_parent);
|
||||
|
@ -2129,6 +2174,7 @@ function delete_node(&$mm, $exclude_parent = false )
|
|||
build_map($mm);
|
||||
display($mm);
|
||||
|
||||
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;
|
||||
|
|
29
readme.md
29
readme.md
|
@ -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.
|
||||
|
||||
|
|
Loading…
Reference in a new issue