hyperlist 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +25 -12
- data/hyperlist +274 -27
- data/hyperlist.gemspec +2 -2
- metadata +6 -7
- data/test_visibility.hl +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ab71a37a8c51bc72f5a944172d2fae808da9ed42e4a21e13f937d2a4410596a
|
4
|
+
data.tar.gz: 346c2edd59e6a6e4a116d05a506ded75b313996baa06f938def3fb0947c05850
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b66f71b652663dbf1fcbcee37fa7478b718813a7dd234081aad77e9110d1e01c472f2ce3d2a325ad6cd1e922b2efacb398c531fab79cd594999c5e2db20ad039
|
7
|
+
data.tar.gz: 3f2a1573bb24704f3f3df797e8cd3766e78d265aa27c68ca41fc7326976a23ec361c9fc93c814b9a8afc7b9003921b7e0c3111e6bfbbc9df0ebf8efddee3401e
|
data/README.md
CHANGED
@@ -29,17 +29,26 @@ For historical context and the original VIM implementation, see: [hyperlist.vim]
|
|
29
29
|
### Help Screen
|
30
30
|

|
31
31
|
|
32
|
-
## What's New in v1.
|
33
|
-
|
34
|
-
###
|
35
|
-
-
|
36
|
-
-
|
37
|
-
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
-
|
32
|
+
## What's New in v1.8.0
|
33
|
+
|
34
|
+
### 📋 Multi-Line Paste Support
|
35
|
+
- **Paste multiple lines**: When pasting multi-line content into item insertion prompts ('o', 'O', 'a', 'A'), each line becomes a separate item
|
36
|
+
- **Visual feedback**: Shows `[+N lines]` indicator during multi-line paste
|
37
|
+
- **Smart insertion**: All pasted lines inserted as siblings at the same level
|
38
|
+
- Great for importing bullet lists from PDFs, emails, or other documents
|
39
|
+
- Requires rcurses 6.1.5+
|
40
|
+
|
41
|
+
### 📄 PDF/LaTeX Export
|
42
|
+
- **Export to PDF**: `:export pdf filename.pdf` - Full LaTeX-based PDF generation
|
43
|
+
- **Export to LaTeX**: `:export latex filename.tex` - Get the LaTeX source
|
44
|
+
- **Professional output**: Color-coded elements, table of contents, headers
|
45
|
+
- **Complete HyperList support**: All syntax elements rendered beautifully
|
46
|
+
- Requires: texlive-latex-base and texlive-latex-extra packages
|
47
|
+
|
48
|
+
### 📋 System Clipboard Integration
|
49
|
+
- **Yank to clipboard**: 'y' and 'Y' now copy to system clipboard
|
50
|
+
- **Middle-click paste**: Yanked items can be pasted into other terminals
|
51
|
+
- **Preserves indentation**: Copied text maintains proper structure
|
43
52
|
|
44
53
|
## Previous Version Features (v1.4.0)
|
45
54
|
|
@@ -149,6 +158,8 @@ All `:set` commands automatically update the file's configuration line.
|
|
149
158
|
- **Dates**: `2025-08-12` or `2025-08-12 14:30`
|
150
159
|
|
151
160
|
### Export Formats
|
161
|
+
- **PDF**: Professional LaTeX-based PDF with color coding and TOC
|
162
|
+
- **LaTeX**: Source .tex files for customization
|
152
163
|
- **HTML**: Full-featured HTML with syntax highlighting
|
153
164
|
- **Markdown**: GitHub-flavored Markdown
|
154
165
|
- **Plain Text**: Clean text output
|
@@ -236,9 +247,11 @@ hyperlist file.txt # Open any text file
|
|
236
247
|
- `:q` - Quit
|
237
248
|
- `:wq` or `W` - Save and quit
|
238
249
|
- `:e file` - Open file
|
250
|
+
- `:export pdf` - Export to PDF (requires LaTeX)
|
251
|
+
- `:export latex` - Export to LaTeX source
|
239
252
|
- `:export html` - Export to HTML
|
240
253
|
- `:export md` - Export to Markdown
|
241
|
-
- `:graph` - Export to PNG
|
254
|
+
- `:graph` - Export to PNG graph
|
242
255
|
|
243
256
|
#### Template Commands
|
244
257
|
- `:st` - Save current document as template
|
data/hyperlist
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
# Check for help/version BEFORE loading any libraries
|
8
8
|
if ARGV[0] == '-h' || ARGV[0] == '--help'
|
9
9
|
puts <<~HELP
|
10
|
-
HyperList v1.
|
10
|
+
HyperList v1.8.0 - Terminal User Interface for HyperList files
|
11
11
|
|
12
12
|
USAGE
|
13
13
|
hyperlist [OPTIONS] [FILE]
|
@@ -52,7 +52,7 @@ if ARGV[0] == '-h' || ARGV[0] == '--help'
|
|
52
52
|
HELP
|
53
53
|
exit 0
|
54
54
|
elsif ARGV[0] == '-v' || ARGV[0] == '--version'
|
55
|
-
puts "HyperList v1.
|
55
|
+
puts "HyperList v1.8.0"
|
56
56
|
exit 0
|
57
57
|
end
|
58
58
|
|
@@ -72,7 +72,7 @@ class HyperListApp
|
|
72
72
|
include Rcurses::Input
|
73
73
|
include Rcurses::Cursor
|
74
74
|
|
75
|
-
VERSION = "1.
|
75
|
+
VERSION = "1.8.0"
|
76
76
|
|
77
77
|
def initialize(filename = nil)
|
78
78
|
@filename = filename ? File.expand_path(filename) : nil
|
@@ -724,10 +724,12 @@ class HyperListApp
|
|
724
724
|
when 'md', 'markdown' then '.md'
|
725
725
|
when 'html' then '.html'
|
726
726
|
when 'txt', 'text' then '.txt'
|
727
|
+
when 'latex', 'tex' then '.tex'
|
728
|
+
when 'pdf' then '.pdf'
|
727
729
|
end
|
728
730
|
export_file = base + extension
|
729
731
|
end
|
730
|
-
|
732
|
+
|
731
733
|
content = case format
|
732
734
|
when 'md', 'markdown'
|
733
735
|
export_to_markdown
|
@@ -735,10 +737,39 @@ class HyperListApp
|
|
735
737
|
export_to_html
|
736
738
|
when 'txt', 'text'
|
737
739
|
export_to_text
|
740
|
+
when 'latex', 'tex'
|
741
|
+
export_to_latex
|
742
|
+
when 'pdf'
|
743
|
+
export_to_latex
|
738
744
|
end
|
739
|
-
|
745
|
+
|
740
746
|
File.open(export_file, 'w') { |f| f.write(content) }
|
741
|
-
|
747
|
+
|
748
|
+
# For PDF, compile the LaTeX file
|
749
|
+
if format == 'pdf'
|
750
|
+
tex_file = export_file.sub(/\.pdf$/, '.tex')
|
751
|
+
File.open(tex_file, 'w') { |f| f.write(content) }
|
752
|
+
|
753
|
+
# Compile LaTeX to PDF
|
754
|
+
@message = "Compiling LaTeX to PDF..."
|
755
|
+
render_footer
|
756
|
+
|
757
|
+
result = system("pdflatex -interaction=nonstopmode -output-directory=#{File.dirname(tex_file)} #{tex_file} > /dev/null 2>&1")
|
758
|
+
if result
|
759
|
+
# Run twice for TOC
|
760
|
+
system("pdflatex -interaction=nonstopmode -output-directory=#{File.dirname(tex_file)} #{tex_file} > /dev/null 2>&1")
|
761
|
+
@message = "Exported to #{export_file}"
|
762
|
+
# Clean up auxiliary files
|
763
|
+
['aux', 'log', 'out', 'toc'].each do |ext|
|
764
|
+
aux_file = tex_file.sub(/\.tex$/, ".#{ext}")
|
765
|
+
File.delete(aux_file) if File.exist?(aux_file)
|
766
|
+
end
|
767
|
+
else
|
768
|
+
@message = "PDF compilation failed. Check #{tex_file}"
|
769
|
+
end
|
770
|
+
else
|
771
|
+
@message = "Exported to #{export_file}"
|
772
|
+
end
|
742
773
|
rescue => e
|
743
774
|
@message = "Export failed: #{e.message}"
|
744
775
|
end
|
@@ -948,7 +979,151 @@ class HyperListApp
|
|
948
979
|
end
|
949
980
|
lines.join("\n")
|
950
981
|
end
|
951
|
-
|
982
|
+
|
983
|
+
def escape_latex(text)
|
984
|
+
# Escape special LaTeX characters
|
985
|
+
text = text.gsub('\\', '\\textbackslash{}')
|
986
|
+
text = text.gsub('&', '\\&')
|
987
|
+
text = text.gsub('%', '\\%')
|
988
|
+
text = text.gsub('$', '\\$')
|
989
|
+
text = text.gsub('#', '\\#')
|
990
|
+
text = text.gsub('_', '\\_')
|
991
|
+
text = text.gsub('^', '\\textasciicircum{}')
|
992
|
+
text = text.gsub('~', '\\textasciitilde{}')
|
993
|
+
text
|
994
|
+
end
|
995
|
+
|
996
|
+
def export_to_latex
|
997
|
+
lines = []
|
998
|
+
|
999
|
+
# LaTeX header
|
1000
|
+
lines << "% Generated by HyperList - LaTeX Export"
|
1001
|
+
lines << "% Export date: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
1002
|
+
lines << ""
|
1003
|
+
lines << "\\documentclass[11pt,a4paper]{article}"
|
1004
|
+
lines << "\\usepackage[utf8]{inputenc}"
|
1005
|
+
lines << "\\usepackage[T1]{fontenc}"
|
1006
|
+
lines << "\\usepackage[english]{babel}"
|
1007
|
+
lines << "\\usepackage[margin=2.5cm]{geometry}"
|
1008
|
+
lines << "\\usepackage{xcolor}"
|
1009
|
+
lines << "\\usepackage{enumitem}"
|
1010
|
+
lines << "\\usepackage{fancyhdr}"
|
1011
|
+
lines << "\\usepackage{hyperref}"
|
1012
|
+
lines << "\\usepackage{tcolorbox}"
|
1013
|
+
lines << "\\usepackage{fontawesome5}"
|
1014
|
+
lines << ""
|
1015
|
+
lines << "% HyperList color definitions"
|
1016
|
+
lines << "\\definecolor{hloperator}{RGB}{41,128,185}"
|
1017
|
+
lines << "\\definecolor{hlproperty}{RGB}{231,76,60}"
|
1018
|
+
lines << "\\definecolor{hlqualifier}{RGB}{39,174,96}"
|
1019
|
+
lines << "\\definecolor{hlhashtag}{RGB}{243,156,18}"
|
1020
|
+
lines << "\\definecolor{hlreference}{RGB}{155,89,182}"
|
1021
|
+
lines << "\\definecolor{hlcomment}{RGB}{127,140,141}"
|
1022
|
+
lines << "\\definecolor{hlquote}{RGB}{22,160,133}"
|
1023
|
+
lines << "\\definecolor{hlstate}{RGB}{46,204,113}"
|
1024
|
+
lines << "\\definecolor{hltransition}{RGB}{230,126,34}"
|
1025
|
+
lines << ""
|
1026
|
+
lines << "% HyperList commands"
|
1027
|
+
lines << "\\newcommand{\\hloperator}[1]{\\textcolor{hloperator}{\\textbf{#1}}}"
|
1028
|
+
lines << "\\newcommand{\\hlproperty}[1]{\\textcolor{hlproperty}{\\textit{#1}}}"
|
1029
|
+
lines << "\\newcommand{\\hlqualifier}[1]{\\textcolor{hlqualifier}{\\texttt{#1}}}"
|
1030
|
+
lines << "\\newcommand{\\hlhashtag}[1]{\\textcolor{hlhashtag}{\\textbf{#1}}}"
|
1031
|
+
lines << "\\newcommand{\\hlreference}[1]{\\textcolor{hlreference}{#1}}"
|
1032
|
+
lines << "\\newcommand{\\hlcomment}[1]{\\textcolor{hlcomment}{\\textit{#1}}}"
|
1033
|
+
lines << "\\newcommand{\\hlquote}[1]{\\textcolor{hlquote}{#1}}"
|
1034
|
+
lines << "\\newcommand{\\hlstate}[1]{\\begin{tcolorbox}[colback=hlstate!10,colframe=hlstate,title=State]#1\\end{tcolorbox}}"
|
1035
|
+
lines << "\\newcommand{\\hltransition}[1]{\\begin{tcolorbox}[colback=hltransition!10,colframe=hltransition,title=Action]#1\\end{tcolorbox}}"
|
1036
|
+
lines << "\\newcommand{\\hlsubstitution}[1]{\\textcolor{hlqualifier}{#1}}"
|
1037
|
+
lines << "\\newcommand{\\checkbox}{\\faSquare[regular]}"
|
1038
|
+
lines << "\\newcommand{\\checkboxdone}{\\faCheckSquare}"
|
1039
|
+
lines << "\\newcommand{\\checkboxprogress}{\\faMinusSquare[regular]}"
|
1040
|
+
lines << ""
|
1041
|
+
lines << "% Document setup"
|
1042
|
+
title = @filename ? File.basename(@filename, '.*') : 'HyperList Export'
|
1043
|
+
lines << "\\title{#{escape_latex(title)}}"
|
1044
|
+
lines << "\\author{Generated by HyperList}"
|
1045
|
+
lines << "\\date{#{Time.now.strftime('%Y-%m-%d')}}"
|
1046
|
+
lines << ""
|
1047
|
+
lines << "\\pagestyle{fancy}"
|
1048
|
+
lines << "\\fancyhf{}"
|
1049
|
+
lines << "\\fancyhead[R]{\\thepage}"
|
1050
|
+
lines << "\\fancyhead[L]{#{escape_latex(title)}}"
|
1051
|
+
lines << ""
|
1052
|
+
lines << "\\begin{document}"
|
1053
|
+
lines << "\\maketitle"
|
1054
|
+
lines << "\\tableofcontents"
|
1055
|
+
lines << "\\newpage"
|
1056
|
+
lines << ""
|
1057
|
+
lines << "\\begin{itemize}[leftmargin=0pt,itemsep=2pt,parsep=0pt]"
|
1058
|
+
|
1059
|
+
# Process each item
|
1060
|
+
prev_level = 0
|
1061
|
+
@items.each do |item|
|
1062
|
+
text = item["text"]
|
1063
|
+
level = item["level"]
|
1064
|
+
|
1065
|
+
# Handle level changes
|
1066
|
+
if level > prev_level
|
1067
|
+
(level - prev_level).times do
|
1068
|
+
lines << "\\begin{itemize}"
|
1069
|
+
end
|
1070
|
+
elsif level < prev_level
|
1071
|
+
(prev_level - level).times do
|
1072
|
+
lines << "\\end{itemize}"
|
1073
|
+
end
|
1074
|
+
end
|
1075
|
+
|
1076
|
+
# Escape LaTeX special characters first
|
1077
|
+
text = escape_latex(text)
|
1078
|
+
|
1079
|
+
# Convert checkboxes
|
1080
|
+
text = text.gsub(/\[_\]/, '\\checkbox{}')
|
1081
|
+
text = text.gsub(/\[x\]|\[X\]/, '\\checkboxdone{}')
|
1082
|
+
text = text.gsub(/\[O\]/, '\\checkboxprogress{}')
|
1083
|
+
|
1084
|
+
# Convert HyperList markup (must be after escaping)
|
1085
|
+
text = text.gsub(/ \*([^*]+)\* /, ' \\textbf{\1} ')
|
1086
|
+
text = text.gsub(/ \/([^\/]+)\/ /, ' \\textit{\1} ')
|
1087
|
+
text = text.gsub(/ _([^_]+)_ /, ' \\underline{\1} ')
|
1088
|
+
|
1089
|
+
# Convert HyperList elements
|
1090
|
+
text = text.gsub(/\[([^\]]+)\]/, '\\hlqualifier{[\1]}')
|
1091
|
+
text = text.gsub(/\{([^\}]+)\}/, '\\hlsubstitution{\{\1\}}')
|
1092
|
+
text = text.gsub(/(#[a-zA-Z0-9.:\/\\_&?%=\-*]+)/, '\\hlhashtag{\1}')
|
1093
|
+
text = text.gsub(/(<{1,2}[a-zA-Z0-9.:\/\\_&?%=\-* ]+>{1,2})/, '\\hlreference{\1}')
|
1094
|
+
text = text.gsub(/(\([^)]*\))/, '\\hlcomment{\1}')
|
1095
|
+
text = text.gsub(/(\"[^\"]*\")/, '\\hlquote{\1}')
|
1096
|
+
|
1097
|
+
# Convert States and Transitions
|
1098
|
+
if text =~ /^S: (.+)/
|
1099
|
+
text = "\\hlstate{State: #{$1}}"
|
1100
|
+
elsif text =~ /^T: (.+)/
|
1101
|
+
text = "\\hltransition{Action: #{$1}}"
|
1102
|
+
elsif text =~ /^\| (.+)/
|
1103
|
+
text = "\\hlstate{State: #{$1}}"
|
1104
|
+
elsif text =~ /^\/ (.+)/
|
1105
|
+
text = "\\hltransition{Action: #{$1}}"
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
# Convert Operators and Properties
|
1109
|
+
text = text.gsub(/([A-Z_\-() \/]{2,}): /, '\\hloperator{\1:} ')
|
1110
|
+
text = text.gsub(/([a-zA-Z0-9,._&?%=\-\/+<>#'()*:]{2,}): /, '\\hlproperty{\1:} ')
|
1111
|
+
|
1112
|
+
lines << "\\item #{text}"
|
1113
|
+
prev_level = level
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
# Close any remaining nested lists
|
1117
|
+
prev_level.times do
|
1118
|
+
lines << "\\end{itemize}"
|
1119
|
+
end
|
1120
|
+
|
1121
|
+
lines << "\\end{itemize}"
|
1122
|
+
lines << "\\end{document}"
|
1123
|
+
|
1124
|
+
lines.join("\n")
|
1125
|
+
end
|
1126
|
+
|
952
1127
|
def render
|
953
1128
|
render_main
|
954
1129
|
render_split_pane if @split_view
|
@@ -2332,19 +2507,41 @@ class HyperListApp
|
|
2332
2507
|
|
2333
2508
|
def insert_line
|
2334
2509
|
@mode = :insert
|
2335
|
-
|
2510
|
+
|
2336
2511
|
input = @footer.ask("New item: ", "")
|
2337
|
-
|
2512
|
+
|
2338
2513
|
if input && !input.strip.empty?
|
2339
|
-
|
2514
|
+
# Collect all lines (first line + buffer)
|
2515
|
+
all_lines = [input]
|
2516
|
+
if @footer.multiline_buffer && !@footer.multiline_buffer.empty?
|
2517
|
+
all_lines += @footer.multiline_buffer.reject { |l| l.strip.empty? }
|
2518
|
+
@footer.multiline_buffer = []
|
2519
|
+
end
|
2520
|
+
|
2521
|
+
# Insert all lines as siblings at the same level
|
2522
|
+
all_lines.each do |line|
|
2523
|
+
insert_line_with_text(line.strip)
|
2524
|
+
@current -= 1 # Keep cursor at same position so next insert is sibling
|
2525
|
+
end
|
2526
|
+
@current += 1 # Move to last inserted item
|
2527
|
+
|
2340
2528
|
record_last_action(:insert_line, input)
|
2341
2529
|
end
|
2342
|
-
|
2530
|
+
|
2343
2531
|
@mode = :normal
|
2344
2532
|
@footer.clear # Clear footer immediately
|
2345
2533
|
@footer.refresh
|
2346
2534
|
end
|
2347
|
-
|
2535
|
+
|
2536
|
+
# Alias for 'o' key
|
2537
|
+
alias insert_line_below insert_line
|
2538
|
+
|
2539
|
+
# Method for 'O' key - insert line above
|
2540
|
+
def insert_line_above
|
2541
|
+
@current -= 1 if @current > 0
|
2542
|
+
insert_line
|
2543
|
+
end
|
2544
|
+
|
2348
2545
|
def insert_line_with_text(text)
|
2349
2546
|
return unless text && !text.strip.empty?
|
2350
2547
|
|
@@ -2371,14 +2568,27 @@ class HyperListApp
|
|
2371
2568
|
|
2372
2569
|
def insert_child
|
2373
2570
|
@mode = :insert
|
2374
|
-
|
2571
|
+
|
2375
2572
|
input = @footer.ask("New child item: ", "")
|
2376
|
-
|
2573
|
+
|
2377
2574
|
if input && !input.strip.empty?
|
2378
|
-
|
2575
|
+
# Collect all lines (first line + buffer)
|
2576
|
+
all_lines = [input]
|
2577
|
+
if @footer.multiline_buffer && !@footer.multiline_buffer.empty?
|
2578
|
+
all_lines += @footer.multiline_buffer.reject { |l| l.strip.empty? }
|
2579
|
+
@footer.multiline_buffer = []
|
2580
|
+
end
|
2581
|
+
|
2582
|
+
# Insert all lines as siblings at the same level
|
2583
|
+
all_lines.each do |line|
|
2584
|
+
insert_child_with_text(line.strip)
|
2585
|
+
@current -= 1 # Keep cursor at same position so next insert is sibling
|
2586
|
+
end
|
2587
|
+
@current += 1 # Move to last inserted item
|
2588
|
+
|
2379
2589
|
record_last_action(:insert_child, input)
|
2380
2590
|
end
|
2381
|
-
|
2591
|
+
|
2382
2592
|
@mode = :normal
|
2383
2593
|
@footer.clear # Clear footer immediately
|
2384
2594
|
@footer.refresh
|
@@ -2386,14 +2596,43 @@ class HyperListApp
|
|
2386
2596
|
|
2387
2597
|
def insert_outdented
|
2388
2598
|
@mode = :insert
|
2389
|
-
|
2599
|
+
|
2390
2600
|
input = @footer.ask("New outdented item: ", "")
|
2391
|
-
|
2601
|
+
|
2392
2602
|
if input && !input.strip.empty?
|
2393
|
-
|
2603
|
+
# Collect all lines (first line + buffer)
|
2604
|
+
all_lines = [input]
|
2605
|
+
if @footer.multiline_buffer && !@footer.multiline_buffer.empty?
|
2606
|
+
all_lines += @footer.multiline_buffer.reject { |l| l.strip.empty? }
|
2607
|
+
@footer.multiline_buffer = []
|
2608
|
+
end
|
2609
|
+
|
2610
|
+
# Calculate target level BEFORE inserting anything
|
2611
|
+
visible = get_visible_items
|
2612
|
+
if @current < visible.length
|
2613
|
+
current_level = visible[@current]["level"]
|
2614
|
+
target_level = [current_level - 1, 0].max # Outdented level
|
2615
|
+
else
|
2616
|
+
target_level = 0
|
2617
|
+
end
|
2618
|
+
|
2619
|
+
# Insert first line normally
|
2620
|
+
insert_outdented_with_text(all_lines[0].strip)
|
2621
|
+
|
2622
|
+
# Insert remaining lines at same level as the first
|
2623
|
+
if all_lines.length > 1
|
2624
|
+
all_lines[1..-1].each do |line|
|
2625
|
+
visible = get_visible_items
|
2626
|
+
real_idx = get_real_index(visible[@current])
|
2627
|
+
@items.insert(real_idx + 1, {"text" => line.strip, "level" => target_level, "fold" => false})
|
2628
|
+
@current += 1
|
2629
|
+
end
|
2630
|
+
@modified = true
|
2631
|
+
end
|
2632
|
+
|
2394
2633
|
record_last_action(:insert_outdented, input)
|
2395
2634
|
end
|
2396
|
-
|
2635
|
+
|
2397
2636
|
@mode = :normal
|
2398
2637
|
@footer.clear # Clear footer immediately
|
2399
2638
|
@footer.refresh
|
@@ -2578,14 +2817,14 @@ class HyperListApp
|
|
2578
2817
|
def yank_line(with_children = false)
|
2579
2818
|
visible = get_visible_items
|
2580
2819
|
return if @current >= visible.length
|
2581
|
-
|
2820
|
+
|
2582
2821
|
item = visible[@current]
|
2583
2822
|
real_idx = get_real_index(item)
|
2584
|
-
|
2823
|
+
|
2585
2824
|
@clipboard = []
|
2586
2825
|
@clipboard << item.dup
|
2587
2826
|
@clipboard_is_tree = with_children # Remember if this is a tree copy (Y) or single (y)
|
2588
|
-
|
2827
|
+
|
2589
2828
|
# Copy children if requested
|
2590
2829
|
if with_children
|
2591
2830
|
level = item["level"]
|
@@ -2597,7 +2836,15 @@ class HyperListApp
|
|
2597
2836
|
end
|
2598
2837
|
end
|
2599
2838
|
end
|
2600
|
-
|
2839
|
+
|
2840
|
+
# Copy to system clipboard for middle-click paste
|
2841
|
+
begin
|
2842
|
+
text_to_copy = @clipboard.map { |it| " " * it["level"] + it["text"] }.join("\n")
|
2843
|
+
Clipboard.copy(text_to_copy)
|
2844
|
+
rescue => e
|
2845
|
+
# Silently fail if clipboard gem not available
|
2846
|
+
end
|
2847
|
+
|
2601
2848
|
@message = "Yanked #{@clipboard.length} item(s)"
|
2602
2849
|
record_last_action(:yank_line, with_children)
|
2603
2850
|
end
|
@@ -3216,7 +3463,7 @@ class HyperListApp
|
|
3216
3463
|
help_lines << "#{"FILE OPERATIONS".fg("14")}"
|
3217
3464
|
help_lines << help_line("#{":w".fg("10")}", "Save", "#{":q".fg("10")}", "Quit")
|
3218
3465
|
help_lines << help_line("#{":wq".fg("10")}", "Save and quit", "#{":e file".fg("10")}", "Open file")
|
3219
|
-
help_lines << help_line("#{":recent".fg("10")}", "Recent files", "#{":export :ex".fg("10")}", "Export md|html|txt")
|
3466
|
+
help_lines << help_line("#{":recent".fg("10")}", "Recent files", "#{":export :ex".fg("10")}", "Export md|html|txt|pdf")
|
3220
3467
|
help_lines << help_line("#{":graph :g".fg("10")}", "Export to PNG graph", "#{":vsplit :vs".fg("10")}", "Split view")
|
3221
3468
|
help_lines << help_line("#{":as on".fg("10")}", "Enable autosave", "#{":as off".fg("10")}", "Disable autosave")
|
3222
3469
|
help_lines << help_line("#{":as N".fg("10")}", "Set interval (secs)", "#{":as".fg("10")}", "Show autosave status")
|
@@ -3900,12 +4147,12 @@ class HyperListApp
|
|
3900
4147
|
@current = 0
|
3901
4148
|
@offset = 0
|
3902
4149
|
@modified = false
|
3903
|
-
when /^(export|ex)\s+(md|markdown|html|txt|text)\s*(.*)$/
|
4150
|
+
when /^(export|ex)\s+(md|markdown|html|txt|text|latex|tex|pdf)\s*(.*)$/
|
3904
4151
|
format = $2
|
3905
4152
|
export_file = $3.empty? ? nil : $3
|
3906
4153
|
export_to(format, export_file)
|
3907
4154
|
when /^(export|ex)$/
|
3908
|
-
@message = "Usage: :export [md|html|txt] [filename] (or :ex)"
|
4155
|
+
@message = "Usage: :export [md|html|txt|latex|pdf] [filename] (or :ex)"
|
3909
4156
|
when "recent", "r"
|
3910
4157
|
show_recent_files
|
3911
4158
|
when "autosave on", "as on"
|
data/hyperlist.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "hyperlist"
|
3
|
-
spec.version = "1.8.
|
3
|
+
spec.version = "1.8.1"
|
4
4
|
spec.authors = ["Geir Isene"]
|
5
5
|
spec.email = ["g@isene.com"]
|
6
6
|
|
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.require_paths = ["."]
|
29
29
|
|
30
30
|
# Runtime dependencies
|
31
|
-
spec.add_runtime_dependency "rcurses", "~>
|
31
|
+
spec.add_runtime_dependency "rcurses", "~> 6.1", ">= 6.1.5"
|
32
32
|
|
33
33
|
# Development dependencies
|
34
34
|
spec.add_development_dependency "minitest", "~> 5.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyperlist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.8.
|
4
|
+
version: 1.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Geir Isene
|
8
8
|
autorequire:
|
9
9
|
bindir: "."
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-10-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rcurses
|
@@ -16,20 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6.1'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 6.1.5
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
29
|
+
version: '6.1'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version:
|
32
|
+
version: 6.1.5
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: minitest
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -79,7 +79,6 @@ files:
|
|
79
79
|
- img/screenshot_help.png
|
80
80
|
- img/screenshot_sample.png
|
81
81
|
- sample.hl
|
82
|
-
- test_visibility.hl
|
83
82
|
homepage: https://github.com/isene/HyperList
|
84
83
|
licenses:
|
85
84
|
- Unlicense
|