Compare commits
884 Commits
v6.0
...
line-foldi
| Author | SHA1 | Date | |
|---|---|---|---|
| c56bbe74bf | |||
|
|
8e6360d166 | ||
|
|
4e8238edec | ||
|
|
c497a5f90b | ||
|
|
b04a2a18ea | ||
|
|
613fe4b9b2 | ||
|
|
27bf87d21a | ||
|
|
b6faa5d5bb | ||
|
|
4ebd490225 | ||
|
|
f6e9c00f59 | ||
|
|
79b18f462c | ||
|
|
ff68fa7304 | ||
|
|
b6aa309aa7 | ||
|
|
6e39b405c8 | ||
|
|
0c3e596ad7 | ||
|
|
b41de01e6c | ||
|
|
e075df83e9 | ||
|
|
1cff717d98 | ||
|
|
68d4b84610 | ||
|
|
a41f238042 | ||
|
|
e18c6c95e7 | ||
|
|
c4948d5035 | ||
|
|
4c3ab6f5fb | ||
|
|
757ce59330 | ||
|
|
9375b99c52 | ||
|
|
50df473643 | ||
|
|
0c242b8666 | ||
|
|
96adcef377 | ||
|
|
a6046c6668 | ||
|
|
cfb9c08580 | ||
|
|
fde24946da | ||
|
|
9797150ffd | ||
|
|
d43809146f | ||
|
|
2c1bbb5552 | ||
|
|
f63547027c | ||
|
|
ab597a6c2f | ||
|
|
9383ed03a2 | ||
|
|
e1d954c739 | ||
|
|
6d98026285 | ||
|
|
21d5d8707f | ||
|
|
982bca3bd3 | ||
|
|
834b88eed9 | ||
|
|
b273b69cad | ||
|
|
81a3c3e82f | ||
|
|
cebb2a383d | ||
|
|
2adaa1139c | ||
|
|
ad92fe6638 | ||
|
|
4b21ed39c7 | ||
|
|
21b833d423 | ||
|
|
afb9cdac24 | ||
|
|
ca9d6e7dec | ||
|
|
03a1a00ef3 | ||
|
|
1e5c40765d | ||
|
|
67af31e8f3 | ||
|
|
57d70fedf1 | ||
|
|
bf4bc730c4 | ||
|
|
6adbd4249e | ||
|
|
96cf1b3807 | ||
|
|
be46139504 | ||
|
|
61abc2e59a | ||
|
|
b53833c4f3 | ||
|
|
f6d38a5be0 | ||
|
|
00d137baf3 | ||
|
|
27244483fe | ||
|
|
78f7424f37 | ||
|
|
2a9121fc2d | ||
|
|
c77a5e5169 | ||
|
|
21bedd0db9 | ||
|
|
7fe76a4dfb | ||
|
|
fd72375aa4 | ||
|
|
e9c0c8b930 | ||
|
|
66da03e555 | ||
|
|
382bcc77c0 | ||
|
|
dbc1f29296 | ||
|
|
799577b4df | ||
|
|
57e2cc251d | ||
|
|
8cb86c9582 | ||
|
|
e4852e4f56 | ||
|
|
2abf56546b | ||
|
|
02825602e2 | ||
|
|
0daeab17cd | ||
|
|
6b49b498cc | ||
|
|
924190ce7d | ||
|
|
4a347cd7dc | ||
|
|
1e022b55d1 | ||
|
|
29ff6abec6 | ||
|
|
054b478999 | ||
|
|
e6ce29d531 | ||
|
|
b3c195ef00 | ||
|
|
f0b1606f28 | ||
|
|
d0ee91f4eb | ||
|
|
266a4fc748 | ||
|
|
d985946ef5 | ||
|
|
9644ca0ca5 | ||
|
|
83f0a593fd | ||
|
|
3948c09d2b | ||
|
|
b89ab4a99d | ||
|
|
c04aa40543 | ||
|
|
6ee4c67226 | ||
|
|
b70851e488 | ||
|
|
7cf20d7227 | ||
|
|
355a5a3bfa | ||
|
|
6c3e9848b2 | ||
|
|
ac83dddcd2 | ||
|
|
e40ba24d89 | ||
|
|
9639971a0e | ||
|
|
bbab2770c5 | ||
|
|
0e7f744744 | ||
|
|
0d36dc4942 | ||
|
|
faf90cfaa6 | ||
|
|
34cfbcc4d0 | ||
|
|
376ae53608 | ||
|
|
95bcb90691 | ||
|
|
0edc6610dd | ||
|
|
fc84a19883 | ||
|
|
35e11ce7ff | ||
|
|
269b96b703 | ||
|
|
286aefa34a | ||
| 3cdc00fdf6 | |||
|
|
5660833ce8 | ||
|
|
8499183c02 | ||
|
|
2e59a695e7 | ||
|
|
6fe93a6c3f | ||
|
|
09db112412 | ||
|
|
2de91de36b | ||
|
|
f43240e9b0 | ||
|
|
ac1bf7d60e | ||
|
|
b11349d901 | ||
|
|
2838b2429e | ||
|
|
97d72f4821 | ||
|
|
5bb19b0598 | ||
|
|
22e2ea3cf4 | ||
|
|
cad7948400 | ||
|
|
bf342bcb3c | ||
|
|
d75b7a3072 | ||
| bf4d6244c6 | |||
|
|
c7276e58c9 | ||
|
|
b7c9882428 | ||
|
|
cb43493e00 | ||
|
|
7cf0125e9c | ||
|
|
3b22c1cce8 | ||
|
|
c1ea0601c9 | ||
|
|
0b7328bce4 | ||
|
|
0e430310b8 | ||
|
|
dbfce437af | ||
|
|
a01bc5f117 | ||
|
|
adff8171cc | ||
|
|
f16e8d8888 | ||
|
|
e637fdb42c | ||
|
|
0b17713756 | ||
|
|
5d31b0f595 | ||
|
|
a3cb12ccff | ||
|
|
84f7eb2d1e | ||
|
|
9e2f8e0fb3 | ||
|
|
8abdd80f24 | ||
|
|
3dc49fa6b8 | ||
|
|
d3019a1c40 | ||
|
|
63594a3f92 | ||
|
|
3e104064db | ||
|
|
c05a9009be | ||
|
|
902378fd7d | ||
|
|
3ac3b27259 | ||
|
|
a334b64e89 | ||
|
|
f6e9b78b73 | ||
|
|
d896becfee | ||
|
|
98ad9496cc | ||
|
|
80f6650c81 | ||
|
|
c3139b8d65 | ||
|
|
50107bd23a | ||
|
|
df20e9895f | ||
|
|
df0aa86e05 | ||
|
|
81a6abc623 | ||
|
|
4b14e562e2 | ||
|
|
6aa0f3ba39 | ||
|
|
c65d25da2f | ||
| 49a78cbb75 | |||
| 68f10939d4 | |||
|
|
287b7ef90b | ||
|
|
b1f5531063 | ||
|
|
9713f804df | ||
|
|
bdac995173 | ||
|
|
793d6723ec | ||
|
|
5670c57dd2 | ||
|
|
bf8b527375 | ||
|
|
a63141ecf4 | ||
|
|
dd50adb61b | ||
|
|
4694c95524 | ||
|
|
49be1275e6 | ||
|
|
8d49be96d6 | ||
|
|
5df0b2e41a | ||
|
|
07f84b7b61 | ||
|
|
083d6c70ee | ||
|
|
83ef26dc74 | ||
|
|
f1db15c7b6 | ||
|
|
93ae8259c8 | ||
|
|
8771acb98a | ||
|
|
a29c225b7a | ||
|
|
db9ada1bf8 | ||
|
|
1d3a8bc24e | ||
|
|
00bfeb2dcf | ||
|
|
617c559628 | ||
|
|
6b547f3afe | ||
|
|
a8dca7c918 | ||
|
|
965531485f | ||
|
|
9419bc38de | ||
|
|
1b7e24dc30 | ||
|
|
bf194dae5d | ||
|
|
46a015c624 | ||
|
|
20c554c9b3 | ||
|
|
c5902343bd | ||
|
|
aca7face38 | ||
|
|
5131dca77f | ||
| 869f75830d | |||
|
|
2e2a40ea09 | ||
|
|
38f87fb5c3 | ||
|
|
f6297f0933 | ||
|
|
a7e8dd7d6b | ||
|
|
7779a19903 | ||
|
|
255845cc13 | ||
| 244b25c88a | |||
|
|
f7c96dba4a | ||
|
|
299aab6acf | ||
|
|
3295ca6bd8 | ||
|
|
632542462a | ||
|
|
bd72b21c18 | ||
|
|
31fc5194b2 | ||
|
|
fc1d88a00f | ||
|
|
54e1619d6e | ||
|
|
b4246d2cac | ||
|
|
3539d4862e | ||
|
|
1457013c53 | ||
|
|
c32fdec09f | ||
|
|
3b983dd889 | ||
|
|
71c60563a2 | ||
|
|
fd531c248e | ||
|
|
9735af4d78 | ||
|
|
88aa9157d1 | ||
|
|
2593572392 | ||
|
|
e83e1ca4e3 | ||
|
|
75ed9e4d55 | ||
|
|
3c129ffded | ||
|
|
6136b28af7 | ||
|
|
c11569fb99 | ||
|
|
a23ad70e0e | ||
|
|
e1df83c885 | ||
|
|
ffc456ebac | ||
|
|
4b7ec23db3 | ||
|
|
50e186bc81 | ||
|
|
3823e8e209 | ||
|
|
f08c0300ce | ||
|
|
43f0618f77 | ||
|
|
54c7709964 | ||
|
|
326e4146b2 | ||
|
|
fd5900c252 | ||
|
|
74faba1251 | ||
|
|
70e580c002 | ||
|
|
1ee74172c2 | ||
| 625e1b9d12 | |||
|
|
121dd596d9 | ||
|
|
ea5e199d3b | ||
|
|
e7c28bcb66 | ||
|
|
21207b47a0 | ||
|
|
09d574bae9 | ||
|
|
b68d74effc | ||
|
|
88309f981a | ||
|
|
653432b6a8 | ||
|
|
4d4c231dad | ||
|
|
a195ba6cc0 | ||
|
|
e05b7a5cd5 | ||
|
|
2a51d35e25 | ||
|
|
d7e427daac | ||
|
|
ee37afd1e2 | ||
|
|
d2e261d873 | ||
|
|
2525291ef0 | ||
|
|
124b41acdb | ||
|
|
2ce71a1332 | ||
|
|
a74e326448 | ||
|
|
173cd01731 | ||
|
|
737f4057fb | ||
|
|
62966d085f | ||
|
|
8036d4beaa | ||
|
|
14f17c3601 | ||
|
|
8cfa180fae | ||
|
|
e95469bcbb | ||
|
|
cf71d761dc | ||
|
|
c2b9211bd5 | ||
|
|
7a7405571c | ||
|
|
1270657602 | ||
|
|
6c80b97694 | ||
|
|
e6b087bcae | ||
|
|
a0918c5e98 | ||
|
|
879885a736 | ||
|
|
155258e06e | ||
|
|
06e48df8a3 | ||
|
|
88776e0eee | ||
|
|
9be62a6964 | ||
|
|
c000917cda | ||
|
|
76b87890d8 | ||
|
|
d0796bde4f | ||
|
|
a6e7d5c99b | ||
|
|
b37cc32de0 | ||
|
|
6d724f6d07 | ||
|
|
1cc19c8c6a | ||
|
|
60e2f2baf2 | ||
|
|
b8c684193e | ||
|
|
84b1fdf6c6 | ||
|
|
2181853574 | ||
|
|
281197895f | ||
|
|
d50e8feed9 | ||
|
|
8e104117a4 | ||
|
|
b8b71399e8 | ||
|
|
fb78eea6fc | ||
|
|
a942be9f6f | ||
|
|
34db8682b3 | ||
|
|
61dee21466 | ||
|
|
820f68f147 | ||
|
|
fabc1e1219 | ||
|
|
2fec40e2ec | ||
|
|
95731b800d | ||
|
|
3142d471e1 | ||
|
|
045664107e | ||
|
|
e512466ff0 | ||
|
|
131849e7e8 | ||
| 9a96973b00 | |||
|
|
186896f072 | ||
|
|
78eb483bc2 | ||
|
|
c7033324a9 | ||
|
|
334604a591 | ||
|
|
7905ba80ea | ||
|
|
ccff4685df | ||
|
|
0167f78dca | ||
|
|
282ec08e5e | ||
|
|
5efb7f31df | ||
|
|
bf39ffe903 | ||
|
|
f2c30aa437 | ||
|
|
bf12c90b07 | ||
|
|
615570cf5e | ||
|
|
aff9f4742c | ||
|
|
31a2cc9d76 | ||
|
|
9c6a62d319 | ||
|
|
38c8845b05 | ||
|
|
934d122dd4 | ||
|
|
f8de98f7cd | ||
|
|
ef7f825d97 | ||
|
|
41c1b9623e | ||
|
|
555a987844 | ||
| 1d4ac090d8 | |||
|
|
c1df6dfd05 | ||
|
|
163c569919 | ||
|
|
63a7be115a | ||
|
|
fed31f2a79 | ||
|
|
5d496b3152 | ||
|
|
f5a2b8983d | ||
|
|
8f44800588 | ||
|
|
68c9b6af07 | ||
|
|
8536b4bfcb | ||
|
|
0694c616a2 | ||
|
|
8e456bab9f | ||
|
|
aa663ae386 | ||
|
|
01c8ffd61f | ||
|
|
58c7358cb3 | ||
|
|
1a150bf544 | ||
|
|
98bab0db07 | ||
|
|
b9c65193af | ||
|
|
20403ef8bb | ||
|
|
e26cdd3dab | ||
|
|
2065713e5c | ||
|
|
a9cf841042 | ||
|
|
46466530a5 | ||
|
|
94ed548366 | ||
|
|
1e4c69baa7 | ||
|
|
f04c1a6ab5 | ||
|
|
6393edf40a | ||
|
|
7fd38e88c1 | ||
|
|
ee66c13487 | ||
|
|
250192c603 | ||
|
|
9d181a1cc6 | ||
|
|
07a92c3988 | ||
|
|
e9b0a57490 | ||
|
|
2fca581095 | ||
|
|
53afd90ad4 | ||
|
|
d9ea07515b | ||
|
|
de82920819 | ||
|
|
9a842e4bf2 | ||
| 9cfda05f71 | |||
|
|
1862995aab | ||
|
|
468613c9db | ||
|
|
28642cd047 | ||
|
|
f96f3546c7 | ||
|
|
205066ed12 | ||
|
|
7e8ee46c09 | ||
|
|
d1e2febb6d | ||
|
|
3d0273de45 | ||
|
|
109386dfe8 | ||
|
|
ebddb49041 | ||
|
|
b5f320a2f9 | ||
|
|
7568bd9af5 | ||
|
|
0384c251ff | ||
|
|
b812ad2926 | ||
|
|
fe0b928b39 | ||
|
|
4b1a81e773 | ||
|
|
af2f218192 | ||
|
|
572247dbd8 | ||
|
|
c5a0e6b60c | ||
| 9c2ec9f3af | |||
|
|
d7e8665782 | ||
|
|
7c86c1a185 | ||
|
|
4b03cc60cf | ||
|
|
c356db9f44 | ||
|
|
c53839cefa | ||
|
|
887803cb67 | ||
|
|
f69a08fc63 | ||
|
|
4ddd61cfde | ||
|
|
fe39d137c7 | ||
|
|
ade975891b | ||
|
|
479e56bdd6 | ||
|
|
e5d36de24c | ||
|
|
d824c4e633 | ||
|
|
f499635461 | ||
|
|
e8cf0f37f1 | ||
|
|
12a0c0f690 | ||
|
|
77a8841d25 | ||
|
|
7d8f13b9f7 | ||
|
|
ec177c84b3 | ||
|
|
3809c67bb2 | ||
|
|
dff779e3ad | ||
|
|
ef1c9b9f2b | ||
|
|
90e62db26e | ||
|
|
498154804c | ||
|
|
34dda64610 | ||
|
|
d1c723bc14 | ||
|
|
d477bfd4ee | ||
|
|
6c81f60914 | ||
|
|
aa844ada4e | ||
|
|
9b7a813069 | ||
| baadfa34f1 | |||
|
|
bc09f0992e | ||
|
|
00e2309987 | ||
|
|
a98f82e27b | ||
|
|
c70e6919c2 | ||
|
|
abdf069ce3 | ||
|
|
6be1f7e95a | ||
|
|
a1159ff484 | ||
|
|
0c2caa50cc | ||
|
|
dcbbbf8134 | ||
|
|
05602e29cd | ||
|
|
cd53f7cf8c | ||
|
|
689748843c | ||
|
|
ea07eb6aa3 | ||
|
|
5251ce1b20 | ||
|
|
b3780aab33 | ||
|
|
5bc6d0ef2e | ||
|
|
b92cbf5f09 | ||
|
|
c26f901ba9 | ||
|
|
a590645cde | ||
|
|
49c2f5dea9 | ||
|
|
b408147f48 | ||
|
|
4930fbbba7 | ||
|
|
02dd0b4ed5 | ||
|
|
add945e717 | ||
|
|
259a3c70e3 | ||
|
|
2445e77535 | ||
|
|
d64235eb6e | ||
|
|
54c8cb8c81 | ||
| 758130f5b9 | |||
|
|
803a16cbcd | ||
|
|
0b43c8da11 | ||
|
|
c446904c19 | ||
|
|
363a4378b7 | ||
|
|
f70f528730 | ||
|
|
2334dedba6 | ||
|
|
e9c7dfa992 | ||
|
|
33eaf3e947 | ||
|
|
ce5513b009 | ||
|
|
a98b03e46e | ||
|
|
e4c3ffcd38 | ||
|
|
5e7a3c2e7e | ||
|
|
c020d53e23 | ||
|
|
cb02937714 | ||
|
|
1327e296c2 | ||
|
|
d53521a631 | ||
|
|
5beb14cffe | ||
|
|
7b07e1ee5c | ||
|
|
c02aec557c | ||
|
|
c695d49a86 | ||
|
|
3cd3ba0397 | ||
|
|
829ab5e72d | ||
|
|
4ae8082552 | ||
|
|
2c8d57fbb2 | ||
|
|
e51a28e492 | ||
|
|
72c83badf6 | ||
|
|
fe4f74f631 | ||
|
|
2b335060b0 | ||
|
|
c3fc3ec73d | ||
|
|
be14fc593f | ||
|
|
f2bfa53b61 | ||
|
|
25d07b422d | ||
|
|
8610857015 | ||
|
|
17abce073f | ||
|
|
02d50bd4aa | ||
|
|
67d459b262 | ||
|
|
5ecefb8766 | ||
|
|
52eb0e992d | ||
|
|
19ddc081c1 | ||
|
|
8e91e26cc5 | ||
|
|
c2322f8563 | ||
|
|
4f0683a481 | ||
|
|
b9449de5cf | ||
|
|
c3a9578b82 | ||
|
|
6351dab3e6 | ||
|
|
3ef6399d56 | ||
|
|
f4754bfb5a | ||
|
|
3fb8efc8f2 | ||
|
|
9ae84071eb | ||
|
|
c2b4c2ae0e | ||
|
|
9f1431be17 | ||
|
|
e1c6ae7cf3 | ||
|
|
bb7a9fe7d2 | ||
|
|
d77263d8ed | ||
|
|
fdd92af3ac | ||
|
|
dd009e0bc7 | ||
|
|
170e7d79e7 | ||
|
|
a7635ceb5d | ||
|
|
64fb0be8b2 | ||
|
|
a5a8487132 | ||
|
|
8cf61af551 | ||
|
|
778f000a3b | ||
|
|
623ff4e1ed | ||
|
|
260f00c76d | ||
|
|
0c8a3b5c3e | ||
|
|
e76068a2de | ||
|
|
a12e45c355 | ||
|
|
74b9dd6881 | ||
|
|
edd0823d96 | ||
|
|
4ef4eb4f12 | ||
|
|
862574f381 | ||
|
|
c67ea1ffc1 | ||
|
|
5bd5bcd06a | ||
|
|
a13cd6a177 | ||
|
|
f60c6b25ad | ||
|
|
c6a2664106 | ||
|
|
4ab80abb5e | ||
|
|
f37d097c1c | ||
|
|
191cf671be | ||
|
|
3098315e05 | ||
|
|
39db2e9d66 | ||
|
|
ee1a1306e2 | ||
|
|
db72774458 | ||
|
|
3d727266c3 | ||
|
|
4673e709b2 | ||
|
|
f1a04f780a | ||
|
|
eca5856d99 | ||
|
|
190221c91c | ||
|
|
77d74b5d81 | ||
|
|
0e44752ba1 | ||
|
|
20692e0c29 | ||
|
|
206b4e2a7e | ||
|
|
8fefee2d41 | ||
|
|
cdaa43b396 | ||
|
|
a0eebf20db | ||
|
|
b84f6fc15f | ||
|
|
d0a1bc361a | ||
|
|
d35650b034 | ||
|
|
580eaf29d6 | ||
|
|
a27da0d75b | ||
|
|
26c75a6828 | ||
|
|
c32828bb13 | ||
|
|
18b37c980a | ||
|
|
64ac4610de | ||
|
|
dea34733a4 | ||
|
|
0e72c0d372 | ||
|
|
88c8da143f | ||
|
|
367f84b0ec | ||
|
|
1a3ef7e497 | ||
|
|
c19012d4cd | ||
|
|
b502631d10 | ||
|
|
6728e5d791 | ||
|
|
101b53b541 | ||
|
|
11c492fdd0 | ||
|
|
792d4e9a23 | ||
|
|
c59e9d228e | ||
|
|
d8848df14f | ||
|
|
4a2729b780 | ||
|
|
7c174a1a25 | ||
|
|
f0e69b4a51 | ||
|
|
4a915b1ed5 | ||
|
|
cbf5a5b5d3 | ||
|
|
41b52d70be | ||
|
|
129696cdbe | ||
|
|
8cc3ab213d | ||
|
|
9bf966af37 | ||
|
|
a76a6bf692 | ||
|
|
6a7a0c8f50 | ||
|
|
f5bc261944 | ||
|
|
8a304bdf7c | ||
|
|
124e86a6d2 | ||
|
|
96df9e0a20 | ||
| 9228180b1e | |||
|
|
a04d2a433c | ||
|
|
ef35ea72cf | ||
|
|
8804b6dcd4 | ||
|
|
86b8388889 | ||
|
|
812c48dde4 | ||
|
|
f0f1c94afa | ||
|
|
75b312ded1 | ||
| b2f79e3a6e | |||
|
|
e65b0ba654 | ||
|
|
d3dd403dc7 | ||
|
|
7f4c2c6a25 | ||
| 4622210cfb | |||
|
|
cb1b3a28ab | ||
|
|
f7d8735b6b | ||
|
|
fc42ab9b46 | ||
|
|
7f17777a4b | ||
|
|
bcdb27416c | ||
|
|
15c6396d42 | ||
|
|
2c19345e58 | ||
|
|
69a7dd86ec | ||
| 9317206586 | |||
| 7027b9b601 | |||
| fc3598f116 | |||
| 90dac326c1 | |||
| a299827554 | |||
| a39e61a3e0 | |||
| 584571248f | |||
|
|
fdcafb83e3 | ||
|
|
b8ead3b511 | ||
|
|
ffff664918 | ||
|
|
bf984ecb9b | ||
|
|
f1e238a9af | ||
|
|
5290a85afd | ||
|
|
b5157dd9cb | ||
|
|
94812d17c8 | ||
|
|
7681090c12 | ||
|
|
866490c41f | ||
|
|
0662fc4d42 | ||
|
|
078d612b9e | ||
|
|
26025f79ce | ||
|
|
1c307bc1be | ||
|
|
7abddbd752 | ||
|
|
51c9f7270c | ||
|
|
b896670e85 | ||
|
|
69dd0c40bb | ||
|
|
c374c773ad | ||
|
|
2fd7888a51 | ||
|
|
d19915ea44 | ||
|
|
549e37d218 | ||
|
|
7b48a9f671 | ||
|
|
344db835e4 | ||
|
|
04353acccf | ||
|
|
c33f0b7d8d | ||
|
|
fd51fee424 | ||
|
|
c8b44816fe | ||
|
|
6e88389fb8 | ||
|
|
298447e22d | ||
|
|
a3c7de8a50 | ||
|
|
264f305d94 | ||
|
|
f8ec08a928 | ||
|
|
f09e6c183e | ||
|
|
3791ed86a3 | ||
|
|
7f772693eb | ||
|
|
5771f1ea14 | ||
|
|
0f4db1ed0d | ||
|
|
4b35626aec | ||
|
|
846588ee81 | ||
|
|
4f92b12a6a | ||
|
|
4b4b20f8a9 | ||
|
|
e26fe9bddd | ||
|
|
972be2df04 | ||
|
|
374cb6a7f8 | ||
|
|
923d6300ad | ||
|
|
baa4edc6ca | ||
|
|
9875311bcc | ||
|
|
c3a453512a | ||
|
|
e413ed8e1d | ||
|
|
858f411447 | ||
|
|
19c8cea8e5 | ||
|
|
1ae10b1487 | ||
|
|
35cde9f8d7 | ||
|
|
d4d2840f5d | ||
|
|
119ec47072 | ||
|
|
ceb305a780 | ||
|
|
1dc2a75cb6 | ||
|
|
8d7b716ea7 | ||
|
|
034af70a65 | ||
|
|
162c213e7b | ||
|
|
6fde7d8a51 | ||
|
|
e4abef5768 | ||
|
|
3922b531a8 | ||
|
|
0d1438a731 | ||
|
|
7eb66d3e09 | ||
|
|
c7a600063d | ||
|
|
5b654ce9fb | ||
|
|
98e9a881c0 | ||
|
|
f420f7c177 | ||
|
|
50954a4b6a | ||
|
|
567310e698 | ||
|
|
f90b710c9b | ||
|
|
bdaec3f934 | ||
|
|
8198fd9c58 | ||
|
|
358a10e3cc | ||
|
|
7b935e0d40 | ||
|
|
7034c3cc47 | ||
|
|
e30eadb4de | ||
|
|
3e3f4a167a | ||
|
|
c98528f8d3 | ||
|
|
75e5f885e5 | ||
|
|
40b9e68e02 | ||
|
|
e7491920fd | ||
|
|
9904aa5538 | ||
|
|
41b89aef8c | ||
|
|
3925c137a4 | ||
|
|
97fa42c82b | ||
|
|
ccabaac5a0 | ||
|
|
80f7852941 | ||
|
|
6243831dfb | ||
|
|
4f9abb52a4 | ||
|
|
7bab8780ad | ||
|
|
d0dc270eec | ||
|
|
cd9402075a | ||
|
|
b1f3bdfcbd | ||
|
|
541a2dbc88 | ||
|
|
d1e28417d5 | ||
|
|
9410a55679 | ||
|
|
25ceefbd89 | ||
|
|
a37c4bb59e | ||
|
|
ee1f8a0494 | ||
|
|
2c5459a1b7 | ||
|
|
b561c386c3 | ||
|
|
a374dd0359 | ||
|
|
aba4f4e0e2 | ||
|
|
210c94d82f | ||
|
|
c410ba4d42 | ||
|
|
f3738fe164 | ||
|
|
04a08fe6a5 | ||
|
|
69d33ec170 | ||
|
|
40a4225ed8 | ||
|
|
801622ce19 | ||
|
|
67750a30ba | ||
|
|
2f25b6a650 | ||
|
|
5a3bd329d6 | ||
|
|
8b4bf2bb8d | ||
|
|
2a515058be | ||
|
|
3785f762fc | ||
|
|
5cee9f183b | ||
|
|
958ec294b2 | ||
|
|
3a781fd719 | ||
|
|
f4a2e7efe2 | ||
|
|
027365503f | ||
|
|
e31d59ebc8 | ||
|
|
11178e14ab | ||
|
|
0bcbd0015f | ||
|
|
271bd5d3ba | ||
|
|
74d252a68f | ||
|
|
4b928b466a | ||
|
|
10b4d0c8ad | ||
|
|
433dd92196 | ||
|
|
78d284881c | ||
|
|
a36b726bde | ||
|
|
83629b9991 | ||
|
|
405c66e864 | ||
|
|
e5df84a9ed | ||
|
|
614a977259 | ||
|
|
f1651abdac | ||
|
|
05a06048fc | ||
|
|
c599bc9bff | ||
|
|
54ded4527a | ||
|
|
4f433cd601 | ||
|
|
accecb9863 | ||
|
|
079588cac5 | ||
|
|
1d10ee71bf | ||
|
|
0520cbdccb | ||
|
|
3d3270c1b2 | ||
|
|
b60a26d40b | ||
|
|
36fcdce886 | ||
|
|
b760388bbf | ||
|
|
bb18524cce | ||
|
|
05eaa0f0d7 | ||
|
|
d4a1dbd4a9 | ||
|
|
0e9bef3429 | ||
|
|
34238dc119 | ||
|
|
18a40caa48 | ||
|
|
1980f1b2ba | ||
|
|
ec0c13afda | ||
|
|
ed41b3cefa | ||
|
|
80a924edfa | ||
|
|
98f9518bf2 | ||
|
|
1de47610f4 | ||
|
|
25ba7712f7 | ||
|
|
a6b534d760 | ||
|
|
494b191d55 | ||
|
|
450bfa7a75 | ||
|
|
a52ac1375a | ||
|
|
4990713e9e | ||
|
|
c022c4cc6d | ||
|
|
6257dec0a7 | ||
|
|
ea9d49b9d8 | ||
|
|
42c7bfcf8a | ||
|
|
e67d1bfeb8 | ||
|
|
e2f444cfdf | ||
|
|
03b85df4eb | ||
|
|
7db5c2f225 | ||
|
|
603ce231d0 | ||
|
|
940b5eaad1 | ||
|
|
fdd946c02c | ||
|
|
81e5b57d74 | ||
|
|
b568705eec | ||
|
|
fe42eb7a1a | ||
|
|
df7b0a6d97 | ||
|
|
fcf598e797 | ||
|
|
d9cb12f6e3 | ||
|
|
0f23729253 | ||
|
|
3def429290 | ||
|
|
803ea0d7a0 | ||
|
|
9b014876cd | ||
|
|
9ccf85eaa8 | ||
|
|
93fa53c3e8 | ||
|
|
eea3e1f0b2 | ||
|
|
e6e22ea976 | ||
|
|
80c2000f87 | ||
|
|
15a0a129c8 | ||
|
|
51bd04b541 | ||
|
|
18ba7f60c1 | ||
|
|
5c3e00d70a | ||
|
|
6c4c77971e | ||
|
|
67adef8f6c | ||
|
|
ed60e16974 | ||
|
|
47c11ae83d | ||
|
|
8173b1bfbe | ||
|
|
93400ec8a1 | ||
|
|
0d85a798e5 | ||
|
|
d4d534925f | ||
|
|
a1ba7ee786 | ||
|
|
756cd4a4b8 | ||
|
|
1b186fcff3 | ||
|
|
165da9b447 | ||
|
|
aea10ed383 | ||
|
|
8fccb31436 | ||
|
|
89bb88e4f5 | ||
|
|
a58efa70bc | ||
|
|
fe1fecc5da | ||
|
|
87612582ff | ||
|
|
c3a53cffbc | ||
|
|
aeea83703b | ||
|
|
27c8f13fc9 | ||
|
|
c6ddae70f7 | ||
|
|
e4ecd03e3f | ||
|
|
a6dc5c963c | ||
|
|
989e6a9a7e | ||
|
|
c28048d20f | ||
|
|
a24e72f972 | ||
|
|
a29aa31e93 | ||
|
|
8546139997 | ||
|
|
a61586947e | ||
|
|
5e4645b082 | ||
|
|
f9f0a8fd67 | ||
|
|
637a2eeb66 | ||
|
|
13caef2de0 | ||
|
|
61c6d43231 | ||
|
|
a04f6e0165 | ||
|
|
3f494e359d | ||
|
|
8a06f70379 | ||
|
|
2290152743 | ||
|
|
3b657a26a6 | ||
|
|
ff5084479b | ||
|
|
97f4a3f4eb | ||
|
|
1ca1732d32 | ||
|
|
accd2308f1 | ||
|
|
10eec2fe17 | ||
|
|
d69cd759cb | ||
|
|
f261a8aca5 | ||
|
|
bdf64d660b | ||
|
|
2fd30ee095 | ||
|
|
9bc6f1797e | ||
|
|
32e63fe1b8 | ||
|
|
1c074cc8cc | ||
|
|
ebf6228f21 | ||
|
|
4a1db96db8 | ||
|
|
16ee4636bc | ||
|
|
6831b37b43 | ||
|
|
4d16f26ba4 | ||
|
|
4a7bc73e03 | ||
|
|
caf583ec4b | ||
|
|
e20880da21 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -45,6 +45,7 @@ core
|
||||
/m4/gettext.m4
|
||||
/m4/glibc2.m4
|
||||
/m4/glibc21.m4
|
||||
/m4/host-cpu-c-abi.m4
|
||||
/m4/iconv.m4
|
||||
/m4/intdiv0.m4
|
||||
/m4/intl.m4
|
||||
|
||||
35
AUTHORS
35
AUTHORS
@@ -8,19 +8,20 @@ Chris Allegretta <chrisa@asty.org>
|
||||
Benno Schulenberg <bensberg@telfort.nl>
|
||||
* An array of small bug fixes, the cut-word and block-jump
|
||||
routines, text selection by holding Shift, macro recording
|
||||
and replay, plus some key bindings. Current maintainer.
|
||||
and replay, extra key bindings, the --indicator, --minibar,
|
||||
and --zero options, and braced functions in string binds.
|
||||
Current maintainer.
|
||||
|
||||
David Lawrence Ramsey <pooka109@gmail.com>
|
||||
* Former stable series maintainer. Multiple buffer support,
|
||||
operating dir (-o) option, bug fixes for display routines,
|
||||
wrapping code, spelling fixes, constantshow mode, parts of
|
||||
UTF-8 support, softwrap overhaul, undoable (un)indentations,
|
||||
undoable justifications, justifiable regions, and numerous
|
||||
other fixes.
|
||||
* Multiple-buffer support, operating-dir option (-o), bug fixes
|
||||
for display routines, wrapping code, spelling fixes, parts of
|
||||
UTF-8 support, softwrap overhaul, constantshow mode, undoable
|
||||
indentations, undoable justifications, justifiable regions,
|
||||
and numerous other fixes. Former stable-series maintainer.
|
||||
|
||||
Jordi Mallach <jordi@gnu.org>
|
||||
* Debian package maintainer, fellow bug squasher.
|
||||
* Internationalization support head, ca.po maintainer.
|
||||
* Debian package maintainer, fellow bug squasher, translator
|
||||
for Catalan. Former head of internationalization support.
|
||||
|
||||
Adam Rogoyski <rogoyski@cs.utexas.edu>
|
||||
* New write_file() function, read_file() optimization, mouse
|
||||
@@ -33,9 +34,9 @@ Robert Siemborski <rjs3@andrew.cmu.edu>
|
||||
new edit display routines.
|
||||
|
||||
Rocco Corsi <rocco.corsi@sympatico.ca>
|
||||
* Internal spelling code, many optimizations and bug fixes for
|
||||
findnextstr() and search-related functions, various display
|
||||
and file handling fixes.
|
||||
* Internal spelling code, many optimizations and bug fixes
|
||||
for findnextstr() and search-related functions, various
|
||||
display and file-handling fixes.
|
||||
|
||||
David Benbennick <dbenbenn@math.cornell.edu>
|
||||
* Wrap and justify bugfixes/enhancements, new color syntax
|
||||
@@ -43,11 +44,11 @@ David Benbennick <dbenbenn@math.cornell.edu>
|
||||
miscellaneous fixes.
|
||||
|
||||
Mike Frysinger <vapier@gentoo.org>
|
||||
* Gentoo package maintainer. Whitespace display mode,
|
||||
--enable-utf8/--disable-utf8 configure options for ncurses,
|
||||
many new color regexes and improvements to existing color
|
||||
regexes in syntax/*.nanorc, the move from svn to git, the
|
||||
conversion to gnulib, and miscellaneous bug fixes.
|
||||
* Whitespace display mode, --enable-utf8/--disable-utf8 configure
|
||||
options for ncurses, many new color regexes and improvements to
|
||||
existing ones in syntax/*.nanorc, the move from svn to git, the
|
||||
conversion to gnulib, and miscellaneous bug fixes. Former
|
||||
Gentoo package maintainer.
|
||||
|
||||
Mark Majeres <mark@engine12.com>
|
||||
* A functional undo/redo system, and coloring nano's interface.
|
||||
|
||||
@@ -8246,7 +8246,7 @@ nano-0.7.7 - 2000.01.19
|
||||
- Added check for keystroke key sequence 407 or NANO_CONTROL_Z
|
||||
in main while loop because suspend mode was broken. This should
|
||||
fix it, at least for now.
|
||||
- Added long option support (By popular harassment ;-) - Added
|
||||
- Added long option support (by popular harassment ;-) : added
|
||||
#include for getopt.h, changed getopt() to getopt_long().
|
||||
Options added so far: --version (-V), --nowrap (-w), --suspend
|
||||
(-z), --help (-h), --nohelp (-x).
|
||||
@@ -8258,15 +8258,15 @@ nano 0.7.6 - 2000.01.15
|
||||
main(): Bound CONTROL_H to backspace (oops).
|
||||
Added more Alt-[-key combinations, for page up & down.
|
||||
read_bytes(): New function. (Adam Rogoyski)
|
||||
read_file(): Optimizations - malloc()s *buf a little at a time rather
|
||||
than one huge buffer, and replaced the strcat at the end
|
||||
with an index variable. Added call to read_bytes().
|
||||
read_file(): Optimizations -- malloc()s *buf a little at a time
|
||||
rather than one huge buffer, and replaced the strcat() at
|
||||
the end with an index variable. Added call to read_bytes().
|
||||
do_next_word(): New function, binding is Ctrl-Space (0). (Chris)
|
||||
- winio.c:
|
||||
bottombars(): Fixed non-expanding shortcut keys at bottom of screen.
|
||||
(formula is extra space needed = COLS / 6 - 13).
|
||||
actual_x() & strlenpt():
|
||||
Added bug#9 fix - when tabs % 8 == 0, we should only
|
||||
Added fix for bug #9 -- when tabs % 8 == 0, we should only
|
||||
increment tabs by 1.
|
||||
titlebar(): Fixed overrun in titlebar on very long filenames.
|
||||
|
||||
|
||||
23
IMPROVEMENTS
23
IMPROVEMENTS
@@ -1,6 +1,29 @@
|
||||
Improvements in GNU nano
|
||||
========================
|
||||
|
||||
Since 9.0:
|
||||
- With M-< and M-> the viewport can be scrolled sideways.
|
||||
- When the cursor nears the edge, all lines are scrolled sideways.
|
||||
- M-Left, M-Right, M-Up, and M-Down have become rebindable.
|
||||
- Immediately stopping a recording retains the existing macro.
|
||||
- Clicking in the scrollbar crudely navigates in the buffer.
|
||||
|
||||
Since 8.0:
|
||||
- To accommodate newcomers, ^F now starts a forward search.
|
||||
- Option --modernbindings makes ^Q quit, ^X cut, ^C copy, ^V paste,
|
||||
^Z undo, ^Y redo, ^O open a file, and ^G find again, among others.
|
||||
- M-Home/M-End put the cursor on the first/last row in the viewport.
|
||||
- With `nano filename:number` the given file will be opened with the
|
||||
cursor on the given line number (when 'set colonparsing' is used).
|
||||
- Option --listsyntaxes lists the names of available syntaxes.
|
||||
- Anchors are saved and restored (when --positionlog is active).
|
||||
- Key combos ^O^Q and ^X^Q cause an exit status of 2.
|
||||
|
||||
Since 7.0:
|
||||
- String binds may contain bindable function names between braces.
|
||||
- Word completion looks for candidates in all open buffers.
|
||||
- Unicode codes can be entered without leading zeroes.
|
||||
|
||||
Since 6.0:
|
||||
- Option --zero hides the interface and uses the whole terminal for editing.
|
||||
- Colors can be given also in #rgb hexadecimal, to select the nearest color
|
||||
|
||||
228
NEWS
228
NEWS
@@ -1,3 +1,158 @@
|
||||
2026.07.31 - GNU nano 9.2 "Alquézar"
|
||||
• Nano refuses to start when standard output is not a terminal.
|
||||
• Options --newbuffer and 'set newbuffer' were added as better
|
||||
synonyms of --multibuffer and 'set multibuffer'.
|
||||
• Legacy keystroke pairs ^W^T and ^/^T are recognized again.
|
||||
|
||||
2026.06.23 - GNU nano 9.1 "met een hongerig paard aan ons been"
|
||||
• When searching, the viewport is placed snug left where possible.
|
||||
• The ability to read and write files in old Mac format was removed
|
||||
(that is: files that use a lone carriage return as line ending).
|
||||
• The ^T toggle between WhereIs and GotoLine has been dropped.
|
||||
• When --backup is active, in some situations no backup was made,
|
||||
or it had a wrong timestamp. Both issues are fixed now.
|
||||
• When nano crashes or is killed, any .save file is not chmodded
|
||||
to the permissions of the base file, nor chowned to its owner.
|
||||
• M-Ins and M-Del have become rebindable.
|
||||
|
||||
2026.04.08 - GNU nano 9.0 "Le bonheur est dans le pré"
|
||||
• When the cursor almost goes offscreen to the right, all lines are
|
||||
now scrolled sideways together, by just the amount needed to keep
|
||||
the cursor in view. Use --solosidescroll or 'set solosidescroll'
|
||||
to get back the old, jerky, single-line horizontal scrolling.
|
||||
• The viewport can be scrolled sideways (in steps of one tabsize)
|
||||
with M-< and M->. See `man nanorc` if M-< and M-> should switch
|
||||
between buffers (as they did earlier).
|
||||
• M-Left, M-Right, M-Up, and M-Down have become rebindable.
|
||||
• Stopping the recording of a macro immediately after starting it
|
||||
cancels the recording and leaves an existing macro in place.
|
||||
• Feature toggles no longer break a chain of ^K cuts or M-6 copies,
|
||||
except the M-K cut-from-cursor toggle.
|
||||
• With --mouse and --indicator, one can click in the scrollbar area
|
||||
to roughly navigate within the buffer.
|
||||
|
||||
|
||||
2026.02.04 - GNU nano 8.7.1 "Tende Samnug"
|
||||
• A build failure when compiling against glibc-2.43 is fixed.
|
||||
|
||||
2025.11.12 - GNU nano 8.7 "Blue Highways"
|
||||
• At the Execute prompt, preceding the command with two pipe symbols
|
||||
allows implementing a copy-to-clipboard feature in your nanorc (on
|
||||
terminals that support OSC 52). See the doc/sample.nanorc file.
|
||||
|
||||
2025.08.21 - GNU nano 8.6 "reason alone was a defective compass"
|
||||
• The GotoLine menu accepts the prefixes ++ and -- for jumping
|
||||
a number of lines forward or backward.
|
||||
• Anchors are not forgotten when a line number is given on the
|
||||
command line.
|
||||
|
||||
2025.06.12 - GNU nano 8.5 "Sigourney"
|
||||
• Anchors are now saved when a file is closed, and restored when
|
||||
the file is reopened -- if and when --positionlog is active.
|
||||
• Nano exits with an error status upon keystrokes ^O^Q and ^X^Q.
|
||||
• Keystroke ^L just centers the cursor, while M-% cycles it.
|
||||
• Option --whitespace is accepted, but left undocumented.
|
||||
• Syntax coloring now works correctly in more locales.
|
||||
|
||||
2025.04.02 - GNU nano 8.4 "Five Miles Out"
|
||||
• Bracketed pastes over a slow connection are more reliable.
|
||||
• Tabs in an external paste at a prompt are not dropped.
|
||||
• Feedback occurs when the cursor sits on a Byte Order Mark.
|
||||
• The Execute prompt is more forgiving of a typo.
|
||||
|
||||
2024.12.21 - GNU nano 8.3 "like mice in the dream of a tabby cat"
|
||||
• A build failure with gcc-15 is fixed.
|
||||
• Several translations were updated.
|
||||
|
||||
2024.09.05 - GNU nano 8.2 "Charlotte will climb walls!"
|
||||
• At a Yes-No prompt, beside Y and the localized initial for "Yes",
|
||||
also ^Y is accepted. Similarly, ^N for "No", and ^A for "All".
|
||||
• A text-highlighting bug with Alt+Home/Alt+End is fixed.
|
||||
|
||||
2024.07.12 - GNU nano 8.1 "de dag van de bitterkoekjespudding"
|
||||
• The idiom `nano filename:linenumber` is understood only when the
|
||||
option --colonparsing (or 'set colonparsing') is used.
|
||||
• Modern bindings are *not* activated when nano's invocation name
|
||||
starts with "e", as it jars with Debian's alternatives system.
|
||||
• New bindable function 'cycle' first centers the current row,
|
||||
then moves it to the top of the viewport, then to the bottom.
|
||||
It is bound by default to ^L.
|
||||
• Option --listsyntaxes/-z lists the names of available syntaxes.
|
||||
|
||||
2024.05.01 - GNU nano 8.0 "Grus grus"
|
||||
• By default ^F is bound to starting a forward search, and ^B to
|
||||
starting a backward search, while M-F and M-B repeat the search
|
||||
in the corresponding direction. (See the documentation if you
|
||||
want the old bindings back.)
|
||||
• Command-line option --modernbindings (-/) makes ^Q quit, ^X cut,
|
||||
^C copy, ^V paste, ^Z undo, ^Y redo, ^O open a file, ^W write a
|
||||
file, ^R replace, ^G find again, ^D find again backwards, ^A set
|
||||
the mark, ^T jump to a line, ^P show the position, and ^E execute.
|
||||
• Above modern bindings are activated also when the name of nano's
|
||||
executable (or a symlink to it) starts with the letter "e".
|
||||
• To open a file at a certain line number, one can now use also
|
||||
`nano filename:number`, besides `nano +number filename`.
|
||||
• <Alt+Home> and <Alt+End> put the cursor on the first and last
|
||||
row in the viewport, while retaining the horizontal position.
|
||||
• When the three digits in an #RGB color code are all the same,
|
||||
the code is mapped to the xterm grey scale, giving access to
|
||||
fourteen levels of grey instead of just four.
|
||||
• For easier access, M-" is bound to placing/removing an anchor,
|
||||
and M-' to jumping to the next anchor.
|
||||
• Whenever an error occurs, the keystroke buffer is cleared, thus
|
||||
stopping the execution of a macro or a string bind.
|
||||
• The mousewheel scrolls the viewport instead of moving the cursor.
|
||||
|
||||
|
||||
2023.01.18 - GNU nano 7.2 "Boer doe mij 't hekke lös!"
|
||||
• <Shift+Insert> is prevented from pasting in view mode.
|
||||
|
||||
2022.12.14 - GNU nano 7.1 "And the devices shall be made of wood"
|
||||
• When --autoindent and --breaklonglines are combined, pressing
|
||||
<Enter> at a specific position no longer eats characters.
|
||||
|
||||
2022.11.15 - GNU nano 7.0 "Una existencia simple bajo el sol"
|
||||
• String binds may contain bindable function names between braces.
|
||||
For example, to move the current line down to after the next one:
|
||||
bind ^D "{cut}{down}{paste}{up}" main. Of course, braced function
|
||||
names may be mixed with literal text. If an existing string bind
|
||||
contains a literal {, replace it with {{}.
|
||||
• Unicode codes can be entered (via M-V) without leading zeroes,
|
||||
by finishing short codes with <Space> or <Enter>.
|
||||
• Word completion (^]) looks for candidates in all open buffers.
|
||||
• No regular expression matches the final empty line any more.
|
||||
|
||||
|
||||
2022.08.02 - GNU nano 6.4 "Regentag Dunkelbunt Hundertwasser"
|
||||
• The file browser does not crash when moving up to the root folder.
|
||||
• Softwrapping very long lines is done more efficiently.
|
||||
• Invoking the formatter does not blink the screen.
|
||||
|
||||
2022.04.28 - GNU nano 6.3 "Wat zullen we drinken? Wat een dorst!"
|
||||
• For multiline regexes, text is now colored as soon as a start match
|
||||
is found, also when there is no end match at all.
|
||||
• The colorizing of any line is stopped after two thousand bytes,
|
||||
to avoid frustrating delays.
|
||||
• When environment variable NO_COLOR is set, the two default colors
|
||||
(yellow for the spotlight, red for error messages) are suppressed
|
||||
when no interface colors are specified in a nanorc file.
|
||||
• Full justification and piping the whole buffer through a command
|
||||
now keep the cursor at the same line number.
|
||||
• Utility 'xsel' can be used to copy a marked region to the system's
|
||||
clipboard. See doc/sample.nanorc for an example.
|
||||
|
||||
2022.02.18 - GNU nano 6.2 "Kamperfoelie"
|
||||
• The file browser clears the prompt bar also when using --minibar.
|
||||
• Linting now works also with a newer 'pyflakes'.
|
||||
|
||||
2022.02.09 - GNU nano 6.1 "Rețelele de socializare sunt ca un frigider"
|
||||
• The behavior of ^K at a prompt has been enhanced: when there is some
|
||||
text after the cursor, just this text is erased. In the most common
|
||||
situation, when the cursor is at the end of the answer, the behavior
|
||||
is as before: the whole answer is erased.
|
||||
• At a prompt, M-6 copies the current answer into the cutbuffer.
|
||||
• Large external pastes into nano are handled more quickly.
|
||||
|
||||
2021.12.15 - GNU nano 6.0 "Humor heeft ook zijn leuke kanten"
|
||||
• Option --zero hides the title bar, status bar and help lines, and
|
||||
uses all rows of the terminal as editing area. The title bar and
|
||||
@@ -752,22 +907,22 @@
|
||||
the undo implementation and the default syntax config are
|
||||
also included. As always, Share and Enjoy!
|
||||
|
||||
2014.05.28 - GNU nano 2.3.3 is in its right place. This release contains
|
||||
many many improvements to the core system, including
|
||||
substantial improvements to the undo/redo code, UTF-8
|
||||
handling, the configure script, and display of shortcuts
|
||||
on very wide terminals. New features include the
|
||||
ability to write to named pipes (--noread), as well as
|
||||
linter support (see the nanorc man page for details). Also
|
||||
included are much improved syntax highlighting code, and
|
||||
configurations for JSON, texinfo, Go, and a default syntax
|
||||
for catch-all highlighting. Finally, nano now has the
|
||||
ability to set the color of the title bar, status bar, and
|
||||
shortcut keys (e.g. "^X") and their descriptions. Again
|
||||
see the nanorc page for details. There's much more, too
|
||||
much to include here, but please keep those reports and
|
||||
general feedback coming! Thank you for helping us help
|
||||
you help us all.
|
||||
2014.05.28 - GNU nano 2.3.3 is in its right place. This release
|
||||
contains many many improvements to the core system,
|
||||
including substantial improvements to the undo/redo code,
|
||||
UTF-8 handling, the configure script, and display of
|
||||
shortcuts on very wide terminals. New features include
|
||||
the ability to write to named pipes (--noread), as well
|
||||
as linter support (see the nanorc man page for details).
|
||||
Also included are much improved syntax highlighting code,
|
||||
and configurations for JSON, texinfo, Go, and a default
|
||||
syntax for catch-all highlighting. Finally, nano now has
|
||||
the ability to set the color of the title bar, status bar,
|
||||
and shortcut keys (e.g. "^X") and their descriptions.
|
||||
Again see the nanorc page for details. There's much more,
|
||||
too much to include here, but please keep those reports
|
||||
and general feedback coming! Thank you for helping us
|
||||
help you help us all.
|
||||
|
||||
2013.03.22 - GNU nano 2.3.2 "Annoy your coworkers for fun and profit" is
|
||||
released. This release introduces vim-style file locking
|
||||
@@ -838,26 +993,23 @@
|
||||
fixes for that version are still forthcoming.
|
||||
|
||||
2010.02.11 - GNU nano 2.2.3 "fumbling toward stability" is released.
|
||||
This release contains a fix for only one bug, but a
|
||||
rather irritating one: when paging up/down with smooth
|
||||
scrolling, the cursor position was not being preserved
|
||||
due to a bug in 2.2.2. With such a targeted fix
|
||||
like this what could POSSIBLY go WRONG? Hahaha.
|
||||
Enjoy and if you find new bugs, as always please
|
||||
use Savannah's bug tracker.
|
||||
This release contains a fix for only one bug, but a rather
|
||||
irritating one: when paging up/down with smooth scrolling,
|
||||
the cursor position was not being preserved due to a bug
|
||||
in 2.2.2. With such a targeted fix like this what could
|
||||
POSSIBLY go WRONG? Hahaha. Enjoy, and if you find new
|
||||
bugs, as always please use Savannah's bug tracker:
|
||||
https://savannah.gnu.org/bugs/?func=additem&group=nano
|
||||
|
||||
2010.01.17 - GNU nano 2.2.2 is released for you, you, you. This
|
||||
release includes fixes for: crashes when writing
|
||||
backup files in certain conditions, improper
|
||||
screen centering when moving up/down in various
|
||||
combination of smooth scrolling and soft wrapping modes,
|
||||
a search crash on the armel arch, and issues with
|
||||
lots of keybinding customizations causing crashing
|
||||
particularly on FreeBSD. Also included are better
|
||||
help menu entries for forward/back in the file browser,
|
||||
some man page tweaks and one assert fix. As always,
|
||||
share and enjoy!
|
||||
2010.01.17 - GNU nano 2.2.2 is released for you, you, you. This release
|
||||
includes fixes for: crashes when writing backup files in
|
||||
certain conditions, improper screen centering when moving
|
||||
up/down in various combinations of smooth scrolling and soft
|
||||
wrapping modes, a search crash on the armel arch, and issues
|
||||
with lots of keybinding customizations causing crashing
|
||||
particularly on FreeBSD. Also included are better help menu
|
||||
entries for forward/back in the file browser, some man page
|
||||
tweaks and one assert fix. As always, share and enjoy!
|
||||
|
||||
2009.12.12 - GNU nano 2.2.1 "DLR strikes back" is open for business.
|
||||
This release fixes many bugs, including: missing
|
||||
@@ -906,13 +1058,13 @@
|
||||
the command line will now override any related .nanorc
|
||||
entries. Speak now or forever hold your bugs!
|
||||
|
||||
2009.11.15 - GNU nano 2.1.99pre1 "take a bow" is out there, man, it's
|
||||
out there all right. This release contains mainly
|
||||
2009.11.15 - GNU nano 2.1.99pre1 "take a bow" is out there, man,
|
||||
it's out there all right. This release contains mainly
|
||||
bugfixes, underscoring that we are preparing for the
|
||||
next stable series release. Included are many fixes
|
||||
for the new soft wrapping code, compiler warning tweaks,
|
||||
and the modification time warning no longer triggers
|
||||
when saving a file as a new name. Also include are
|
||||
when saving a file with a new name. Also included are
|
||||
some fixes for various nanorc options, and there are
|
||||
surely more bugs to find before we call the code base
|
||||
stable, so please keep those reports coming!
|
||||
@@ -1542,7 +1694,7 @@
|
||||
allow multiple syntax highlighting types, and a new -Y,
|
||||
--syntax flag to set a specific one if there's no
|
||||
filename regex to match it against (i.e. w/mutt). The
|
||||
^space and M-space keys will now show up in the help
|
||||
^Space and M-Space keys will now show up in the help
|
||||
menu, which itself has been tweaked a bit, and many more
|
||||
configure options should now cooperate (like the odd
|
||||
pairing of --enable-tiny and --enable-multibuffer). The
|
||||
|
||||
12
README
12
README
@@ -15,7 +15,7 @@ Appearance
|
||||
In rough ASCII graphics, this is what nano's screen looks like:
|
||||
|
||||
____________________________________________________________________
|
||||
| GNU nano 6.0 filename Modified |
|
||||
| GNU nano 9.2 filename Modified |
|
||||
--------------------------------------------------------------------
|
||||
| This is the text window, displaying the contents of a 'buffer', |
|
||||
| the contents of the file you are editing. |
|
||||
@@ -29,7 +29,7 @@ Appearance
|
||||
| |
|
||||
--------------------------------------------------------------------
|
||||
| [ Some status message ] |
|
||||
|^G Help ^O Write Out ^W Where Is ^K Cut ^T Execute |
|
||||
|^G Help ^O Write Out ^F Where Is ^K Cut ^T Execute |
|
||||
|^X Exit ^R Read File ^\ Replace ^U Paste ^J Justify |
|
||||
--------------------------------------------------------------------
|
||||
|
||||
@@ -52,8 +52,8 @@ Origin
|
||||
Nowadays, nano wants to be a generally useful editor with sensible
|
||||
defaults (linewise scrolling, no automatic line breaking).
|
||||
|
||||
The nano editor is an official GNU package. For more information on
|
||||
GNU and the Free Software Foundation, please see https://www.gnu.org/.
|
||||
The nano editor is an official GNU package. For more information
|
||||
on GNU and the Free Software Foundation, see https://www.gnu.org/.
|
||||
|
||||
License
|
||||
|
||||
@@ -81,7 +81,9 @@ How to compile and install nano
|
||||
You will need the header files of ncurses installed for ./configure
|
||||
to succeed -- get them from libncurses-dev (Debian) or ncurses-devel
|
||||
(Fedora) or a similarly named package. Use --prefix with ./configure
|
||||
to override the default installation directory of /usr/local.
|
||||
to override the default installation directory of /usr/local. And
|
||||
use --sysconfdir=/etc when you want your self-compiled nano to read
|
||||
the /etc/nanorc file.
|
||||
|
||||
After installation you may want to copy the doc/sample.nanorc file
|
||||
to your home directory, rename it to ".nanorc", and then edit it
|
||||
|
||||
@@ -8,19 +8,18 @@ building this needs a bit more care than the official tarballs.
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
To successfully compile GNU nano from git, you'll need the following
|
||||
packages:
|
||||
To successfully compile GNU nano from git, you'll need the following:
|
||||
|
||||
- autoconf (version >= 2.69)
|
||||
- automake (version >= 1.14)
|
||||
- autopoint (version >= 0.18.3)
|
||||
- gcc (version >= 5.0)
|
||||
- gettext (version >= 0.18.3)
|
||||
- git (version >= 2.7.4)
|
||||
- groff (version >= 1.12)
|
||||
- make (any version)
|
||||
- pkg-config (version >= 0.22)
|
||||
- texinfo (version >= 4.0)
|
||||
autoconf (version >= 2.69)
|
||||
automake (version >= 1.14)
|
||||
autopoint (version >= 0.20)
|
||||
gcc (version >= 5.0)
|
||||
gettext (version >= 0.20)
|
||||
git (version >= 2.7.4)
|
||||
groff (version >= 1.12)
|
||||
make (any version)
|
||||
pkg-config (version >= 0.22)
|
||||
texinfo (version >= 4.0)
|
||||
|
||||
You will also need to have the header files for ncurses installed,
|
||||
from libncurses-dev on Debian, ncurses-devel on Fedora, or similar.
|
||||
@@ -29,14 +28,14 @@ These should all be available in your distro's package manager or
|
||||
software center, or otherwise on any GNU mirror.
|
||||
|
||||
|
||||
Download the source
|
||||
-------------------
|
||||
Clone the source
|
||||
----------------
|
||||
|
||||
To obtain the current nano development branch (called 'master'), use the
|
||||
following command. It will create in your current working directory a
|
||||
subdirectory called 'nano' containing a copy of all of the files:
|
||||
|
||||
$ git clone git://git.savannah.gnu.org/nano.git nano
|
||||
$ git clone git://git.git.savannah.gnu.org/nano.git
|
||||
|
||||
|
||||
Generate the configure script
|
||||
@@ -58,6 +57,9 @@ directory:
|
||||
|
||||
$ ./configure [--add-options-here]
|
||||
|
||||
Use --sysconfdir=/etc when you want your self-compiled nano to read
|
||||
/etc/nanorc instead of /usr/local/etc/nanorc.
|
||||
|
||||
|
||||
Build and install
|
||||
-----------------
|
||||
@@ -84,6 +86,7 @@ Problems?
|
||||
Please submit any bugs you find in the code in git via the bug tracker
|
||||
on Savannah (https://savannah.gnu.org/bugs/?group=nano).
|
||||
|
||||
|
||||
Contributing something
|
||||
----------------------
|
||||
|
||||
6
THANKS
6
THANKS
@@ -5,9 +5,11 @@ If we missed you here, let us know!
|
||||
Translations:
|
||||
============
|
||||
Pedro Albuquerque <palbuquerque73@gmail.com> Portuguese
|
||||
Zayed Al-Saidi <zayed.alsaidi@gmail.com> Arabic
|
||||
Josef Andersson <josef.andersson@fripost.org> Swedish
|
||||
Laurentiu Buzdugan <buzdugan@voyager.net> Romanian
|
||||
Mario Blättermann <mario.blaettermann@gmail.com> German
|
||||
Besnik Bleta <besnik@programeshqip.org> Albanian
|
||||
Laurențiu Buzdugan <buzdugan@voyager.net> Romanian
|
||||
Ricardo Cárdenes Medina <ricardo@conisys.com> Spanish
|
||||
Antonio Ceballos <aceballos@gmail.com> Spanish
|
||||
Wei-Lun CHAO <chaoweilun@pcmail.com.tw> Chinese (traditional)
|
||||
@@ -46,6 +48,7 @@ Jordi Mallach <jordi@gnu.org> Catalan
|
||||
João Victor Duarte Martins <jvdm@sdf.lonestar.org> Brazilian Portuguese
|
||||
Pavel Maryanov <acid@jack.kiev.ua> Russian
|
||||
Daniele Medri <madrid@linux.it> Italian
|
||||
Baurzhan Muftakhidinov <baurthefirst@gmail.com> Kazakh
|
||||
Gergely Nagy <algernon@debian.org> Hungarian
|
||||
Claudio Neves <cneves@nextis.com> Brazilian Portuguese
|
||||
Kalle Olavi Niemitalo <kon@iki.fi> Finnish
|
||||
@@ -78,6 +81,7 @@ Jacobo Tarrío <jtarrio@trasno.net> Galician
|
||||
Andika Triwidada <andika@gmail.com> Indonesian
|
||||
Francisco Javier Tsao Santín <tsao@members.fsf.org> Galician
|
||||
Balázs Úr <urbalazs@gmail.com> Hungarian
|
||||
Luca Vercelli <luca.vercelli.to@gmail.com> Italian
|
||||
Miquel Vidal <miquel@sindominio.net> Catalan
|
||||
Phan Vinh Thinh <teppi82@gmail.com> Vietnamese
|
||||
Pauli Virtanen <pauli.virtanen@saunalahti.fi> Finnish
|
||||
|
||||
22
autogen.sh
22
autogen.sh
@@ -2,9 +2,10 @@
|
||||
# Generate configure & friends for GIT users.
|
||||
|
||||
gnulib_url="git://git.sv.gnu.org/gnulib.git"
|
||||
gnulib_hash="135414a7f543e4d40ad0a7cbd51885e159a6e0f4"
|
||||
gnulib_hash="833eea6be5607a85bc964bf728a7a82ca461b5b1"
|
||||
|
||||
modules="
|
||||
canonicalize-lgpl
|
||||
futimens
|
||||
getdelim
|
||||
getline
|
||||
@@ -18,32 +19,35 @@ modules="
|
||||
regex
|
||||
sigaction
|
||||
snprintf-posix
|
||||
stdarg
|
||||
stdarg-h
|
||||
strcase
|
||||
strcasestr-simple
|
||||
strnlen
|
||||
sys_wait
|
||||
vsnprintf-posix
|
||||
wchar
|
||||
wchar-h
|
||||
wctype-h
|
||||
wcwidth
|
||||
"
|
||||
|
||||
# Make sure the local gnulib git repo is up-to-date.
|
||||
if [ ! -d "gnulib" ]; then
|
||||
git clone --depth=1111 ${gnulib_url}
|
||||
git clone --depth=2222 ${gnulib_url}
|
||||
fi
|
||||
cd gnulib >/dev/null || exit 1
|
||||
curr_hash=$(git log -1 --format=%H)
|
||||
if [ "${gnulib_hash}" != "${curr_hash}" ]; then
|
||||
echo "Pulling..."
|
||||
git pull
|
||||
git checkout -f ${gnulib_hash}
|
||||
git checkout --force ${gnulib_hash}
|
||||
fi
|
||||
cd .. >/dev/null || exit 1
|
||||
|
||||
rm -rf lib
|
||||
./gnulib/gnulib-tool \
|
||||
--import \
|
||||
${modules}
|
||||
echo "Gnulib-tool..."
|
||||
./gnulib/gnulib-tool --import ${modules}
|
||||
echo
|
||||
|
||||
autoreconf -f -i -s
|
||||
echo "Autoreconf..."
|
||||
autoreconf --install --symlink --force
|
||||
echo "Done."
|
||||
|
||||
93
configure.ac
93
configure.ac
@@ -1,6 +1,6 @@
|
||||
# Configuration for GNU nano - a small and user-friendly text editor
|
||||
#
|
||||
# Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2014, 2017 Mike Frysinger
|
||||
#
|
||||
# GNU nano is free software: you can redistribute it and/or modify
|
||||
@@ -16,10 +16,11 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
|
||||
AC_INIT([GNU nano], [6.0], [nano-devel@gnu.org], [nano])
|
||||
AC_INIT([GNU nano], [9.2], [nano-devel@gnu.org], [nano])
|
||||
AC_CONFIG_SRCDIR([src/nano.c])
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE([1.14])
|
||||
AM_MAINTAINER_MODE([enable])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
dnl Make sure the ONCE macros are available.
|
||||
@@ -47,7 +48,7 @@ PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl Internationalization macros.
|
||||
|
||||
AM_GNU_GETTEXT_VERSION([0.18.3])
|
||||
AM_GNU_GETTEXT_VERSION([0.20])
|
||||
AM_GNU_GETTEXT([external], [need-ngettext])
|
||||
AM_CONDITIONAL(USE_NLS, test x$USE_NLS = xyes)
|
||||
|
||||
@@ -127,6 +128,20 @@ if test "x$enable_color" != xno; then
|
||||
color_support=yes
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(folding,
|
||||
AS_HELP_STRING([--disable-folding], [Disable line folding support]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_folding" = xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-folding cannot work with --enable-tiny])
|
||||
else
|
||||
enable_folding=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_folding" != xno; then
|
||||
AC_DEFINE(ENABLE_FOLDING, 1, [Define this to have line folding support.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(comment,
|
||||
AS_HELP_STRING([--disable-comment], [Disable the comment/uncomment function]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
@@ -152,6 +167,30 @@ if test "x$enable_extra" != xno; then
|
||||
AC_DEFINE(ENABLE_EXTRA, 1, [Define this to have an Easter egg.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(formatter,
|
||||
AS_HELP_STRING([--disable-formatter], [Disable the formatting tool]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_formatter" = xyes; then
|
||||
if test "x$enable_color" != xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-formatter needs both --enable-color and --enable-nanorc to work])
|
||||
fi
|
||||
else
|
||||
enable_formatter=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_color" = xno; then
|
||||
if test "x$enable_formatter" = xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-formatter cannot work with --disable-color nor --disable-nanorc])
|
||||
else
|
||||
enable_formatter=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_formatter" != xno; then
|
||||
AC_DEFINE(ENABLE_FORMATTER, 1, [Define this to have access to a formatter.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(help,
|
||||
AS_HELP_STRING([--disable-help], [Disable the built-in help texts]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
@@ -205,7 +244,7 @@ if test "x$enable_libmagic" = xyes; then
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_color" != xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-libmagic needs --enable-color and --enable-nanorc to work])
|
||||
*** --enable-libmagic needs both --enable-color and --enable-nanorc to work])
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_color" = xno; then
|
||||
@@ -214,6 +253,30 @@ if test "x$enable_libmagic" = xyes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(linter,
|
||||
AS_HELP_STRING([--disable-linter], [Disable the linting tool]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_linter" = xyes; then
|
||||
if test "x$enable_color" != xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-linter needs both --enable-color and --enable-nanorc to work])
|
||||
fi
|
||||
else
|
||||
enable_linter=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_color" = xno; then
|
||||
if test "x$enable_linter" = xyes; then
|
||||
AC_MSG_ERROR([
|
||||
*** --enable-linter cannot work with --disable-color nor --disable-nanorc])
|
||||
else
|
||||
enable_linter=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_linter" != xno; then
|
||||
AC_DEFINE(ENABLE_LINTER, 1, [Define this to have access to a linter.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(linenumbers,
|
||||
AS_HELP_STRING([--disable-linenumbers], [Disable line numbering]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
@@ -271,14 +334,14 @@ if test "x$enable_operatingdir" != xno; then
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(speller,
|
||||
AS_HELP_STRING([--disable-speller], [Disable the spell-checker functions]))
|
||||
AS_HELP_STRING([--disable-speller], [Disable the spell-checking tool]))
|
||||
if test "x$enable_tiny" = xyes; then
|
||||
if test "x$enable_speller" != xyes; then
|
||||
enable_speller=no
|
||||
fi
|
||||
fi
|
||||
if test "x$enable_speller" != xno; then
|
||||
AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have the spell-checker functions.])
|
||||
AC_DEFINE(ENABLE_SPELLER, 1, [Define this to have access to a spell checker.])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(tabcomp,
|
||||
@@ -353,6 +416,9 @@ if test "x$enable_utf8" != xno; then
|
||||
AC_CHECK_FUNCS(iswalpha iswalnum iswpunct mbstowcs wctomb)
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS_ONCE(chmod chown fchmod fchown flockfile funlockfile
|
||||
fork fsync geteuid pipe wait waitpid)
|
||||
|
||||
dnl Checks for available flags.
|
||||
|
||||
AX_CHECK_COMPILE_FLAG([-Wall], [CFLAGS="$CFLAGS -Wall"], [], [])
|
||||
@@ -510,21 +576,6 @@ int main(void)
|
||||
*** Can't check need for _XOPEN_SOURCE_EXTENDED when cross-compiling.]))
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([whether LINES and COLS can be redefined])
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <curses.h>
|
||||
int main(void)
|
||||
{
|
||||
LINES = 80;
|
||||
COLS = 25;
|
||||
return 0;
|
||||
}]])],
|
||||
AC_DEFINE(REDEFINING_MACROS_OK, 1, [Define this if you know your curses library allows LINES and COLS to be redefined to deal with a resizing bug.])
|
||||
AC_MSG_RESULT(yes),
|
||||
AC_MSG_RESULT(no),
|
||||
AC_MSG_WARN([
|
||||
*** Can't check for macro redefinability when cross-compiling.]))
|
||||
|
||||
AS_IF([test "x$enable_libmagic" != "xno"], [
|
||||
AC_CHECK_HEADERS([magic.h])
|
||||
AC_CHECK_LIB(magic, magic_open)
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<body>
|
||||
|
||||
<br>
|
||||
<h1 align="center">Overview of nano's shortcuts </h1>
|
||||
<h3 align="center">The editor's keystrokes and their functions </h3>
|
||||
<h1 align="center">Overview of nano's shortcuts </h1>
|
||||
<h3 align="center">The editor's keystrokes and their functions </h3>
|
||||
<br>
|
||||
|
||||
<table align="center"><tbody>
|
||||
@@ -33,7 +33,6 @@
|
||||
<tr><td>Ctrl+K </td><td>Cut current line into cutbuffer</td></tr>
|
||||
<tr><td>Alt+6</td><td>Copy current line into cutbuffer</td></tr>
|
||||
<tr><td>Ctrl+U</td><td>Paste contents of cutbuffer</td></tr>
|
||||
<tr><td>Alt+T</td><td>Cut until end of buffer</td></tr>
|
||||
<tr><td>Ctrl+]</td><td>Complete current word</td></tr>
|
||||
<tr><td>Alt+3</td><td>Comment/uncomment line/region</td></tr>
|
||||
<tr><td>Alt+U</td><td>Undo last action</td></tr>
|
||||
@@ -43,10 +42,10 @@
|
||||
|
||||
<b>Search and replace</b>
|
||||
<table><tbody>
|
||||
<tr><td>Ctrl+Q </td><td>Start backward search</td></tr>
|
||||
<tr><td>Ctrl+W</td><td>Start forward search</td></tr>
|
||||
<tr><td>Alt+Q</td><td>Find next occurrence backward</td></tr>
|
||||
<tr><td>Alt+W</td><td>Find next occurrence forward</td></tr>
|
||||
<tr><td>Ctrl+B </td><td>Start backward search</td></tr>
|
||||
<tr><td>Ctrl+F</td><td>Start forward search</td></tr>
|
||||
<tr><td>Alt+B</td><td>Find next occurrence backward</td></tr>
|
||||
<tr><td>Alt+F</td><td>Find next occurrence forward</td></tr>
|
||||
<tr><td>Alt+R</td><td>Start a replacing session</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
@@ -64,11 +63,16 @@
|
||||
<b>Operations</b>
|
||||
<table><tbody>
|
||||
<tr><td>Ctrl+T </td><td>Execute some command</td></tr>
|
||||
<tr><td>Ctrl+T Ctrl+S</td><td>Run a spell check</td></tr>
|
||||
<tr><td>Ctrl+T Ctrl+Y</td><td>Run a syntax check</td></tr>
|
||||
<tr><td>Ctrl+T Ctrl+O </td><td>Run a formatter</td></tr>
|
||||
<tr><td>Tab</td><td>Indent marked region</td></tr>
|
||||
<tr><td>Shift+Tab </td><td>Unindent marked region</td></tr>
|
||||
<tr><td>Ctrl+J</td><td>Justify paragraph or region</td></tr>
|
||||
<tr><td>Alt+J</td><td>Justify entire buffer</td></tr>
|
||||
<tr><td>Alt+B</td><td>Run a syntax check</td></tr>
|
||||
<tr><td>Alt+F</td><td>Run a formatter/fixer/arranger</td></tr>
|
||||
<tr><td>Alt+:</td><td>Start/stop recording of macro</td></tr>
|
||||
<tr><td>Alt+T</td><td>Cut until end of buffer</td></tr>
|
||||
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
||||
<tr><td>Alt+:</td><td>Start/stop recording of macro </td></tr>
|
||||
<tr><td>Alt+;</td><td>Replay macro</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
@@ -77,8 +81,8 @@
|
||||
|
||||
<b>Moving around</b>
|
||||
<table><tbody>
|
||||
<tr><td>Ctrl+B </td><td>One character backward</td></tr>
|
||||
<tr><td>Ctrl+F</td><td>One character forward</td></tr>
|
||||
<tr><td><b>←</b></td><td>One character backward</td></tr>
|
||||
<tr><td><b>→</b></td><td>One character forward</td></tr>
|
||||
<tr><td>Ctrl+<b>←</b></td><td>One word backward</td></tr>
|
||||
<tr><td>Ctrl+<b>→</b></td><td>One word forward</td></tr>
|
||||
<tr><td>Ctrl+A</td><td>To start of line</td></tr>
|
||||
@@ -87,6 +91,8 @@
|
||||
<tr><td>Ctrl+N</td><td>One line down</td></tr>
|
||||
<tr><td>Ctrl+<b>↑</b></td><td>To previous block</td></tr>
|
||||
<tr><td>Ctrl+<b>↓</b></td><td>To next block</td></tr>
|
||||
<tr><td>Alt+Home </td><td>To first row in viewport</td></tr>
|
||||
<tr><td>Alt+End</td><td>To last row in viewport</td></tr>
|
||||
<tr><td>Ctrl+Y</td><td>One page up</td></tr>
|
||||
<tr><td>Ctrl+V</td><td>One page down</td></tr>
|
||||
<tr><td>Alt+\</td><td>To top of buffer</td></tr>
|
||||
@@ -96,33 +102,35 @@
|
||||
|
||||
<b>Special movement</b>
|
||||
<table><tbody>
|
||||
<tr><td>Alt+G </td><td>Go to specified line</td></tr>
|
||||
<tr><td>Alt+G </td><td>Go to a specified line</td></tr>
|
||||
<tr><td>Alt+]</td><td>Go to complementary bracket</td></tr>
|
||||
<tr><td>Alt+<</td><td>Scroll viewport to the left</td></tr>
|
||||
<tr><td>Alt+></td><td>Scroll viewport to the right</td></tr>
|
||||
<tr><td>Alt+<b>↑</b></td><td>Scroll viewport up</td></tr>
|
||||
<tr><td>Alt+<b>↓</b></td><td>Scroll viewport down</td></tr>
|
||||
<tr><td>Alt+<</td><td>Switch to preceding buffer</td></tr>
|
||||
<tr><td>Alt+></td><td>Switch to succeeding buffer</td></tr>
|
||||
<tr><td>Ctrl+L</td><td>Center the current line</td></tr>
|
||||
<tr><td>Alt+<b>←</b></td><td>Switch to preceding buffer</td></tr>
|
||||
<tr><td>Alt+<b>→</b></td><td>Switch to succeeding buffer</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
|
||||
<b>Information</b>
|
||||
<table><tbody>
|
||||
<tr><td>Ctrl+C </td><td>Report cursor position</td></tr>
|
||||
<tr><td>Alt+D</td><td>Report line/word/character count</td></tr>
|
||||
<tr><td>Alt+D</td><td>Report line/word/character counts</td></tr>
|
||||
<tr><td>Ctrl+G</td><td>Display help text</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
|
||||
<b>Various</b>
|
||||
<table><tbody>
|
||||
<tr><td>Alt+A</td><td>Turn the mark on/off</td></tr>
|
||||
<tr><td>Tab</td><td>Indent marked region</td></tr>
|
||||
<tr><td>Shift+Tab </td><td>Unindent marked region</td></tr>
|
||||
<tr><td>Alt+A </td><td>Set or unset the mark</td></tr>
|
||||
<tr><td>Alt+C</td><td>Turn constant position info on/off</td></tr>
|
||||
<tr><td>Alt+N</td><td>Turn line numbers on/off</td></tr>
|
||||
<tr><td>Alt+P</td><td>Turn visible whitespace on/off</td></tr>
|
||||
<tr><td>Alt+V</td><td>Enter next keystroke verbatim</td></tr>
|
||||
<tr><td>Ctrl+L</td><td>Refresh the screen</td></tr>
|
||||
<tr><td>Ctrl+Z</td><td>Suspend nano</td></tr>
|
||||
<tr><td>Alt+S</td><td>Turn softwrapping on/off</td></tr>
|
||||
<tr><td>Alt+X</td><td>Hide/unhide the help lines</td></tr>
|
||||
<tr><td>Alt+Z</td><td>Hide/unhide the info bars</td></tr>
|
||||
</tbody></table>
|
||||
<br>
|
||||
|
||||
|
||||
147
doc/faq.html
147
doc/faq.html
@@ -5,7 +5,7 @@
|
||||
<title>The GNU nano editor FAQ</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="description" content="The genesis story of the nano editor, plus the solution to some common problems.">
|
||||
<style>
|
||||
<style type="text/css">
|
||||
.indented { margin-left: 2em; font-family: courier; font-size: 110%; }
|
||||
</style>
|
||||
</head>
|
||||
@@ -27,7 +27,7 @@
|
||||
<a href="#2.1">2.1. FTP and WWW sites that carry nano.</a><br>
|
||||
<a href="#2.2">2.2. RedHat and derivatives (.rpm) packages.</a><br>
|
||||
<a href="#2.3">2.3. Debian (.deb) packages.</a><br>
|
||||
<a href="#2.4">2.4. By GIT (for the brave).</a>
|
||||
<a href="#2.4">2.4. By git (for the brave).</a>
|
||||
</p></blockquote>
|
||||
<h3><a href="#3">3. Installation and Configuration</a></h3>
|
||||
<blockquote><p>
|
||||
@@ -45,13 +45,13 @@
|
||||
<blockquote><p>
|
||||
<a href="#4.1">4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</a><br>
|
||||
<a href="#4.2">4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</a><br>
|
||||
<a href="#4.3">4.3. Ack! My numeric keypad's keys don't work properly when NumLock is off! What can I do?</a><br>
|
||||
<a href="#4.4">4.4. With what keystroke can I paste text from the clipboard into nano?</a><br>
|
||||
<a href="#4.3">4.3. How do I remove an unwanted Byte Order Mark?</a><br>
|
||||
<a href="#4.4">4.4. Where did Ctrl+T in the Search menu go?</a><br>
|
||||
<a href="#4.5">4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</a><br>
|
||||
<a href="#4.6">4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</a><br>
|
||||
<a href="#4.7">4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</a><br>
|
||||
<a href="#4.8">4.8. I've compiled nano with color support, but I don't see any color when I run it!</a><br>
|
||||
<a href="#4.9">4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</a><br>
|
||||
<a href="#4.9">4.9. How do I make nano my default editor (in Pine, mutt, git, ...)?</a><br>
|
||||
</p></blockquote>
|
||||
<h3><a href="#5">5. Internationalization</a></h3>
|
||||
<blockquote><p>
|
||||
@@ -72,14 +72,14 @@
|
||||
<a href="#7.2">7.2. How do I submit a bug report or patch?</a><br>
|
||||
<a href="#7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</a><br>
|
||||
<a href="#7.4">7.4. How do I join the development team?</a><br>
|
||||
<a href="#7.5">7.5. Can I have write access to the GIT tree?</a>
|
||||
<a href="#7.5">7.5. Can I have write access to the git tree?</a>
|
||||
</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="1"></a>1. General</h1>
|
||||
<h3><a name="1.1"></a>1.1. What is GNU nano?</h3>
|
||||
<h1 id="1">1. General</h1>
|
||||
<h3 id="1.1">1.1. What is GNU nano?</h3>
|
||||
<blockquote><p>GNU nano was designed to be a free replacement for the Pico text editor, part of the Pine email suite from <a href="http://www.washington.edu/pine/">The University of Washington</a>. It aimed to "emulate Pico as closely as is reasonable and then include extra functionality".</p></blockquote>
|
||||
<h3><a name="1.2"></a>1.2. What is the history behind nano?</h3>
|
||||
<h3 id="1.2">1.2. What is the history behind nano?</h3>
|
||||
<blockquote><p>Funny you should ask!</p>
|
||||
<p><b>In the beginning...</b></p>
|
||||
<p>For years Pine was THE program used to read email on a Unix system. The Pico text editor is the portion of the program one would use to compose his or her mail messages. Many beginners to Unix flocked to Pico and Pine because of their well organized, easy to use interfaces. With the proliferation of GNU/Linux in the mid to late 90's, many University students became intimately familiar with the strengths (and weaknesses) of Pine and Pico.</p>
|
||||
@@ -89,30 +89,30 @@
|
||||
<p>It was in late 1999 when Chris Allegretta (our hero) was yet again complaining to himself about the less-than-perfect license Pico was distributed under, the 1000 makefiles that came with it and how just a few small improvements could make it the Best Editor in the World (TM). Having been a convert from Slackware to Debian, he missed having a simple binary package that included Pine and Pico, and had grown tired of downloading them himself.</p>
|
||||
<p>Finally something snapped inside and Chris coded and hacked like a madman for many hours straight one weekend to make a (barely usable) Pico clone, at the time called TIP (Tip Isn't Pico). The program could not be invoked without a filename, could not save files, had no help text display, spell checker, and so forth. But over time it improved, and with the help of a few great coders it matured to the (hopefully) stable state it is in today.</p>
|
||||
<p>In February 2001, nano was declared an official GNU program by Richard Stallman. nano also reached its first production release on March 22, 2001.</p></blockquote>
|
||||
<h3><a name="1.3"></a>1.3. Why the name change from TIP?</h3>
|
||||
<h3 id="1.3">1.3. Why the name change from TIP?</h3>
|
||||
<blockquote><p>On January 10, 2000, TIP was officially renamed to nano because of a namespace conflict with another program called 'tip'. The original 'tip' program "establishes a full duplex terminal connection to a remote host", and was included with many older Unix systems (and newer ones like Solaris). The conflict was not noticed at first because there is no 'tip' utility included with most GNU/Linux distributions (where nano was developed).</p></blockquote>
|
||||
<h3><a name="1.4"></a>1.4. What is the current version of nano?</h3>
|
||||
<blockquote><p>The current version of nano <i>should</i> be <b>6.0</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<h3><a name="1.5"></a>1.5. I want to read the man page without having to download the program!</h3>
|
||||
<h3 id="1.4">1.4. What is the current version of nano?</h3>
|
||||
<blockquote><p>The current version of nano <i>should</i> be <b>9.2</b>. Of course, you should always check the <a href="https://nano-editor.org/">nano homepage</a> to see what the latest and greatest version is.</p></blockquote>
|
||||
<h3 id="1.5">1.5. I want to read the man page without having to download the program!</h3>
|
||||
<blockquote><p>Jeez, demanding, aren't we? Okay, look <a href="https://nano-editor.org/dist/latest/nano.1.html">here</a>.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="2"></a>2. Where to get GNU nano.</h1>
|
||||
<h3><a name="2.1"></a>2.1. Web sites that carry nano.</h3>
|
||||
<h1 id="2">2. Where to get GNU nano.</h1>
|
||||
<h3 id="2.1">2.1. Web sites that carry nano.</h3>
|
||||
<blockquote><p>The nano source tarballs can be downloaded from the following web sites:</p>
|
||||
<ul>
|
||||
<li><a href="https://nano-editor.org/dist/latest/">https://nano-editor.org/dist/latest/</a></li>
|
||||
<li><a href="https://ftpmirror.gnu.org/gnu/nano/">https://ftpmirror.gnu.org/gnu/nano/</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h3><a name="2.2"></a>2.2. RPM packages (RedHat, OpenSuse, and derivatives).</h3>
|
||||
<h3 id="2.2">2.2. RPM packages (RedHat, OpenSuse, and derivatives).</h3>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li><a href="https://kojipkgs.fedoraproject.org//packages/nano/">https://kojipkgs.fedoraproject.org//packages/nano/</a></li>
|
||||
<li><a href="https://software.opensuse.org/package/nano">https://software.opensuse.org/package/nano</a></li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h3><a name="2.3"></a>2.3. Deb packages (Debian and derivatives):</h3>
|
||||
<h3 id="2.3">2.3. Deb packages (Debian and derivatives):</h3>
|
||||
<blockquote><p>Debian users can check out the current nano packages for:</p>
|
||||
<ul>
|
||||
<li><a href="https://packages.debian.org/stable/editors/nano">stable</a></li>
|
||||
@@ -121,14 +121,14 @@
|
||||
</ul>
|
||||
<p>You can also have a look at the <a href="http://ftp.debian.org/debian/pool/main/n/nano/">Package Pool</a> to see all the available binary and source packages.</p>
|
||||
</blockquote>
|
||||
<h3><a name="2.4"></a>2.4. By GIT (for the brave).</h3>
|
||||
<blockquote><p>For the 'bleeding edge' current version of nano, you can use GIT to download the current source code. <b>Note:</b> believe it or not, by downloading code that has not yet stabilized into an official release, there could quite possibly be bugs, in fact the code may not even compile! Anyway, see <a href="http://git.savannah.gnu.org/cgit/nano.git/tree/README.GIT">the nano GIT document</a> for info on anonymous GIT access to the nano source.</p></blockquote>
|
||||
<h3 id="2.4">2.4. By git (for the brave).</h3>
|
||||
<blockquote><p>For the "bleeding edge" current version of nano, you can use <b>git</b> to download the current source code. <i>Note:</i> believe it or not, by downloading code that has not yet stabilized into an official release, there could quite possibly be bugs, in fact the code may not even compile! Anyway, see <a href="http://git.savannah.gnu.org/cgit/nano.git/tree/README.hacking">the hacking document</a> for info on getting and building nano from git.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="3"></a>3. Installation and Configuration</h1>
|
||||
<h3><a name="3.1"></a>3.1. How do I install the RPM or DEB package?</h3>
|
||||
<h1 id="3">3. Installation and Configuration</h1>
|
||||
<h3 id="3.1">3.1. How do I install the RPM or DEB package?</h3>
|
||||
<blockquote><p>It's simple really! As root, type <b>rpm -Uvh nano-x.y-1*.rpm</b> if you have a RedHat-ish system or <b>dpkg -i nano_x.y-1*.deb</b> if you have a Debian-ish system, where <b>x.y</b> is the version number of nano. There are other programs to install packages, and if you wish to use those, knock yourself out.</p></blockquote>
|
||||
<h3><a name="3.2"></a>3.2. Compiling from source: WHAT THE HECK DO I DO NOW?</h3>
|
||||
<h3 id="3.2">3.2. Compiling from source: WHAT THE HECK DO I DO NOW?</h3>
|
||||
<blockquote><p>Okay, take a deep breath, this really isn't hard. Unpack the nano source with a command like:</p>
|
||||
<p class="indented"><b>tar -xvf nano-x.y.tar.gz</b></p>
|
||||
<p>Then you need to run <b>configure</b> with any options you might want (if any).</p>
|
||||
@@ -137,48 +137,52 @@
|
||||
<b>./configure</b><br>
|
||||
<b>make</b><br>
|
||||
<b>make install</b> #(as root, of course)</p></blockquote>
|
||||
<h3><a name="3.3"></a>3.3. Why does everything go into /usr/local?</h3>
|
||||
<h3 id="3.3">3.3. Why does everything go into /usr/local?</h3>
|
||||
<blockquote><p>Well, that's what the <b>configure</b> script defaults to. If you wish to change this, simply do this:</p>
|
||||
<p class="indented"><b>./configure --prefix=/usr</b></p>
|
||||
<p>This will put nano into /usr/bin when you run <b>make install</b>.</p></blockquote>
|
||||
<h3><a name="3.4"></a>3.4. nano should automatically run strip on the binary when installing it!</h3>
|
||||
<h3 id="3.4">3.4. nano should automatically run strip on the binary when installing it!</h3>
|
||||
<blockquote><p>It does when you use <b>make install-strip</b>. The default <b>make install</b> does not, and will not, run strip automatically.</p></blockquote>
|
||||
<h3><a name="3.5"></a>3.5. How can I make the executable smaller? This is too bloated!</h3>
|
||||
<h3 id="3.5">3.5. How can I make the executable smaller? This is too bloated!</h3>
|
||||
<blockquote><p>Actually, there are several parts of the editor that can be disabled. You can pass arguments to the <b>configure</b> script that disable certain features. Here's a brief list:</p>
|
||||
<pre>
|
||||
<b>--disable-browser</b> Disable the built-in file browser
|
||||
<b>--disable-color</b> Disable color and syntax highlighting
|
||||
<b>--disable-comment</b> Disable the comment/uncomment function
|
||||
<b>--disable-extra</b> Disable the easter egg
|
||||
<b>--disable-formatter</b> Disable the formatting tool
|
||||
<b>--disable-help</b> Disable the built-in help texts
|
||||
<b>--disable-histories</b> Disable the saving of search strings and cursor positions
|
||||
<b>--disable-justify</b> Disable the justify/unjustify functions
|
||||
<b>--disable-libmagic</b> Disable the use of libmagic for determining a file's syntax
|
||||
<b>--disable-linenumbers</b> Disable line numbering
|
||||
<b>--disable-linter</b> Disable the linting tool
|
||||
<b>--disable-mouse</b> Disable mouse support
|
||||
<b>--disable-multibuffer</b> Disable the opening of multiple file buffers
|
||||
<b>--disable-nanorc</b> Disable the use of .nanorc files
|
||||
<b>--disable-operatingdir</b> Disable the setting of an operating directory
|
||||
<b>--disable-speller</b> Disable the spell-checker functions
|
||||
<b>--disable-speller</b> Disable the spell-checking tool
|
||||
<b>--disable-tabcomp</b> Disable the tab-completion functions
|
||||
<b>--disable-wordcomp</b> Disable the word-completion function
|
||||
<b>--disable-wrapping</b> Disable all hard-wrapping of text</pre>
|
||||
<p>There's also the <b>--enable-tiny</b> option which disables everything above, as well as some larger chunks of the program (like the undo/redo code and the code for selecting text). Also, if you know you don't need other languages, you can use <b>--disable-nls</b> to disable internationalization and save a few kilobytes. And finally, there's always good old <b>strip</b> to remove all unneeded symbols.</p>
|
||||
</blockquote>
|
||||
<h3><a name="3.6"></a>3.6. Tell me more about this multibuffer stuff!</h3>
|
||||
<blockquote><p>To use multiple file buffers, you must not have configured nano with <b>--disable-multibuffer</b> nor with <b>--enable-tiny</b> (use <b>nano -V</b> to check the compilation options). Then when you want to insert a file into its own buffer instead of into the current file, just hit <b>Meta-F</b> after typing <b>^R</b>. If you always want files to be loaded into their own buffers, use the <b>-F</b> or <b>--multibuffer</b> flag when you invoke nano, or add <b>set multibuffer</b> to your .nanorc file.</p>
|
||||
<p>You can move between the buffers you have open with the <b>Meta-<</b> and <b>Meta-></b> keys, or more easily without holding Shift: <b>Meta-,</b> and <b>Meta-.</b> (clear as mud, right? =-). When you have more than one buffer open, the ^X shortcut will say "Close", instead of "Exit".</p></blockquote>
|
||||
<h3><a name="3.7"></a>3.7. Tell me more about this verbatim input stuff!</h3>
|
||||
<h3 id="3.6">3.6. Tell me more about this multibuffer stuff!</h3>
|
||||
<blockquote><p>To use multiple file buffers, you must not have configured nano with <b>--disable-multibuffer</b> nor with <b>--enable-tiny</b> (use <b>nano -V</b> to check the compilation options). Then when you want to insert a file into its own buffer instead of into the current file, just hit <b>Meta-F</b> after typing <b>^R</b>.</p>
|
||||
<p>If you want files to be loaded always into their own buffers, use the <b>-F</b> or <b>--multibuffer</b> flag when you invoke nano, or add <b>set multibuffer</b> to your .nanorc file. (Since nano-9.2 these options are named <b>--newbuffer</b> and <b>set newbuffer</b>.)</p>
|
||||
<p>You can switch between open buffers with <b>Meta-,</b> and <b>Meta-.</b> (Alt+comma and Alt+period).</p>
|
||||
<p>When you have more than one buffer open, the help lines will say "<i>Close</i>" instead of "<i>Exit</i>" for the <b>^X</b> shortcut.</p></blockquote>
|
||||
<h3 id="3.7">3.7. Tell me more about this verbatim input stuff!</h3>
|
||||
<blockquote><p>When you want to insert a literal character into the file you're editing, such as a control character that nano usually treats as a command, first press <b>Meta-V</b> (if you're not at a prompt, you'll get the message "Verbatim Input" on the status bar), then press the key(s) that generate the character you want.</p>
|
||||
<p>Alternatively, if Unicode support is enabled (see section <a href="#5.3">5.3</a>), you can press <b>Meta-V</b> and then type a six-digit hexadecimal code (from 000000 to 10FFFF, case-insensitive), and the character with the corresponding value will be inserted. The status bar will change to "Unicode Input: ......" when you do this.</p></blockquote>
|
||||
<h3><a name="3.8"></a>3.8. How do I make a .nanorc file that will be read when I start nano?</h3>
|
||||
<h3 id="3.8">3.8. How do I make a .nanorc file that will be read when I start nano?</h3>
|
||||
<blockquote><p>It's not hard at all! Simply copy the <b>sample.nanorc</b> from the doc/ directory in the nano source package (or from /usr/doc/nano on your system) to <b>.nanorc</b> in your home directory, and then edit it. If you didn't get a sample nanorc, the syntax of the file is simple: features are turned on and off by using the words <b>set</b> and <b>unset</b> followed by the long option name of the feature (see <b>man nanorc</b> for the full list of options). For example, "set quickblank" or "set smarthome". Of course, for this to work, your nano must <b>not</b> have been compiled with <b>--disable-nanorc</b>.</p></blockquote>
|
||||
<h3><a name="3.9"></a>3.9. Why does my self-compiled nano not read /etc/nanorc?</h3>
|
||||
<blockquote><p>By default (see <a href="#3.3">3.3</a>), nano gets installed into /usr/local. This also means that, at startup, nano will read <b>/usr/local/etc/nanorc</b> instead of <b>/etc/nanorc</b>. You can make a symlink from the former to the latter if you want your self-compiled nano to read the same nanorc as the system-installed nano. Or you can configure your nano to overwrite the system nano (again, see <a href="#3.3">3.3</a>).</p></blockquote>
|
||||
<h3 id="3.9">3.9. Why does my self-compiled nano not read /etc/nanorc?</h3>
|
||||
<blockquote><p>By default (see <a href="#3.3">3.3</a>), nano gets installed into /usr/local. This also means that, at startup, nano reads <b>/usr/local/etc/nanorc</b> instead of <b>/etc/nanorc</b>. You can make a symlink from the former to the latter if you want your self-compiled nano to read the same nanorc as the system-installed nano. Or you can simply configure your nano with <b>--sysconfdir=/etc</b>.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="4"></a>4. Running</h1>
|
||||
<h3><a name="4.1"></a>4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</h3>
|
||||
<h1 id="4">4. Running</h1>
|
||||
<h3 id="4.1">4.1. Alt+Up does nothing on a Linux console. How can I make it scroll?</h3>
|
||||
<blockquote><p>On Debian and its derivatives, the <b>Alt+Up</b> keystroke on a Linux console
|
||||
produces by default a 'KeyboardSignal', which normally does absolutely nothing and is useless
|
||||
for the average user. To get the keystroke to do what it ought to do (scroll the viewport
|
||||
@@ -191,7 +195,7 @@
|
||||
sed -i 's/KeyboardSignal/Up/' ${file%.gz};<br>
|
||||
gzip ${file%.gz};<br>
|
||||
done</b></p></blockquote>
|
||||
<h3><a name="4.2"></a>4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</h3>
|
||||
<h3 id="4.2">4.2. How can I make Ctrl+Shift+Left/Right select words on urxvt?</h3>
|
||||
<blockquote><p>The urxvt terminal emulator produces non-standard escape sequences for the modified cursor keys. These deviant sequences are not listed in the terminfo database, which means that ncurses does not recognize them. The easiest way around this is to tell urxvt to produce xterm-compatible escape sequences for the relevant keystrokes. To achieve this, add the following lines to your ~/.Xresources file:</p>
|
||||
<pre>
|
||||
URxvt.iso14755_52: False
|
||||
@@ -206,31 +210,39 @@
|
||||
URxvt.keysym.M-Right: \033[1;3C
|
||||
URxvt.keysym.M-Left: \033[1;3D
|
||||
|
||||
URxvt.keysym.M-Home: \033[1;3H
|
||||
URxvt.keysym.M-End: \033[1;3F
|
||||
|
||||
URxvt.keysym.M-Insert: \033[2;3~
|
||||
URxvt.keysym.M-Delete: \033[3;3~
|
||||
|
||||
URxvt.keysym.M-Page_Up: \033[5;3~
|
||||
URxvt.keysym.M-Page_Down: \033[6;3~</pre>
|
||||
URxvt.keysym.M-Page_Down: \033[6;3~
|
||||
URxvt.keysym.S-Page_Up: \033[5;2~
|
||||
URxvt.keysym.S-Page_Down: \033[6;2~</pre>
|
||||
<p>Then run <b>xrdb ~/.Xresources</b> and restart your urxvt terminal. Now <b>Ctrl+Shift+Left</b> and <b>Ctrl+Shift+Right</b> will select words, <b>Alt+Up</b> and <b>Alt+Down</b> will scroll the text without moving the cursor, and several such things more.</p></blockquote>
|
||||
<h3><a name="4.3"></a>4.3. Ack! My numeric keypad's keys don't work properly when NumLock is off! What can I do?</h3>
|
||||
<blockquote><p>You can use the <b>-K</b> or <b>--rawsequences</b> option on the command line, or add the line <b>set rawsequences</b> to your .nanorc. However, nano's mouse support will be disabled if you do any of these things.</p></blockquote>
|
||||
<h3><a name="4.4"></a>4.4. With what keystroke can I paste text from the clipboard into nano?</h3>
|
||||
<blockquote><p>In most desktop environments <b>Shift+Insert</b> will paste the contents of the clipboard.</p></blockquote>
|
||||
<h3><a name="4.5"></a>4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</h3>
|
||||
<h3 id="4.3">4.3. How do I remove an unwanted Byte Order Mark?</h3>
|
||||
<blockquote><p>To check whether a file contains a Byte Order Mark (BOM), open the file and type <b>Ctrl+Home</b>. If there is a BOM, the status bar will tell you so. Now type <b>Delete</b> to remove the BOM, and <b>^S</b> to save the file.</p>
|
||||
<p>If you've accidentally deleted a Byte Order Mark from a file that needs it, and you want to restore it, then type: <b>Ctrl+Home Alt+V feff Enter</b>. Verify that the BOM is back with <b>Ctrl+Home</b>, and save the file with <b>^S</b>. (Note that on Unix, files should not contain a BOM.)</p></blockquote>
|
||||
<h3 id="4.4">4.4. Where did Ctrl+T in the Search menu go?</h3>
|
||||
<blockquote><p>Actually, the <b>Ctrl+T</b> toggle is still there — it's just not listed in the help lines nor in the help text, and the function it executes cannot be rebound to another key. If you do want to use another key, you can emulate the rebinding with something like this in your .nanorc:</p>
|
||||
<pre>
|
||||
bind ^E "{cancel}{gotoline}" search
|
||||
bind ^E "{cancel}{whereis}" gotoline</pre>
|
||||
<p>But since forever there are also direct keystrokes for jumping to a line number: <b>Ctrl+/</b> and <b>Alt+G</b> in the main menu.</p></blockquote>
|
||||
<h3 id="4.5">4.5. How do I select text for or paste text from the clipboard when nano's mouse support is turned on?</h3>
|
||||
<blockquote><p>Try holding down the Shift key and selecting or pasting the text as you normally would.</p></blockquote>
|
||||
<h3><a name="4.6"></a>4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</h3>
|
||||
<h3 id="4.6">4.6. When I paste text into a document, each line gets indented further than the last. Why? And how can I stop this?</h3>
|
||||
<blockquote><p>You have the <i>autoindent</i> feature turned on. Hit <b>Meta-I</b> to turn it off, paste your text, and then hit <b>Meta-I</b> again to turn it back on.</p>
|
||||
<p><i>Update:</i> Since version 4.8, nano will suppress auto-indentation during a paste, so you no longer need to toggle it off and on manually.</p></blockquote>
|
||||
<h3><a name="4.7"></a>4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</h3>
|
||||
<p><i>Update:</i> Since version 4.8, nano suppresses auto-indentation during a paste (when your terminal understands <a href="https://en.wikipedia.org/wiki/Bracketed-paste">bracketed pastes</a>), so you no longer need to toggle it off and on manually.</p></blockquote>
|
||||
<h3 id="4.7">4.7. When I paste from Windows into a remote nano, nano rewraps the lines. What gives?</h3>
|
||||
<blockquote><p>When pasting from Windows, in some situations linefeeds are sent instead of carriage returns (Enters). And linefeeds are <b>^J</b>s, which make nano justify (rewrap) the current paragraph. To prevent these linefeeds from causing these unwanted justifications, add this line to your .nanorc on the remote Linux box: <b>unbind ^J main</b> or <b>bind ^J enter main</b>, depending on whether the paste contains CR + LF or only LF.</p>
|
||||
<p><i>Update:</i> Since version 4.8, nano will ignore linefeed characters in a paste, so you no longer need the above workaround.</p></blockquote>
|
||||
<h3><a name="4.8"></a>4.8. I've compiled nano with color support, but I don't see any color when I run it!</h3>
|
||||
<p><i>Update:</i> Since version 4.8, nano ignores linefeed characters in a paste (when your terminal understands <a href="https://en.wikipedia.org/wiki/Bracketed-paste">bracketed pastes</a>), so you no longer need the above workaround.</p></blockquote>
|
||||
<h3 id="4.8">4.8. I've compiled nano with color support, but I don't see any color when I run it!</h3>
|
||||
<blockquote><p>If you want nano to actually use color, you have to specify the color configurations you want it to use in your .nanorc. Several example configurations are in the <b>syntax/</b> subdirectory of the nano source, which are normally installed to <b>/usr/local/share/nano/</b>. To enable all of them, uncomment the line <b># include "/usr/local/share/nano/*.nanorc"</b> in your nanorc. See also section <a href="#3.9">3.9</a>.</p></blockquote>
|
||||
<h3><a name="4.9"></a>4.9. How do I make nano my default editor (in Pine, mutt, etc.)?</h3>
|
||||
<h3 id="4.9">4.9. How do I make nano my default editor (in Pine, mutt, git, ...)?</h3>
|
||||
<blockquote><p>You need to make nano your $EDITOR. If you want this to be saved, you should put a line like this in your <b>.bashrc</b> if you use bash (or <b>.zshrc</b> if you believe in zsh):</p>
|
||||
<p class="indented"><b>export EDITOR=/usr/local/bin/nano</b></p>
|
||||
<p>or, if you use tcsh, put this in your <b>.cshrc</b> file:</p>
|
||||
<p class="indented"><b>setenv EDITOR /usr/local/bin/nano</b></p>
|
||||
<p>Change /usr/local/bin/nano to wherever nano is installed on your system. Type "which nano" to find out. This will not take effect until the next time you log in. So log out and back in again.</p>
|
||||
<p>Then, on top of that, if you use Pine, you must go into setup (type <b>S</b> at the main menu), and then configure (type <b>C</b>). Hit Enter on the lines that say:</p>
|
||||
<p class="indented"><b>[ ] enable-alternate-editor-cmd</b><br>
|
||||
@@ -238,47 +250,50 @@
|
||||
<p>Then exit (<b>E</b>) and select Yes (<b>Y</b>).</p>
|
||||
<p>If you're a mutt user, you should see an effect immediately the next time you log in. No further configuration is needed. However, if you want to let people know you use nano to compose your email messages, you can put a line like this in your <b>.muttrc</b>:</p>
|
||||
<p class="indented"><b>my_hdr X-Composer: nano-x.y</b></p>
|
||||
<p>Again, replace x.y with the version of nano you use.</p></blockquote>
|
||||
<p>Again, replace x.y with the version of nano you use.</p>
|
||||
<p>To use nano to edit your git commit messages, you can run:</p>
|
||||
<p class="indented"><b>git config --global core.editor "nano --guide=74 --nohelp +1"</b></p>
|
||||
<p>Note the <b>+1</b> at the end — it makes nano start always at the top of the edit window. The guidestripe helps you keep the text within a reasonable width.</blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="5"></a>5. Internationalization</h1>
|
||||
<h3><a name="5.1"></a>5.1. There's no translation for my language!</h3>
|
||||
<h1 id="5">5. Internationalization</h1>
|
||||
<h3 id="5.1">5.1. There's no translation for my language!</h3>
|
||||
<blockquote><p>In June 2001, GNU nano entered the <a href="https://translationproject.org/html/welcome.html">Translation Project</a> and since then, translations should be managed from there.</p>
|
||||
<p>If there isn't a translation for your language, you could ask <a href="https://translationproject.org/team/">your language team</a> to translate nano, or better still, join that team and do it yourself. Joining a team is easy. You just need to ask the team leader to add you, and then send a <a href="https://translationproject.org/disclaim.txt">translation disclaimer to the FSF</a> (this is necessary as nano is an official GNU package, but it does <b>not</b> mean that you transfer the rights of your work to the FSF, it's just so the FSF can legally manage them).</p>
|
||||
<p>In any case, translating nano is easy. Just grab the latest <b>nano.pot</b> file listed on <a href="https://translationproject.org/domain/nano.html">nano's page</a> at the TP, and translate each <b>msgid</b> line into your native language on the <b>msgstr</b> line. When you're done, you should send it to the TP's central PO-file repository.</p></blockquote>
|
||||
<h3><a name="5.2"></a>5.2. I don't like the translation for <x> in my language. How can I fix it?</h3>
|
||||
<h3 id="5.2">5.2. I don't like the translation for <x> in my language. How can I fix it?</h3>
|
||||
<blockquote><p>The best way is to send an e-mail with your suggested corrections to the team's mailing list. The address is mentioned in the <code>Language-Team:</code> field in the relevant PO file. The team leader or the assigned translator can then make the changes reach the nano-devel list.</p></blockquote>
|
||||
<h3><a name="5.3"></a>5.3. What is the status of Unicode support?</h3>
|
||||
<h3 id="5.3">5.3. What is the status of Unicode support?</h3>
|
||||
<blockquote><p>Unicode should be fully usable nowadays. When the encoding of your terminal is set to UTF-8, and your locale (mainly the LANG environment variable) is UTF-8 too, then you should be able to read, enter and save Unicode text.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="6"></a>6. Advocacy and Licensing</h1>
|
||||
<h3><a name="6.1"></a>6.1. Why should I use nano instead of Pico?</h3>
|
||||
<h1 id="6">6. Advocacy and Licensing</h1>
|
||||
<h3 id="6.1">6.1. Why should I use nano instead of Pico?</h3>
|
||||
<blockquote><p>If you want features like undo/redo, syntax highlighting, line numbers, soft-wrapping, opening multiple files at once, an interface localized to your language, or search and replace with support for regular expressions, then you want nano.</p></blockquote>
|
||||
<h3><a name="6.2"></a>6.2. Why should I use Pico instead of nano?</h3>
|
||||
<h3 id="6.2">6.2. Why should I use Pico instead of nano?</h3>
|
||||
<blockquote><p>If you use your editor only to write emails or other texts and have no need for the above-mentioned features, then Pico will do fine for you.</p></blockquote>
|
||||
<h3><a name="6.3"></a>6.3. What is so bad about the older Pine license?</h3>
|
||||
<h3 id="6.3">6.3. What is so bad about the older Pine license?</h3>
|
||||
<blockquote><p>The U of W license for older versions of Pine and Pico is not considered truly Free Software according to both the Free Software Foundation and the <a href="https://www.debian.org/social_contract#guidelines">Debian Free Software Guidelines</a>. The main problem regards the limitations on distributing derived works: according to UW, you can distribute their software, and you can modify it, but you can not do both, i.e. distribute modified binaries.</p></blockquote>
|
||||
<h3><a name="6.4"></a>6.4. Okay, well, what mail program should I use then?</h3>
|
||||
<h3 id="6.4">6.4. Okay, well, what mail program should I use then?</h3>
|
||||
<blockquote><p>If you are looking to use a Free Software program similar to Pine, and Emacs is not your thing, you should definitely take a look at <a href="http://www.mutt.org/">mutt</a>. It is a full-screen, console based mail program that actually has a lot more flexibility than Pine, but has a keymap included in the distribution that allows you to use the same keystrokes as Pine would to send and receive mail. It's also under the GNU General Public License, version 2.0.</p>
|
||||
<p>Of course, due to the license change you can now use the <a href="http://www.washington.edu/alpine/">Alpine distribution</a> of PINE as it is now considered Free Software, but you would be sacrificing many of nano's features to do so.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
<h1><a name="7"></a>7. Miscellaneous</h1>
|
||||
<h3><a name="7.1"></a>7.1. Where can I ask questions or send suggestions?</h3>
|
||||
<h1 id="7">7. Miscellaneous</h1>
|
||||
<h3 id="7.1">7.1. Where can I ask questions or send suggestions?</h3>
|
||||
<blockquote><p>There are three mailing lists for nano hosted at <a href="https://savannah.gnu.org/">Savannah</a>: info-nano, help-nano and nano-devel. info-nano is a very low traffic list where new versions of nano are announced (surprise!). help-nano is for getting help with the editor without needing to hear all of the development issues surrounding it. nano-devel is a normally low, sometimes high traffic list for discussing the present and future development of nano. Here are links to where you can sign up for a given list:</p>
|
||||
<p>info-nano - <a href="https://lists.gnu.org/mailman/listinfo/info-nano/">https://lists.gnu.org/mailman/listinfo/info-nano/</a><br>
|
||||
help-nano - <a href="https://lists.gnu.org/mailman/listinfo/help-nano/">https://lists.gnu.org/mailman/listinfo/help-nano/</a><br>
|
||||
nano-devel - <a href="https://lists.gnu.org/mailman/listinfo/nano-devel/">https://lists.gnu.org/mailman/listinfo/nano-devel/</a></p></blockquote>
|
||||
<h3><a name="7.2"></a>7.3. How do I submit a bug report or patch?</h3>
|
||||
<h3 id="7.2">7.3. How do I submit a bug report or patch?</h3>
|
||||
<blockquote>
|
||||
<p>The best way to submit bugs is through the <a href="https://savannah.gnu.org/bugs/?group=nano">Savannah bug tracker</a>, as you can check whether the bug you are reporting has already been submitted, and it makes it easier for the maintainers to keep track of them.
|
||||
<p>You can submit patches for nano via <a href="https://savannah.gnu.org/patch/?group=nano">Savannah's patch manager</a>.</p></blockquote>
|
||||
<h3><a name="7.3"></a>7.3. I want to send the development team a big load of cash (or just a thank you).</h3>
|
||||
<h3 id="7.3">7.3. I want to send the development team a big load of cash (or just a thank you).</h3>
|
||||
<blockquote><p>That's fine. Send it <a href="mailto:nano-devel@gnu.org">our way</a>! Better yet, fix a <a href="https://savannah.gnu.org/bugs/?group=nano">bug</a> in the program or implement a <a href="https://nano-editor.org/dist/latest/TODO">cool feature</a> and send us that instead (though cash is fine too).</p></blockquote>
|
||||
<h3><a name="7.4"></a>7.4. How do I join the development team?</h3>
|
||||
<h3 id="7.4">7.4. How do I join the development team?</h3>
|
||||
<blockquote><p>The easiest way is to consistently send in good patches that add some needed functionality, fix a bug or two, and/or make the program more optimized/efficient. Then ask nicely and you will probably be added to the Savannah development list and be given write access after a while. There is a lot of responsibility that goes along with being a team member, so don't think it's just something to add to your resume.</p></blockquote>
|
||||
<h3><a name="7.5"></a>7.5. Can I have write access to the git tree?</h3>
|
||||
<h3 id="7.5">7.5. Can I have write access to the git tree?</h3>
|
||||
<blockquote><p>Re-read section <a href="#7.4">7.4</a> and you should know the answer.</p></blockquote>
|
||||
<hr width="100%">
|
||||
|
||||
|
||||
368
doc/nano.1
368
doc/nano.1
@@ -1,4 +1,4 @@
|
||||
.\" Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||
.\" under the terms of either of the following licenses:
|
||||
@@ -16,27 +16,28 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <https://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH NANO 1 "version 6.0" "December 2021"
|
||||
.TH NANO 1 "July 2026" "GNU nano 9.2"
|
||||
|
||||
.SH NAME
|
||||
nano \- Nano's ANOther editor, inspired by Pico
|
||||
nano \- Nano's ANOther text editor, inspired by Pico
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B nano
|
||||
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
|
||||
.sp
|
||||
.BR nano " [" \fIoptions "] [[" + [ crCR ]( / | ? ) \fIstring "] " \fIfile ]...
|
||||
.BR nano " [" \fIoptions "] [[" + [ crCR ]{ / | ? } \fIstring "] " \fIfile ]...
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBnano\fP is a small and friendly editor. It copies the look and feel
|
||||
of Pico, but is free software, and implements several features that Pico
|
||||
\fBnano\fR is a small and friendly text editor. It copies the look and feel
|
||||
of Pico, but is free software, and implements a few features that Pico
|
||||
lacks, such as: opening multiple files, scrolling per line, undo/redo,
|
||||
syntax coloring, line numbering, and soft-wrapping overlong lines.
|
||||
.sp
|
||||
When giving a filename on the command line, the cursor can be put on a
|
||||
specific line by adding the line number with a plus sign (\fB+\fR) before
|
||||
the filename, and even in a specific column by adding it with a comma.
|
||||
(Negative numbers count from the end of the file or line.)
|
||||
Negative numbers count from the end of the file or line.
|
||||
.sp
|
||||
The cursor can be put on the first or last occurrence of a specific string
|
||||
by specifying that string after \fB+/\fR or \fB+?\fR before the filename.
|
||||
The string can be made case sensitive and/or caused to be interpreted as a
|
||||
@@ -53,76 +54,107 @@ the first occurrence of the word "Foo", you would do:
|
||||
As a special case: if instead of a filename a dash (\fB\-\fR) is given,
|
||||
\fBnano\fR will read data from standard input.
|
||||
|
||||
.SH NOTICES
|
||||
Since version 9.0, all lines are scrolled horizontally together
|
||||
(when the cursor approaches the edge), by just the amount needed,
|
||||
instead of scrolling only the current line by a large step.
|
||||
If you prefer the old behavior, you can use \fB\-\-\%solo\fR on the
|
||||
command line or \fBset \%solosidescroll\fR in your \fInanorc\fR.
|
||||
.sp
|
||||
Also since version 9.0, keystrokes \fBM\-<\fR and \fBM\->\fR have
|
||||
been reassigned to the \fB\%scrollleft\fR and \fB\%scrollright\fR functions.
|
||||
If you want those keystrokes to do what they did before version 9.0,
|
||||
add these two lines at the end of your \fInanorc\fR file:
|
||||
.sp
|
||||
.RS 4
|
||||
.B bind M\-< prevbuf main
|
||||
.br
|
||||
.B bind M\-> nextbuf main
|
||||
.RE
|
||||
.sp
|
||||
Since version 8.0, to be newcomer friendly, \fB^F\fR starts a forward search,
|
||||
\fB^B\fR starts a backward search, \fBM\-F\fR searches the next occurrence
|
||||
forward, and \fBM\-B\fR searches the next occurrence backward. If you want
|
||||
those keystrokes to do what they did before version 8.0, add the following
|
||||
four lines at the end of your \fInanorc\fR file:
|
||||
.sp
|
||||
.RS 4
|
||||
.B bind ^F forward main
|
||||
.br
|
||||
.B bind ^B back main
|
||||
.br
|
||||
.B bind M\-F formatter main
|
||||
.br
|
||||
.B bind M\-B linter main
|
||||
.RE
|
||||
.sp
|
||||
|
||||
.SH EDITING
|
||||
Entering text and moving around in a file is straightforward: typing the
|
||||
Entering text and moving around in a file are straightforward: typing the
|
||||
letters and using the normal cursor movement keys. Commands are entered
|
||||
by using the Control (^) and the Alt or Meta (M\-) keys.
|
||||
Typing \fB^K\fR deletes the current line and puts it in the cutbuffer.
|
||||
Consecutive \fB^K\fRs will put all deleted lines together in the cutbuffer.
|
||||
Any cursor movement or executing any other command will cause the next
|
||||
\fB^K\fR to overwrite the cutbuffer. A \fB^U\fR will paste the current
|
||||
Consecutive \fB^K\fRs put all deleted lines together in the cutbuffer.
|
||||
Any cursor movement or executing any other command causes the next
|
||||
\fB^K\fR to overwrite the cutbuffer. A \fB^U\fR pastes the current
|
||||
contents of the cutbuffer at the current cursor position.
|
||||
.sp
|
||||
When a more precise piece of text needs to be cut or copied, you can mark
|
||||
its start with \fB^6\fR, move the cursor to its end (the marked text will be
|
||||
highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to the
|
||||
cutbuffer. You can also save the marked text to a file with \fB^O\fR, or
|
||||
spell check it with \fB^T^T\fR.
|
||||
its start with \fB^6\fR, move the cursor to its end (the marked text is
|
||||
highlighted), and then use \fB^K\fR to cut it, or \fBM\-6\fR to copy it to
|
||||
the cutbuffer. You can also save the marked text to a file with \fB^O\fR,
|
||||
or spell check it with \fB^T^T\fR.
|
||||
.sp
|
||||
On some terminals, text can be selected also by holding down Shift while
|
||||
using the arrow keys. Holding down the Ctrl or Alt key too will increase
|
||||
using the arrow keys. Holding down the Ctrl or Alt key too increases
|
||||
the stride.
|
||||
Any cursor movement without Shift being held will cancel such a selection.
|
||||
Any cursor movement without Shift being held cancels such a selection.
|
||||
.sp
|
||||
Any valid Unicode code point can be inserted into the buffer by typing
|
||||
\fBM\-V\fR followed by the hexadecimal digits of the code point (concluded
|
||||
with \fB<Space>\fR or \fB<Enter>\fR when it are fewer than six digits).
|
||||
A literal control code (except \fB^J\fR) can be inserted by typing
|
||||
\fBM\-V\fR followed by the pertinent keystroke.
|
||||
.sp
|
||||
The two lines at the bottom of the screen show some important commands;
|
||||
the built-in help (\fB^G\fR) lists all the available ones.
|
||||
The default key bindings can be changed via a \fInanorc\fR file -- see
|
||||
The default key bindings can be changed via a \fInanorc\fR file \[em] see
|
||||
.BR nanorc (5).
|
||||
|
||||
.SH NOTICE
|
||||
Since version 4.0, \fBnano\fR by default:
|
||||
.sp
|
||||
.RS 4
|
||||
\(bu does not automatically hard-wrap lines that become overlong,
|
||||
.br
|
||||
\(bu includes the line below the title bar in the editing area,
|
||||
.br
|
||||
\(bu does linewise (smooth) scrolling.
|
||||
.RE
|
||||
.sp
|
||||
If you want the old, Pico behavior back, you can use \fB\-\-breaklonglines\fR,
|
||||
\fB\-\-emptyline\fR, and \fB\-\-jumpyscrolling\fR (or \fB\-bej\fR for short).
|
||||
With \fB^S^X\fR you can save the buffer and exit from \fBnano\fR.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BR \-A ", " \-\-smarthome
|
||||
Make the Home key smarter. When Home is pressed anywhere but at the
|
||||
very beginning of non-whitespace characters on a line, the cursor will
|
||||
jump to that beginning (either forwards or backwards). If the cursor is
|
||||
already at that position, it will jump to the true beginning of the
|
||||
line.
|
||||
very beginning of non-whitespace characters on a line, the cursor jumps
|
||||
to that beginning (either forwards or backwards). If the cursor is
|
||||
already at that position, it jumps to the true beginning of the line.
|
||||
.TP
|
||||
.BR \-B ", " \-\-backup
|
||||
When saving a file, back up the previous version of it, using the current
|
||||
filename suffixed with a tilde (\fB~\fP).
|
||||
filename suffixed with a tilde (\fB\[ti]\fR).
|
||||
.TP
|
||||
.BR \-C\ \fIdirectory ", " \-\-backupdir= \fIdirectory
|
||||
Make and keep not just one backup file, but make and keep a uniquely
|
||||
numbered one every time a file is saved -- when backups are enabled (\fB\-B\fR).
|
||||
The uniquely numbered files are stored in the specified \fIdirectory\fR.
|
||||
.BI \-C " directory\fR, " \-\-backupdir= directory
|
||||
Make and keep not just one backup file, but make and keep a uniquely numbered
|
||||
one every time a file is saved \[em] when backups are enabled (\fB\-B\fR).
|
||||
The uniquely numbered files are stored in the specified \fI\%directory\fR.
|
||||
.TP
|
||||
.BR \-D ", " \-\-boldtext
|
||||
For the interface, use bold instead of reverse video. This will be overridden
|
||||
by setting the options \fBtitlecolor\fP, \fBstatuscolor\fP, \fBkeycolor\fP,
|
||||
\fBfunctioncolor\fP, \fBnumbercolor\fP, and/or \fBselectedcolor\fP in your
|
||||
nanorc file. See \fBnanorc\fR(5).
|
||||
For the interface, use bold instead of reverse video.
|
||||
This can be overridden for specific elements by setting the options
|
||||
\fB\%titlecolor\fR, \fB\%statuscolor\fR, \fB\%promptcolor\fR,
|
||||
\fB\%minicolor\fR, \fB\%keycolor\fR, \fB\%numbercolor\fR, and/or
|
||||
\fB\%selectedcolor\fR in your \fInanorc\fR file. See \fBnanorc\fR(5).
|
||||
.TP
|
||||
.BR \-E ", " \-\-tabstospaces
|
||||
Convert each typed tab to spaces -- to the number of spaces
|
||||
Convert each typed tab to spaces \[em] to the number of spaces
|
||||
that a tab at that position would take up.
|
||||
(Note: pasted tabs are not converted.)
|
||||
.TP
|
||||
.BR \-F ", " \-\-multibuffer
|
||||
.BR \-F ", " \-\-newbuffer
|
||||
Read a file into a new buffer by default.
|
||||
(The old form of this option, \fB\-\-\%multibuffer\fR, is deprecated.)
|
||||
.TP
|
||||
.BR \-G ", " \-\-locking
|
||||
Use vim-style file locking when editing files.
|
||||
@@ -134,17 +166,17 @@ executed commands, so they can be easily reused in later sessions.
|
||||
.BR \-I ", " \-\-ignorercfiles
|
||||
Don't look at the system's \fInanorc\fR nor at the user's \fInanorc\fR.
|
||||
.TP
|
||||
.BR \-J\ \fInumber ", " \-\-guidestripe= \fInumber
|
||||
.BI \-J " number\fR, " \-\-guidestripe= number
|
||||
Draw a vertical stripe at the given column, to help judge the width of the
|
||||
text. (The color of the stripe can be changed with \fBset stripecolor\fR
|
||||
text. (The color of the stripe can be changed with \fBset \%stripecolor\fR
|
||||
in your \fInanorc\fR file.)
|
||||
.TP
|
||||
.BR \-K ", " \-\-rawsequences
|
||||
Interpret escape sequences directly, instead of asking \fBncurses\fR
|
||||
Interpret escape sequences directly, instead of asking \fI\%ncurses\fR
|
||||
to translate them. (If you need this option to get some keys to work
|
||||
properly, it means that the terminfo terminal description that is used
|
||||
does not fully match the actual behavior of your terminal. This can
|
||||
happen when you ssh into a BSD machine, for example.)
|
||||
properly, it means that the \fI\%terminfo\fR terminal description that
|
||||
is used does not fully match the actual behavior of your terminal.
|
||||
This can happen when you ssh into a BSD machine, for example.)
|
||||
Using this option disables \fBnano\fR's mouse support.
|
||||
.TP
|
||||
.BR \-L ", " \-\-nonewlines
|
||||
@@ -156,7 +188,7 @@ Snip trailing whitespace from the wrapped line when automatic
|
||||
hard-wrapping occurs or when text is justified.
|
||||
.TP
|
||||
.BR \-N ", " \-\-noconvert
|
||||
Disable automatic conversion of files from DOS/Mac format.
|
||||
Disable automatic conversion of files from DOS format.
|
||||
.TP
|
||||
.BR \-O ", " \-\-bookstyle
|
||||
When justifying, treat any line that starts with whitespace as the
|
||||
@@ -165,38 +197,49 @@ beginning of a paragraph (unless auto-indenting is on).
|
||||
.BR \-P ", " \-\-positionlog
|
||||
For the 200 most recent files, log the last position of the cursor,
|
||||
and place it at that position again upon reopening such a file.
|
||||
Also save and restore the positions of any anchors.
|
||||
.TP
|
||||
.BR "\-Q ""\fIregex\fB""" ", " "\-\-quotestr=""" \fIregex """
|
||||
.BI "\-Q """ regex\fB"\fR, " \-\-quotestr=""" regex """"
|
||||
Set the regular expression for matching the quoting part of a line.
|
||||
The default value is "\fB^([\ \\t]*([!#%:;>|}]|//))+\fR".
|
||||
(Note that \fB\\t\fP stands for an actual Tab.)
|
||||
(Note that \fB\\t\fR stands for an actual Tab.)
|
||||
This makes it possible to rejustify blocks of quoted text when composing
|
||||
email, and to rewrap blocks of line comments when writing source code.
|
||||
.TP
|
||||
.BR \-R ", " \-\-restricted
|
||||
Restricted mode: don't read or write to any file not specified on the
|
||||
command line. This means: don't read or write history files;
|
||||
don't allow suspending; don't allow spell checking;
|
||||
don't allow a file to be appended to, prepended to, or saved under a
|
||||
different name if it already has one; and don't make backup files.
|
||||
Restricted mode can also be activated by invoking \fBnano\fP
|
||||
with any name beginning with 'r' (e.g. "rnano").
|
||||
Read and write only the \fIfile\fR (or files) specified on the command line.
|
||||
This means: don't read or write the history files; don't allow suspending;
|
||||
don't allow spell checking; don't allow executing any command in the shell;
|
||||
don't allow the current buffer to be saved under a different name; don't
|
||||
allow appending or prepending to any file; and don't make backup files.
|
||||
.sp
|
||||
As an exception, before the specified file or files, the \fInanorc\fR files
|
||||
are read, to allow customization. If customization should not be allowed,
|
||||
use option \fB\-I\fR (\fB\-\-\%ignorercfiles\fR) as well.
|
||||
.sp
|
||||
When no \fIfile\fR is specified on the command line, restricted mode
|
||||
allows you to save the contents that you type into the new buffer
|
||||
under any name, except that existing files may not be overwritten.
|
||||
If the places where this new file may be created should be limited,
|
||||
then use option \fB\-o\fR (\fB\-\-\%operatingdir\fR) as well.
|
||||
.sp
|
||||
Restricted mode can also be activated by invoking \fBnano\fR
|
||||
with a name beginning with 'r' (for example: \fBrnano\fR).
|
||||
.TP
|
||||
.BR \-S ", " \-\-softwrap
|
||||
Display over multiple screen rows lines that exceed the screen's width.
|
||||
(You can make this soft-wrapping occur at whitespace instead of rudely at
|
||||
the screen's edge, by using also \fB\-\-atblanks\fR.)
|
||||
(The old short option, \fB\-$\fR, is deprecated.)
|
||||
the screen's edge, by using also \fB\-\-\%atblanks\fR.)
|
||||
.TP
|
||||
.BR \-T\ \fInumber ", " \-\-tabsize= \fInumber
|
||||
Set the size (width) of a tab to \fInumber\fP columns. The value of
|
||||
\fInumber\fR must be greater than 0. The default value is \fB8\fR.
|
||||
.BI \-T " number\fR, " \-\-tabsize= number
|
||||
Set the size (width) of a tab to \fI\%number\fR columns. The value of
|
||||
\fI\%number\fR must be greater than 0. The default value is \fB8\fR.
|
||||
.TP
|
||||
.BR \-U ", " \-\-quickblank
|
||||
Make status-bar messages disappear after 1 keystroke instead of after 20.
|
||||
Note that option \fB\-c\fR (\fB\-\-constantshow\fR) overrides this.
|
||||
When option \fB\-\-minibar\fR or \fB\-\-zero\fR is in effect,
|
||||
\fB\-\-quickblank\fR makes a message disappear after
|
||||
Note that option \fB\-c\fR (\fB\-\-\%constantshow\fR) overrides this.
|
||||
When option \fB\-\-\%minibar\fR or \fB\-\-\%zero\fR is in effect,
|
||||
\fB\-\-\%quickblank\fR makes a message disappear after
|
||||
0.8 seconds instead of after the default 1.5 seconds.
|
||||
.
|
||||
.TP
|
||||
@@ -207,14 +250,14 @@ Show the current version number and exit.
|
||||
Detect word boundaries differently by treating punctuation
|
||||
characters as part of a word.
|
||||
.TP
|
||||
.BR "\-X ""\fIcharacters\fB""" ", " "\-\-wordchars=""" \fIcharacters """
|
||||
.BI "\-X """ characters\fB"\fR, " \-\-wordchars=""" characters """"
|
||||
Specify which other characters (besides the normal alphanumeric ones)
|
||||
should be considered as part of a word. When using this option, you
|
||||
probably want to omit \fB\-W\fR (\fB\-\-wordbounds\fR).
|
||||
probably want to omit \fB\-W\fR (\fB\-\-\%wordbounds\fR).
|
||||
.TP
|
||||
.BR \-Y\ \fIname ", " \-\-syntax= \fIname
|
||||
.BI \-Y " name\fR, " \-\-syntax= name
|
||||
Specify the name of the syntax highlighting to use from among the ones
|
||||
defined in the \fInanorc\fP files.
|
||||
defined in the \fInanorc\fR files.
|
||||
.TP
|
||||
.BR \-Z ", " \-\-zap
|
||||
Let an unmodified Backspace or Delete erase the marked region
|
||||
@@ -225,13 +268,16 @@ When doing soft line wrapping, wrap lines at whitespace
|
||||
instead of always at the edge of the screen.
|
||||
.TP
|
||||
.BR \-b ", " \-\-breaklonglines
|
||||
Automatically hard-wrap the current line when it becomes overlong.
|
||||
(This option is the opposite of \fB\-w\fR (\fB\-\-nowrap\fR) --
|
||||
Automatically hard-wrap the current line when it becomes overlong,
|
||||
that is: when it becomes wider than the value given with \fB\-r\fR
|
||||
(\fB\-\-fill\fR). The default value for \fB\-r\fR is the terminal's
|
||||
width minus eight.
|
||||
(This option is the opposite of \fB\-w\fR (\fB\-\-\%nowrap\fR) \[em]
|
||||
the last one given takes effect.)
|
||||
.TP
|
||||
.BR \-c ", " \-\-constantshow
|
||||
Constantly show the cursor position on the status bar.
|
||||
Note that this overrides option \fB\-U\fR (\fB\-\-quickblank\fR).
|
||||
Constantly report the cursor position on the status bar.
|
||||
Note that this overrides option \fB\-U\fR (\fB\-\-\%quickblank\fR).
|
||||
.TP
|
||||
.BR \-d ", " \-\-rebinddelete
|
||||
Interpret the Delete and Backspace keys differently so that both Backspace
|
||||
@@ -241,9 +287,9 @@ system either Backspace acts like Delete or Delete acts like Backspace.
|
||||
.BR \-e ", " \-\-emptyline
|
||||
Do not use the line below the title bar, leaving it entirely blank.
|
||||
.TP
|
||||
.BR \-f\ \fIfile ", " \-\-rcfile= \fIfile
|
||||
Read only this \fIfile\fR for setting nano's options, instead of reading
|
||||
both the system-wide and the user's nanorc files.
|
||||
.BI \-f " file\fR, " \-\-rcfile= file
|
||||
Read only this \fIfile\fR for setting \fBnano\fR's options, instead of reading
|
||||
both the system-wide and the user's \fInanorc\fR files.
|
||||
.TP
|
||||
.BR \-g ", " \-\-showcursor
|
||||
Make the cursor visible in the file browser (putting it on the
|
||||
@@ -272,59 +318,59 @@ Display line numbers to the left of the text area.
|
||||
.BR \-m ", " \-\-mouse
|
||||
Enable mouse support, if available for your system. When enabled, mouse
|
||||
clicks can be used to place the cursor, set the mark (with a double
|
||||
click), and execute shortcuts. The mouse will work in the X Window
|
||||
click), and execute shortcuts. The mouse works in the X Window
|
||||
System, and on the console when gpm is running. Text can still be
|
||||
selected through dragging by holding down the Shift key.
|
||||
.TP
|
||||
.BR \-n ", " \-\-noread
|
||||
Treat any name given on the command line as a new file. This allows
|
||||
\fBnano\fR to write to named pipes: it will start with a blank buffer,
|
||||
and will write to the pipe when the user saves the "file". This way
|
||||
\fBnano\fR to write to named pipes: it starts with a blank buffer,
|
||||
and writes to the pipe when the user saves the \[lq]file\[rq]. This way
|
||||
\fBnano\fR can be used as an editor in combination with for instance
|
||||
\fBgpg\fR without having to write sensitive data to disk first.
|
||||
.TP
|
||||
.BR \-o\ \fIdirectory ", " \-\-operatingdir= \fIdirectory
|
||||
Set the operating directory. This makes \fBnano\fP set up something
|
||||
similar to a chroot.
|
||||
.BI \-o " directory\fR, " \-\-operatingdir= directory
|
||||
Change to the given \fI\%directory\fR, and allow reading and writing
|
||||
files only in this directory and its subdirectories.
|
||||
.TP
|
||||
.BR \-p ", " \-\-preserve
|
||||
Preserve the XON and XOFF sequences (\fB^Q\fR and \fB^S\fR) so they
|
||||
will be caught by the terminal.
|
||||
Preserve the XOFF and XON sequences (\fB^S\fR and \fB^Q\fR) so that
|
||||
they are caught by the terminal (stopping and resuming the output).
|
||||
Note that option \fB\-/\fR (\fB\-\-\%modernbindings\fR) overrides this.
|
||||
.TP
|
||||
.BR \-q ", " \-\-indicator
|
||||
Display a "scrollbar" on the righthand side of the edit window.
|
||||
Display a \[lq]scrollbar\[rq] on the righthand side of the edit window.
|
||||
It shows the position of the viewport in the buffer
|
||||
and how much of the buffer is covered by the viewport.
|
||||
.TP
|
||||
.BR \-r\ \fInumber ", " \-\-fill= \fInumber
|
||||
.BI \-r " number\fR, " \-\-fill= number
|
||||
Set the target width for justifying and automatic hard-wrapping at this
|
||||
\fInumber\fR of columns. If the value is 0 or less, wrapping will occur
|
||||
at the width of the screen minus \fInumber\fR columns, allowing the wrap
|
||||
\fI\%number\fR of columns. If the value is 0 or less, wrapping occurs
|
||||
at the width of the screen minus \fI\%number\fR columns, allowing the wrap
|
||||
point to vary along with the width of the screen if the screen is resized.
|
||||
The default value is \fB\-8\fR.
|
||||
.TP
|
||||
.B "\-s ""\fIprogram\fR [\fIargument \fR...]\fB""\fR, \fB\-\-speller=""\fIprogram\fR [\fIargument \fR...]\fB"""
|
||||
Use this command to perform spell checking and correcting, instead of
|
||||
using the built-in corrector that calls \fBhunspell\fR(1) or \fBspell\fR(1).
|
||||
using the built-in corrector that calls \fB\%hunspell\fR(1) or \fBspell\fR(1).
|
||||
.TP
|
||||
.BR \-t ", " \-\-saveonexit
|
||||
Save a changed buffer without prompting (when exiting with \fB^X\fR).
|
||||
(The old form of the long option, \fB\-\-tempfile\fR, is deprecated.)
|
||||
.TP
|
||||
.BR \-u ", " \-\-unix
|
||||
Save a file by default in Unix format. This overrides nano's
|
||||
Save a file by default in Unix format. This overrides \fBnano\fR's
|
||||
default behavior of saving a file in the format that it had.
|
||||
(This option has no effect when you also use \fB\-\-noconvert\fR.)
|
||||
(This option has no effect when you also use \fB\-\-\%noconvert\fR.)
|
||||
.TP
|
||||
.BR \-v ", " \-\-view
|
||||
Just view the file and disallow editing: read-only mode.
|
||||
This mode allows the user to open also other files for viewing,
|
||||
unless \fB\-\-restricted\fR is given too.
|
||||
unless \fB\-\-\%restricted\fR is given too.
|
||||
.TP
|
||||
.BR \-w ", " \-\-nowrap
|
||||
Do not automatically hard-wrap the current line when it becomes overlong.
|
||||
This is the default. (This option is the opposite of \fB\-b\fR
|
||||
(\fB\-\-breaklonglines\fR) -- the last one given takes effect.)
|
||||
(\fB\-\-\%breaklonglines\fR) \[em] the last one given takes effect.)
|
||||
.TP
|
||||
.BR \-x ", " \-\-nohelp
|
||||
Don't show the two help lines at the bottom of the screen.
|
||||
@@ -332,10 +378,22 @@ Don't show the two help lines at the bottom of the screen.
|
||||
.BR \-y ", " \-\-afterends
|
||||
Make Ctrl+Right and Ctrl+Delete stop at word ends instead of beginnings.
|
||||
.TP
|
||||
.BR \-z ", " \-\-suspendable
|
||||
Obsolete option; ignored. Suspension is enabled by default,
|
||||
reachable via \fB^T^Z\fR. (If you want a plain \fB^Z\fR to
|
||||
suspend nano, add \fBbind ^Z suspend main\fR to your nanorc.)
|
||||
.BR \-z ", " \-\-listsyntaxes
|
||||
List the names of the available syntaxes and exit.
|
||||
.TP
|
||||
.BR \-! ", " \-\-magic
|
||||
When neither the file's name nor its first line give a clue,
|
||||
try using \fI\%libmagic\fR to determine the applicable syntax.
|
||||
.TP
|
||||
.BR \-@ ", " \-\-colonparsing
|
||||
When a filename given on the command line ends in a colon plus digits
|
||||
and this filename does not exist, then snip the colon plus digits and
|
||||
understand the digits as a line number. If the trimmed filename does
|
||||
not exist either, then repeat the process and understand the obtained
|
||||
two numbers as line and column number. But if the doubly trimmed
|
||||
filename does not exist either, then forget the trimming and accept
|
||||
the original filename as is. To disable this colon parsing for some
|
||||
file, use \fB+1\fR or similar before the relevant filename.
|
||||
.TP
|
||||
.BR \-% ", " \-\-stateflags
|
||||
Use the top-right corner of the screen for showing some state flags:
|
||||
@@ -348,31 +406,48 @@ filename in the center of the title bar.
|
||||
.BR \-_ ", " \-\-minibar
|
||||
Suppress the title bar and instead show information about
|
||||
the current buffer at the bottom of the screen, in the space
|
||||
for the status bar. In this "minibar" the filename is shown
|
||||
for the status bar. In this \[lq]mini bar\[rq] the filename is shown
|
||||
on the left, followed by an asterisk if the buffer has been modified.
|
||||
On the right are displayed the current line and column number, the
|
||||
code of the character under the cursor (in Unicode format: U+xxxx),
|
||||
the same flags as are shown by \fB\-\-stateflags\fR, and a percentage
|
||||
the same flags as are shown by \fB\-\-\%stateflags\fR, and a percentage
|
||||
that expresses how far the cursor is into the file (linewise).
|
||||
When a file is loaded or saved, and also when switching between buffers,
|
||||
the number of lines in the buffer is displayed after the filename.
|
||||
This number is cleared upon the next keystroke, or replaced with an
|
||||
[i/n] counter when multiple buffers are open.
|
||||
The line plus column numbers and the character code are displayed only when
|
||||
\fB\-\-constantshow\fR is used, and can be toggled on and off with \fBM-C\fR.
|
||||
The state flags are displayed only when \fB\-\-stateflags\fR is used.
|
||||
\fB\-\-\%constantshow\fR is used, and can be toggled on and off with \fBM\-C\fR.
|
||||
The state flags are displayed only when \fB\-\-\%stateflags\fR is used.
|
||||
.TP
|
||||
.BR \-0 ", " \-\-zero
|
||||
Hide all elements of the interface (title bar, status bar, and help lines)
|
||||
and use all rows of the terminal for showing the contents of the buffer.
|
||||
The status bar appears only when there is a significant message,
|
||||
and disappears after 1.5 seconds or upon the next keystroke.
|
||||
With \fBM-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM-X\fR the help lines.
|
||||
With \fBM\-Z\fR the title bar plus status bar can be toggled.
|
||||
With \fBM\-X\fR the help lines.
|
||||
.TP
|
||||
.BR \-! ", " \-\-magic
|
||||
When neither the file's name nor its first line give a clue,
|
||||
try using libmagic to determine the applicable syntax.
|
||||
.BR \-1 ", " \-\-solosidescroll
|
||||
When the cursor approaches the right edge of the edit window, scroll only the
|
||||
current line sideways by a large amount, instead of scrolling all visible lines
|
||||
sideways by just the amount needed to keep the cursor in view.
|
||||
This latter whole-window smooth sideways scrolling is the new default behavior.
|
||||
The single-line jerky sideways scrolling enabled by this option was the old
|
||||
behavior \[em] the only behavior that \fBnano\fR knew.
|
||||
.TP
|
||||
.BR \-/ ", " \-\-modernbindings
|
||||
Use key bindings similar to the ones that most modern programs use:
|
||||
\fB^X\fR cuts, \fB^C\fR copies, \fB^V\fR pastes,
|
||||
\fB^Z\fR undoes, \fB^Y\fR redoes,
|
||||
\fB^F\fR searches forward, \fB^G\fR searches next,
|
||||
\fB^S\fR saves, \fB^O\fR opens a file, \fB^Q\fR quits,
|
||||
and (when the terminal permits) \fB^H\fR shows help.
|
||||
Furthermore, \fB^A\fR sets the mark, \fB^B\fR searches backward,
|
||||
\fB^D\fR searches previous, \fB^R\fR makes replacements,
|
||||
\fB^P\fR shows the position, \fB^T\fR goes to a line,
|
||||
\fB^W\fR writes out a file, and \fB^E\fR executes a command.
|
||||
Note that this option overrides option \fB\-p\fR (\fB\-\-\%preserve\fR).
|
||||
|
||||
.SH TOGGLES
|
||||
Several of the above options can be switched on and off also while
|
||||
@@ -387,32 +462,61 @@ the help viewer and the linter. All other toggles work in
|
||||
the main menu only.
|
||||
|
||||
.SH FILES
|
||||
When \fB\-\-rcfile\fR is given, \fBnano\fR will read just the specified file
|
||||
for setting its options and syntaxes and key bindings. Without that option,
|
||||
\fBnano\fR will read two configuration files: first the system's
|
||||
When \fB\-\-\%rcfile\fR is given, \fBnano\fR reads just the specified file
|
||||
for setting its options and syntaxes and key bindings. Without that
|
||||
option, \fBnano\fR reads two configuration files: first the system's
|
||||
\fInanorc\fR (if it exists), and then the user's \fInanorc\fR (if it
|
||||
exists), either \fI~/.nanorc\fR or \fI$XDG_CONFIG_HOME/nano/nanorc\fR
|
||||
or \fI~/.config/nano/nanorc\fR, whichever is encountered first. See
|
||||
exists), either \fI\%\[ti]/.nanorc\fR or \fI\%$XDG_CONFIG_HOME/\:nano/\:nanorc\fR
|
||||
or \fI\%\[ti]/.config/\:nano/\:nanorc\fR, whichever is encountered first. See
|
||||
.BR nanorc (5)
|
||||
for more information on the possible contents of those files.
|
||||
.sp
|
||||
See \fI/usr/share/nano/\fR and \fI/usr/share/nano/extra/\fR
|
||||
See \fI/usr/\:share/\:nano/\fR and \fI/usr/\:share/\:nano/\:extra/\fR
|
||||
for available syntax-coloring definitions.
|
||||
|
||||
.SH EXIT STATUS
|
||||
.TP
|
||||
.B 0
|
||||
The editor finished normally.
|
||||
.TP
|
||||
.B 1
|
||||
An invalid option or option argument was given.
|
||||
.TP
|
||||
.B 2
|
||||
The last open buffer was discarded (with \fB^O^Q\fR or \fB^X^Q\fR).
|
||||
|
||||
.SH NOTES
|
||||
If no alternative spell checker command is specified on the command
|
||||
line nor in one of the \fInanorc\fP files, \fBnano\fP will check the
|
||||
\fBSPELL\fP environment variable for one.
|
||||
Suspension is enabled by default, reachable via \fB^T^Z\fR.
|
||||
(If you want a plain \fB^Z\fR to suspend nano, add
|
||||
\fBbind ^Z suspend main\fR to your \fInanorc\fR.)
|
||||
.sp
|
||||
In some cases \fBnano\fP will try to dump the buffer into an emergency
|
||||
file. This will happen mainly if \fBnano\fP receives a SIGHUP or
|
||||
SIGTERM or runs out of memory. It will write the buffer into a file
|
||||
named \fInano.save\fP if the buffer didn't have a name already, or will
|
||||
add a ".save" suffix to the current filename. If an emergency file with
|
||||
that name already exists in the current directory, it will add ".save"
|
||||
plus a number (e.g.\& ".save.1") to the current filename in order to make
|
||||
it unique. In multibuffer mode, \fBnano\fP will write all the open
|
||||
buffers to their respective emergency files.
|
||||
At a Yes-No prompt, \fB^Y\fR can be used for "Yes", \fB^N\fR for "No",
|
||||
and \fB^A\fR for "All".
|
||||
(And when exiting, \fB^Q\fR can be used for "Quit with error".)
|
||||
These unlisted bindings work in any locale.
|
||||
.sp
|
||||
When you want to copy marked text from \fBnano\fR to the system's clipboard,
|
||||
see one of the examples in the \fBnanorc\fR(5) man page.
|
||||
.sp
|
||||
If no alternative spell checker command is specified on the command
|
||||
line nor in one of the \fInanorc\fR files, \fBnano\fR checks the
|
||||
\fBSPELL\fR environment variable for one.
|
||||
.sp
|
||||
In some cases \fBnano\fR tries to dump the buffer into an emergency file.
|
||||
This happens mainly if \fBnano\fR receives a SIGHUP or SIGTERM or runs out
|
||||
of memory. It writes the buffer into a file named \fI\%nano.save\fR if the
|
||||
buffer didn't have a name already, or adds a ".save" suffix to the current
|
||||
filename. If an emergency file with that name already exists in the
|
||||
current directory, it adds ".save" plus a number (for example: ".save.1") to
|
||||
the current filename in order to make it unique. When multiple buffers are
|
||||
open, \fBnano\fR writes each modified buffer to its respective emergency file.
|
||||
.sp
|
||||
The complete manual is maintained in Texinfo format.
|
||||
You can read it with \fBinfo nano\fR, or at
|
||||
.IR https://nano\-editor.org/dist/latest/nano.html .
|
||||
.sp
|
||||
If you have any question about how to use \fBnano\fR in some specific
|
||||
situation, you can ask on \fIhelp\-nano@gnu.org\fR.
|
||||
|
||||
.SH BUGS
|
||||
The recording and playback of keyboard macros works correctly only on a
|
||||
@@ -423,7 +527,7 @@ Please report any other bugs that you encounter via:
|
||||
.br
|
||||
.IR https://savannah.gnu.org/bugs/?group=nano .
|
||||
.sp
|
||||
When nano crashes, it will save any modified buffers to emergency .save files.
|
||||
When \fBnano\fR crashes, it saves any modified buffers to emergency \fI.save\fR files.
|
||||
If you are able to reproduce the crash and you want to get a backtrace, define
|
||||
the environment variable \fBNANO_NOCATCH\fR.
|
||||
|
||||
@@ -433,4 +537,4 @@ the environment variable \fBNANO_NOCATCH\fR.
|
||||
.SH SEE ALSO
|
||||
.BR nanorc (5)
|
||||
.sp
|
||||
\fI/usr/share/doc/nano/\fP (or equivalent on your system)
|
||||
\fI/usr/share/doc/nano/\fR (or equivalent on your system)
|
||||
|
||||
750
doc/nano.texi
750
doc/nano.texi
File diff suppressed because it is too large
Load Diff
605
doc/nanorc.5
605
doc/nanorc.5
File diff suppressed because it is too large
Load Diff
33
doc/rnano.1
33
doc/rnano.1
@@ -1,4 +1,4 @@
|
||||
.\" Copyright (C) 2002-2007, 2014-2021 Free Software Foundation, Inc.
|
||||
.\" Copyright (C) 2002-2007, 2014-2026 Free Software Foundation, Inc.
|
||||
.\"
|
||||
.\" This document is dual-licensed. You may distribute and/or modify it
|
||||
.\" under the terms of either of the following licenses:
|
||||
@@ -16,31 +16,48 @@
|
||||
.\" Documentation License along with this program. If not, see
|
||||
.\" <https://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.TH RNANO 1 "version 6.0" "December 2021"
|
||||
.TH RNANO 1 "July 2026" "GNU nano 9.2"
|
||||
|
||||
.SH NAME
|
||||
rnano \- a restricted nano
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B rnano
|
||||
.RI [ options "] [[+" line [, column "]]\ " file "]..."
|
||||
.RI [ options "] [[\fB+" line [\fB, column "]] " file ]...
|
||||
|
||||
.SH DESCRIPTION
|
||||
\fBrnano\fR runs the \fBnano\fR editor in restricted mode. This allows
|
||||
editing only the specified file or files, and doesn't allow the user
|
||||
access to the filesystem nor to a command shell.
|
||||
editing only the \fIfile\fR (or files) specified on the command line.
|
||||
.sp
|
||||
In restricted mode, \fBnano\fR will:
|
||||
.RS 4
|
||||
.IP \[bu] 2
|
||||
not make backups;
|
||||
.IP \[bu]
|
||||
not read nor write the history files;
|
||||
.IP \[bu]
|
||||
not allow suspending;
|
||||
.IP \[bu]
|
||||
not allow spell checking;
|
||||
.IP \[bu]
|
||||
not allow running any command in the shell;
|
||||
.IP \[bu]
|
||||
not allow saving the current buffer under a different name;
|
||||
.IP \[bu]
|
||||
not allow inserting another file or opening a new buffer;
|
||||
.IP \[bu]
|
||||
not allow appending or prepending to any file;
|
||||
.IP \[bu]
|
||||
not make backup files nor do spell checking.
|
||||
not allow appending or prepending to any file.
|
||||
.RE
|
||||
.sp
|
||||
As an exception, before the specified file or files, the \fInanorc\fR files
|
||||
are read, to allow customization. If customization should not be allowed,
|
||||
use option \fB\-I\fR (\fB\-\-ignorercfiles\fR) as well.
|
||||
.sp
|
||||
When no \fIfile\fR is specified on the command line, the user may save
|
||||
the contents that they type into the new buffer under any name, except
|
||||
that existing files may not be overwritten. If the places where this
|
||||
new file may be created should be limited, then additionally use the
|
||||
option \fB\-o\fR (\fB\-\-operatingdir\fR).
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
|
||||
@@ -8,6 +8,16 @@
|
||||
## Inside string parameters, quotes should not be escaped -- the last
|
||||
## double quote on the line will be seen as the closing quote.
|
||||
|
||||
## If you want ^F, ^B, M-F and M-B to do what they did before version 8.0:
|
||||
# bind ^F forward main
|
||||
# bind ^B back main
|
||||
# bind M-F formatter main
|
||||
# bind M-B linter main
|
||||
|
||||
## Make M-< and M-> switch between buffers, as they did before version 9.0:
|
||||
# bind M-< prevbuf main
|
||||
# bind M-> nextbuf main
|
||||
|
||||
## Make 'nextword' (Ctrl+Right) and 'chopwordright' (Ctrl+Delete)
|
||||
## stop at word ends instead of at beginnings.
|
||||
# set afterends
|
||||
@@ -44,7 +54,11 @@
|
||||
## Do case-sensitive searches by default.
|
||||
# set casesensitive
|
||||
|
||||
## Constantly display the cursor position in the status bar or minibar.
|
||||
## Interpret digits after a colon after a filename (on the command line)
|
||||
## as the line number to go to in that file.
|
||||
# set colonparsing
|
||||
|
||||
## Constantly report the cursor position, in the status bar or minibar.
|
||||
# set constantshow
|
||||
|
||||
## Use cut-from-cursor-to-end-of-line by default.
|
||||
@@ -58,7 +72,11 @@
|
||||
## will be the terminal's width minus this number.
|
||||
# set fill -8
|
||||
|
||||
## Remember the used search/replace strings for the next session.
|
||||
## Draw a vertical stripe at the given column, to help judge text width.
|
||||
## (This option does not have a default value.)
|
||||
# set guidestripe 75
|
||||
|
||||
## Remember the used search/replace/command strings for the next session.
|
||||
# set historylog
|
||||
|
||||
## Display a "scrollbar" on the righthand side of the edit window.
|
||||
@@ -70,9 +88,8 @@
|
||||
## Display line numbers to the left (and any anchors in the margin).
|
||||
# set linenumbers
|
||||
|
||||
## Enable vim-style lock-files. This is just to let a vim user know you
|
||||
## are editing a file [s]he is trying to edit and vice versa. There are
|
||||
## no plans to implement vim-style undo state in these files.
|
||||
## Let other users (of nano or vim) know that you are editing the file
|
||||
## they are trying to edit, and the other way around.
|
||||
# set locking
|
||||
|
||||
## Fall back to slow libmagic to try and determine an applicable syntax.
|
||||
@@ -88,16 +105,15 @@
|
||||
# set minibar
|
||||
|
||||
## Enable mouse support, if available for your system. When enabled,
|
||||
## mouse clicks can be used to place the cursor, set the mark (with a
|
||||
## double click), and execute shortcuts. The mouse will work in the
|
||||
## mouse clicks can be used to place the cursor, set the mark (with
|
||||
## two clicks), and execute shortcuts. The mouse will work in the
|
||||
## X Window System, and on the console when gpm is running.
|
||||
# set mouse
|
||||
|
||||
## Switch on multiple file buffers (inserting a file will put it into
|
||||
## a separate buffer).
|
||||
# set multibuffer
|
||||
## With ^R, insert a file into a separate buffer by default.
|
||||
# set newbuffer
|
||||
|
||||
## Don't convert files from DOS/Mac format.
|
||||
## Don't convert files from DOS format.
|
||||
# set noconvert
|
||||
|
||||
## Don't display the helpful shortcut lists at the bottom of the screen.
|
||||
@@ -112,14 +128,14 @@
|
||||
## string means the operating-directory feature is turned off.
|
||||
# set operatingdir ""
|
||||
|
||||
## Remember the cursor position in each file for the next editing session.
|
||||
## Remember the position of cursor and anchors for the next editing session.
|
||||
# set positionlog
|
||||
|
||||
## Preserve the XON and XOFF keys (^Q and ^S).
|
||||
# set preserve
|
||||
|
||||
## The characters treated as closing punctuation when justifying paragraphs.
|
||||
## This may not contain blank characters. Only these closing punctuations,
|
||||
## This may not contain blank characters. Only these terminating characters,
|
||||
## optionally followed by closing brackets, can end sentences.
|
||||
# set punct "!.?"
|
||||
|
||||
@@ -142,7 +158,6 @@
|
||||
|
||||
## Save a changed buffer automatically on exit; don't prompt.
|
||||
# set saveonexit
|
||||
## (The old form of this option, 'set tempfile', is deprecated.)
|
||||
|
||||
## Put the cursor on the highlighted item in the file browser, and
|
||||
## show the cursor in the help viewer; useful for people who use a
|
||||
@@ -159,6 +174,9 @@
|
||||
## Spread overlong lines over multiple screen lines.
|
||||
# set softwrap
|
||||
|
||||
## Scroll only the current line sideways (instead of all lines).
|
||||
# set solosidescroll
|
||||
|
||||
## Use this spelling checker instead of the internal one. This option
|
||||
## does not have a default value.
|
||||
# set speller "aspell -x -c"
|
||||
@@ -176,6 +194,9 @@
|
||||
## Snip whitespace at the end of lines when justifying or hard-wrapping.
|
||||
# set trimblanks
|
||||
|
||||
## Save files always in Unix format (also when they were DOS).
|
||||
# set unix
|
||||
|
||||
## The two single-column characters used to display the first characters
|
||||
## of tabs and spaces. 187 in ISO 8859-1 (0000BB in Unicode) and 183 in
|
||||
## ISO-8859-1 (0000B7 in Unicode) seem to be good values for these.
|
||||
@@ -208,9 +229,9 @@
|
||||
# set statuscolor bold,white,green
|
||||
# set errorcolor bold,white,red
|
||||
# set spotlightcolor black,lightyellow
|
||||
# set selectedcolor lightwhite,magenta
|
||||
# set stripecolor ,yellow
|
||||
# set scrollercolor cyan
|
||||
# set selectedcolor lightwhite,#804
|
||||
# set stripecolor ,#444
|
||||
# set scrollercolor slate,#222
|
||||
# set numbercolor cyan
|
||||
# set keycolor cyan
|
||||
# set functioncolor green
|
||||
@@ -233,12 +254,12 @@
|
||||
## For all details, see 'man nanorc', section SYNTAX HIGHLIGHTING.
|
||||
|
||||
## To include most of the existing syntax definitions, you can do:
|
||||
# include "@PKGDATADIR@/*.nanorc"
|
||||
# include @PKGDATADIR@/*.nanorc
|
||||
|
||||
## Or you can select just the ones you need. For example:
|
||||
# include "@PKGDATADIR@/html.nanorc"
|
||||
# include "@PKGDATADIR@/python.nanorc"
|
||||
# include "@PKGDATADIR@/sh.nanorc"
|
||||
# include @PKGDATADIR@/html.nanorc
|
||||
# include @PKGDATADIR@/python.nanorc
|
||||
# include @PKGDATADIR@/sh.nanorc
|
||||
|
||||
## In @PKGDATADIR@/extra/ you can find some syntaxes that are
|
||||
## specific for certain distros or for some less common languages.
|
||||
@@ -248,9 +269,6 @@
|
||||
## independent of the settings of 'tabsize' and 'tabstospaces':
|
||||
# extendsyntax python tabgives " "
|
||||
|
||||
## If <Tab> should always produce an actual TAB when editing a Makefile:
|
||||
# extendsyntax makefile tabgives " "
|
||||
|
||||
|
||||
## === Key bindings ===
|
||||
## For all details, see 'man nanorc', section REBINDING KEYS.
|
||||
@@ -278,44 +296,58 @@
|
||||
# unbind M-T main
|
||||
## (Those functions are still accessible through ^T^J and ^T^V.)
|
||||
|
||||
## For quickly uppercasing or lowercasing the word under the cursor.
|
||||
## (These effectively do a Ctrl+Right followed by a Shift+Ctrl+Left,
|
||||
## and then pipe the selected text through a sed command.)
|
||||
# bind Sh-M-U "Oc[1;6D|sed 's/.*/\U&/'
|
||||
" main
|
||||
## For quickly uppercasing or lowercasing the word that the cursor is on.
|
||||
## (These effectively select a word and pipe it through a sed command.)
|
||||
# bind Sh-M-U "{nextword}{mark}{prevword}{execute}| sed 's/.*/\U&/' {enter}" main
|
||||
# bind Sh-M-L "{nextword}{mark}{prevword}{execute}| sed 's/.*/\L&/' {enter}" main
|
||||
|
||||
## Two ways of copying a marked region to the system clipboard:
|
||||
# bind Sh-M-C "{execute}| xsel -ib {enter}{undo}" main
|
||||
# bind Sh-M-P "{execute}| xclip -select clipboard 1>&- 2>&- {enter}{undo}" main
|
||||
|
||||
## For copying text to the local clipboard via OSC 52 (if terminal supports it):
|
||||
# bind M-* "{execute}|| printf "\033]52;c;%s\007" "$(base64 | tr -d '\n')" {enter}{undo}" main
|
||||
|
||||
## For normalizing Unicode to precomposed characters:
|
||||
# bind Sh-M-N "{execute}| uconv -x nfc {enter}" main
|
||||
|
||||
## For wiping all anchors in a buffer:
|
||||
# bind Sh-M-W "{execute}| cat {enter}" main
|
||||
|
||||
## For snipping trailing blanks when you save a file:
|
||||
# bind ^S "{execute}| sed 's/\s\+$//' {enter}{savefile}" main
|
||||
|
||||
## If you would like nano to have keybindings that are more "usual",
|
||||
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
|
||||
## then uncomment these:
|
||||
## such as ^O for Open, ^F for Find, ^H for Help, and ^Q for Quit,
|
||||
## then uncomment these:
|
||||
#bind ^Q exit all
|
||||
#bind ^S savefile main
|
||||
#bind ^W writeout main
|
||||
#bind ^O insert main
|
||||
#bind ^H help all
|
||||
#bind ^H exit help
|
||||
#bind ^F whereis all
|
||||
#bind ^G findnext all
|
||||
#bind ^B wherewas all
|
||||
#bind ^D findprevious all
|
||||
#bind ^R replace main
|
||||
#bind ^X cut main
|
||||
#bind ^C copy main
|
||||
#bind ^V paste all
|
||||
#bind ^P location main
|
||||
#bind ^E execute main
|
||||
#bind ^A mark main
|
||||
#unbind ^K main
|
||||
#unbind ^U all
|
||||
#unbind ^N main
|
||||
#unbind ^Y all
|
||||
#unbind M-J main
|
||||
#unbind M-T main
|
||||
#bind ^T gotoline main
|
||||
#bind ^T gotodir browser
|
||||
#bind ^T cutrestoffile execute
|
||||
#bind ^L linter execute
|
||||
#bind M-U undo main
|
||||
#bind M-R redo main
|
||||
#bind ^Z undo main
|
||||
# bind ^X cut main
|
||||
# bind ^C copy main
|
||||
# bind ^V paste all
|
||||
# bind ^Q exit all
|
||||
# bind ^S savefile main
|
||||
# bind ^W writeout main
|
||||
# bind ^O insert main
|
||||
# set newbuffer
|
||||
# bind ^H help all
|
||||
# bind ^H exit help
|
||||
# bind ^F whereis all
|
||||
# bind ^G findnext all
|
||||
# bind ^B wherewas all
|
||||
# bind ^D findprevious all
|
||||
# bind ^R replace main
|
||||
# unbind ^U all
|
||||
# unbind ^N main
|
||||
# unbind ^Y all
|
||||
# unbind M-J main
|
||||
# unbind M-T main
|
||||
# bind ^A mark main
|
||||
# bind ^P location main
|
||||
# bind ^T gotoline main
|
||||
# bind ^T gotodir browser
|
||||
# bind ^T cutrestoffile execute
|
||||
# bind ^L linter execute
|
||||
# bind ^E execute main
|
||||
# bind ^K "{mark}{end}{zap}" main
|
||||
# bind ^U "{mark}{home}{zap}" main
|
||||
# bind ^Z undo main
|
||||
# bind ^Y redo main
|
||||
|
||||
@@ -31,6 +31,5 @@ EXTRA_DIST = \
|
||||
threadlib.m4 \
|
||||
uintmax_t.m4 \
|
||||
visibility.m4 \
|
||||
wchar_t.m4 \
|
||||
wint_t.m4 \
|
||||
xsize.m4
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# List of available languages.
|
||||
bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ko ms nb nl pl pt pt_BR ro ru sk sl sr sv tr uk vi zh_CN zh_TW
|
||||
ar bg ca cs da de eo es eu fi fr ga gl hr hu id is it ja ka kk ko ms nb nl pl pt pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN zh_TW
|
||||
|
||||
@@ -7,6 +7,7 @@ src/files.c
|
||||
src/global.c
|
||||
src/help.c
|
||||
src/history.c
|
||||
src/move.c
|
||||
src/nano.c
|
||||
src/prompt.c
|
||||
src/rcfile.c
|
||||
|
||||
1901
po/nano.pot
1901
po/nano.pot
File diff suppressed because it is too large
Load Diff
1943
po/pt_BR.po
1943
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
1888
po/zh_CN.po
1888
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
1888
po/zh_TW.po
1888
po/zh_TW.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION="6.0"
|
||||
VERSION="9.2"
|
||||
|
||||
./configure -C --enable-tiny && make && ./configure -C &&
|
||||
|
||||
@@ -20,7 +20,7 @@ gpg -a -b nano-$VERSION.tar.xz &&
|
||||
gpg --verify nano-$VERSION.tar.gz.asc &&
|
||||
gpg --verify nano-$VERSION.tar.xz.asc &&
|
||||
|
||||
git tag -u A0ACE884 -a v$VERSION -m "the nano $VERSION release" &&
|
||||
git tag -u B8E1961F -a v$VERSION -m "the nano $VERSION release" &&
|
||||
|
||||
make pdf && rm -rf doc/nano.t2p &&
|
||||
scp doc/nano.pdf bens@wh0rd.org:nano.pdf &&
|
||||
|
||||
@@ -16,7 +16,8 @@ winio.o: revision.h
|
||||
# only when the revision actually changed.
|
||||
revision.h: FORCE
|
||||
@[ -f $@ ] || touch $@
|
||||
@echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||
@! git describe >/dev/null 2>&1 || \
|
||||
echo "#define $(SOMETHING)" | cmp -s $@ - || \
|
||||
echo "#define $(SOMETHING)" > $@
|
||||
FORCE:
|
||||
|
||||
@@ -29,6 +30,7 @@ nano_SOURCES = \
|
||||
color.c \
|
||||
cut.c \
|
||||
files.c \
|
||||
folding.c \
|
||||
global.c \
|
||||
help.c \
|
||||
history.c \
|
||||
@@ -41,8 +43,8 @@ nano_SOURCES = \
|
||||
utils.c \
|
||||
winio.c
|
||||
|
||||
nano_LDADD = @LIBINTL@ $(top_builddir)/lib/libgnu.a \
|
||||
$(LIB_CLOCK_GETTIME) $(LIBTHREAD)
|
||||
nano_LDADD = $(top_builddir)/lib/libgnu.a @LIBINTL@ \
|
||||
$(GETRANDOM_LIB) $(CLOCK_TIME_LIB) $(LIBTHREAD)
|
||||
|
||||
install-exec-hook:
|
||||
cd $(DESTDIR)$(bindir) && rm -f rnano && $(LN_S) nano rnano
|
||||
|
||||
351
src/browser.c
351
src/browser.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* browser.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015-2016, 2020 Benno Schulenberg *
|
||||
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2015, 2016, 2020, 2022, 2025 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -34,45 +34,43 @@ static size_t list_length = 0;
|
||||
/* The number of files in the list. */
|
||||
static size_t usable_rows = 0;
|
||||
/* The number of screen rows we can use to display the list. */
|
||||
static size_t piles = 0;
|
||||
static int piles = 0;
|
||||
/* The number of files that we can display per screen row. */
|
||||
static size_t longest = 0;
|
||||
/* The number of columns in the longest filename in the list. */
|
||||
static int gauge = 0;
|
||||
/* The width of a 'pile' -- the widest filename plus ten. */
|
||||
static size_t selected = 0;
|
||||
/* The currently selected filename in the list; zero-based. */
|
||||
|
||||
/* Set filelist to the list of files contained in the directory path,
|
||||
* set list_length to the number of files in that list, set longest to
|
||||
* the width in columns of the longest filename in that list (between 15
|
||||
* and COLS), and set piles to the number of files that we can display
|
||||
* per screen row. And sort the list too. */
|
||||
/* Fill 'filelist' with the names of the files in the given directory, set
|
||||
* 'list_length' to the number of names in that list, set 'gauge' to the
|
||||
* width of the widest filename plus ten, and set 'piles' to the number of
|
||||
* files that can be displayed per screen row. And sort the list too. */
|
||||
void read_the_list(const char *path, DIR *dir)
|
||||
{
|
||||
size_t path_len = strlen(path), index = 0;
|
||||
const struct dirent *nextdir;
|
||||
size_t path_len = strlen(path);
|
||||
const struct dirent *entry;
|
||||
size_t widest = 0;
|
||||
size_t index = 0;
|
||||
|
||||
longest = 0;
|
||||
/* Find the width of the widest filename in the current folder. */
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
size_t span = breadth(entry->d_name);
|
||||
|
||||
/* Find the length of the longest filename in the current folder. */
|
||||
while ((nextdir = readdir(dir)) != NULL) {
|
||||
size_t name_len = breadth(nextdir->d_name);
|
||||
|
||||
if (name_len > longest)
|
||||
longest = name_len;
|
||||
if (span > widest)
|
||||
widest = span;
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Put 10 characters' worth of blank space between columns of filenames
|
||||
* in the list whenever possible, as Pico does. */
|
||||
longest += 10;
|
||||
/* Reserve ten columns for blanks plus file size. */
|
||||
gauge = widest + 10;
|
||||
|
||||
/* If needed, make room for ".. (parent dir)". */
|
||||
if (longest < 15)
|
||||
longest = 15;
|
||||
if (gauge < 15)
|
||||
gauge = 15;
|
||||
/* Make sure we're not wider than the window. */
|
||||
if (longest > COLS)
|
||||
longest = COLS;
|
||||
if (gauge > COLS)
|
||||
gauge = COLS;
|
||||
|
||||
rewinddir(dir);
|
||||
|
||||
@@ -83,20 +81,19 @@ void read_the_list(const char *path, DIR *dir)
|
||||
|
||||
filelist = nmalloc(list_length * sizeof(char *));
|
||||
|
||||
while ((nextdir = readdir(dir)) != NULL && index < list_length) {
|
||||
/* Don't show the "." entry. */
|
||||
if (strcmp(nextdir->d_name, ".") == 0)
|
||||
while ((entry = readdir(dir)) != NULL && index < list_length) {
|
||||
/* Don't show the useless dot item. */
|
||||
if (strcmp(entry->d_name, ".") == 0)
|
||||
continue;
|
||||
|
||||
filelist[index] = nmalloc(path_len + strlen(nextdir->d_name) + 1);
|
||||
sprintf(filelist[index], "%s%s", path, nextdir->d_name);
|
||||
filelist[index] = nmalloc(path_len + strlen(entry->d_name) + 1);
|
||||
sprintf(filelist[index], "%s%s", path, entry->d_name);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
/* Maybe the number of files in the directory decreased between the
|
||||
* first time we scanned and the second time. index is the actual
|
||||
* length of the file list, so record it. */
|
||||
/* Maybe the number of files in the directory decreased between
|
||||
* the first time we scanned and the second time. */
|
||||
list_length = index;
|
||||
|
||||
/* Sort the list of names. */
|
||||
@@ -105,33 +102,28 @@ void read_the_list(const char *path, DIR *dir)
|
||||
/* Calculate how many files fit on a line -- feigning room for two
|
||||
* spaces beyond the right edge, and adding two spaces of padding
|
||||
* between columns. */
|
||||
piles = (COLS + 2) / (longest + 2);
|
||||
piles = (COLS + 2) / (gauge + 2);
|
||||
|
||||
usable_rows = editwinrows - (ISSET(ZERO) && LINES > 1 ? 1 : 0);
|
||||
}
|
||||
|
||||
/* Look for needle. If we find it, set selected to its location.
|
||||
* Note that needle must be an exact match for a file in the list. */
|
||||
void browser_select_dirname(const char *needle)
|
||||
/* Reselect the given file or directory name, if it still exists. */
|
||||
void reselect(const char *name)
|
||||
{
|
||||
size_t looking_at = 0;
|
||||
|
||||
for (; looking_at < list_length; looking_at++) {
|
||||
if (strcmp(filelist[looking_at], needle) == 0) {
|
||||
selected = looking_at;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (looking_at < list_length && strcmp(filelist[looking_at], name) != 0)
|
||||
looking_at++;
|
||||
|
||||
/* If the sought name isn't found, move the highlight so that the
|
||||
* changed selection will be noticed. */
|
||||
if (looking_at == list_length) {
|
||||
/* If the sought name was found, select it; otherwise, just move
|
||||
* the highlight so that the changed selection will be noticed,
|
||||
* but make sure to stay within the current available range. */
|
||||
if (looking_at < list_length)
|
||||
selected = looking_at;
|
||||
else if (selected > list_length)
|
||||
selected = list_length - 1;
|
||||
else
|
||||
--selected;
|
||||
|
||||
/* Make sure we stay within the available range. */
|
||||
if (selected >= list_length)
|
||||
selected = list_length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Display at most a screenful of filenames from the gleaned filelist. */
|
||||
@@ -158,11 +150,11 @@ void browser_refresh(void)
|
||||
size_t infomaxlen = 7;
|
||||
/* The maximum length of the file information in columns:
|
||||
* normally seven, but will be twelve for "(parent dir)". */
|
||||
bool dots = (COLS >= 15 && namelen >= longest - infomaxlen);
|
||||
bool dots = (COLS >= 15 && namelen >= gauge - infomaxlen);
|
||||
/* Whether to put an ellipsis before the filename? We don't
|
||||
* waste space on dots when there are fewer than 15 columns. */
|
||||
char *disp = display_string(thename, dots ?
|
||||
namelen + infomaxlen + 4 - longest : 0, longest, FALSE, FALSE);
|
||||
namelen + infomaxlen + 4 - gauge : 0, gauge, FALSE, FALSE);
|
||||
/* The filename (or a fragment of it) in displayable format.
|
||||
* When a fragment, account for dots plus one space padding. */
|
||||
struct stat state;
|
||||
@@ -170,31 +162,31 @@ void browser_refresh(void)
|
||||
/* If this is the selected item, draw its highlighted bar upfront, and
|
||||
* remember its location to be able to place the cursor on it. */
|
||||
if (index == selected) {
|
||||
wattron(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
mvwprintw(edit, row, col, "%*s", longest, " ");
|
||||
wattron(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||
mvwprintw(midwin, row, col, "%*s", gauge, " ");
|
||||
the_row = row;
|
||||
the_column = col;
|
||||
}
|
||||
|
||||
/* If the name is too long, we display something like "...ename". */
|
||||
if (dots)
|
||||
mvwaddstr(edit, row, col, "...");
|
||||
mvwaddstr(edit, row, dots ? col + 3 : col, disp);
|
||||
mvwaddstr(midwin, row, col, "...");
|
||||
mvwaddstr(midwin, row, dots ? col + 3 : col, disp);
|
||||
|
||||
col += longest;
|
||||
col += gauge;
|
||||
|
||||
/* Show information about the file: "--" for symlinks (except when
|
||||
* they point to a directory) and for files that have disappeared,
|
||||
* "(dir)" for directories, and the file size for normal files. */
|
||||
if (lstat(filelist[index], &state) == -1 || S_ISLNK(state.st_mode)) {
|
||||
if (stat(filelist[index], &state) == -1 || !S_ISDIR(state.st_mode))
|
||||
if (lstat(filelist[index], &state) < 0 || S_ISLNK(state.st_mode)) {
|
||||
if (stat(filelist[index], &state) < 0 || !S_ISDIR(state.st_mode))
|
||||
info = copy_of("--");
|
||||
else
|
||||
/* TRANSLATORS: Try to keep this at most 7 characters. */
|
||||
/* TRANSLATORS: Anything more than 7 cells gets clipped. */
|
||||
info = copy_of(_("(dir)"));
|
||||
} else if (S_ISDIR(state.st_mode)) {
|
||||
if (strcmp(thename, "..") == 0) {
|
||||
/* TRANSLATORS: Try to keep this at most 12 characters. */
|
||||
/* TRANSLATORS: Anything more than 12 cells gets clipped. */
|
||||
info = copy_of(_("(parent dir)"));
|
||||
infomaxlen = 12;
|
||||
} else
|
||||
@@ -223,7 +215,7 @@ void browser_refresh(void)
|
||||
if (result < (1 << 10))
|
||||
sprintf(info, "%4ju %cB", (intmax_t)result, modifier);
|
||||
else
|
||||
/* TRANSLATORS: Try to keep this at most 7 characters.
|
||||
/* TRANSLATORS: Anything more than 7 cells gets clipped.
|
||||
* If necessary, you can leave out the parentheses. */
|
||||
info = mallocstrcpy(info, _("(huge)"));
|
||||
}
|
||||
@@ -235,11 +227,11 @@ void browser_refresh(void)
|
||||
infolen = infomaxlen;
|
||||
}
|
||||
|
||||
mvwaddstr(edit, row, col - infolen, info);
|
||||
mvwaddstr(midwin, row, col - infolen, info);
|
||||
|
||||
/* If this is the selected item, finish its highlighting. */
|
||||
if (index == selected)
|
||||
wattroff(edit, interface_color_pair[SELECTED_TEXT]);
|
||||
wattroff(midwin, interface_color_pair[SELECTED_TEXT]);
|
||||
|
||||
free(disp);
|
||||
free(info);
|
||||
@@ -247,8 +239,8 @@ void browser_refresh(void)
|
||||
/* Add some space between the columns. */
|
||||
col += 2;
|
||||
|
||||
/* If the next entry will not fit on this row, move to next row. */
|
||||
if (col > COLS - longest) {
|
||||
/* If the next item will not fit on this row, move to next row. */
|
||||
if (col > COLS - gauge) {
|
||||
row++;
|
||||
col = 0;
|
||||
}
|
||||
@@ -256,70 +248,46 @@ void browser_refresh(void)
|
||||
|
||||
/* If requested, put the cursor on the selected item and switch it on. */
|
||||
if (ISSET(SHOW_CURSOR)) {
|
||||
wmove(edit, the_row, the_column);
|
||||
wmove(midwin, the_row, the_column);
|
||||
curs_set(1);
|
||||
}
|
||||
|
||||
wnoutrefresh(edit);
|
||||
wnoutrefresh(midwin);
|
||||
}
|
||||
|
||||
/* Look for the given needle in the list of files. If forwards is TRUE,
|
||||
* search forward in the list; otherwise, search backward. */
|
||||
/* Look for the given needle in the list of files, forwards or backwards. */
|
||||
void findfile(const char *needle, bool forwards)
|
||||
{
|
||||
size_t looking_at = selected;
|
||||
/* The location in the file list of the filename we're looking at. */
|
||||
const char *thename;
|
||||
/* The plain filename, without the path. */
|
||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
||||
/* A storage place for the current flag settings. */
|
||||
size_t began_at = selected;
|
||||
|
||||
/* Save the settings of all flags. */
|
||||
memcpy(stash, flags, sizeof(flags));
|
||||
|
||||
/* Search forward, case insensitive, and without regexes. */
|
||||
UNSET(BACKWARDS_SEARCH);
|
||||
UNSET(CASE_SENSITIVE);
|
||||
UNSET(USE_REGEXP);
|
||||
|
||||
/* Step through each filename in the list until a match is found or
|
||||
/* Iterate through the list of filenames, until a match is found or
|
||||
* we've come back to the point where we started. */
|
||||
while (TRUE) {
|
||||
if (forwards) {
|
||||
if (looking_at++ == list_length - 1) {
|
||||
looking_at = 0;
|
||||
if (selected++ == list_length - 1) {
|
||||
selected = 0;
|
||||
statusbar(_("Search Wrapped"));
|
||||
}
|
||||
} else {
|
||||
if (looking_at-- == 0) {
|
||||
looking_at = list_length - 1;
|
||||
if (selected-- == 0) {
|
||||
selected = list_length - 1;
|
||||
statusbar(_("Search Wrapped"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the bare filename, without the path. */
|
||||
thename = tail(filelist[looking_at]);
|
||||
|
||||
/* If the needle matches, we're done. And if we're back at the file
|
||||
* where we started, it is the only occurrence. */
|
||||
if (strstrwrapper(thename, needle, thename)) {
|
||||
if (looking_at == selected)
|
||||
/* When the needle occurs in the basename of the file, we have a match. */
|
||||
if (mbstrcasestr(tail(filelist[selected]), needle)) {
|
||||
if (selected == began_at)
|
||||
statusbar(_("This is the only occurrence"));
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're back at the beginning and didn't find any match... */
|
||||
if (looking_at == selected) {
|
||||
/* When we're back at the starting point without any match... */
|
||||
if (selected == began_at) {
|
||||
not_found_msg(needle);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore the settings of all flags. */
|
||||
memcpy(flags, stash, sizeof(flags));
|
||||
|
||||
/* Select the one we've found. */
|
||||
selected = looking_at;
|
||||
}
|
||||
|
||||
/* Prepare the prompt and ask the user what to search for; then search for it.
|
||||
@@ -330,7 +298,7 @@ void search_filename(bool forwards)
|
||||
int response;
|
||||
|
||||
/* If something was searched for before, show it between square brackets. */
|
||||
if (*last_search != '\0') {
|
||||
if (*last_search) {
|
||||
char *disp = display_string(last_search, 0, COLS / 3, FALSE, FALSE);
|
||||
|
||||
thedefault = nmalloc(strlen(disp) + 7);
|
||||
@@ -356,7 +324,7 @@ void search_filename(bool forwards)
|
||||
}
|
||||
|
||||
/* If the user typed an answer, remember it. */
|
||||
if (*answer != '\0') {
|
||||
if (*answer) {
|
||||
last_search = mallocstrcpy(last_search, answer);
|
||||
#ifdef ENABLE_HISTORIES
|
||||
update_history(&search_history, answer, PRUNE_DUPLICATE);
|
||||
@@ -373,7 +341,7 @@ void research_filename(bool forwards)
|
||||
{
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If nothing was searched for yet, take the last item from history. */
|
||||
if (*last_search == '\0' && searchbot->prev != NULL)
|
||||
if (*last_search == '\0' && searchbot->prev)
|
||||
last_search = mallocstrcpy(last_search, searchbot->prev->data);
|
||||
#endif
|
||||
|
||||
@@ -385,13 +353,13 @@ void research_filename(bool forwards)
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the first file in the list -- called by ^W^Y. */
|
||||
/* Select the first file in the list -- called directly by ^W^Y. */
|
||||
void to_first_file(void)
|
||||
{
|
||||
selected = 0;
|
||||
}
|
||||
|
||||
/* Select the last file in the list -- called by ^W^V. */
|
||||
/* Select the last file in the list -- called directly by ^W^V. */
|
||||
void to_last_file(void)
|
||||
{
|
||||
selected = list_length - 1;
|
||||
@@ -404,7 +372,7 @@ char *strip_last_component(const char *path)
|
||||
char *copy = copy_of(path);
|
||||
char *last_slash = strrchr(copy, '/');
|
||||
|
||||
if (last_slash != NULL)
|
||||
if (last_slash)
|
||||
*last_slash = '\0';
|
||||
|
||||
return copy;
|
||||
@@ -419,7 +387,7 @@ char *browse(char *path)
|
||||
* were in before backing up to "..". */
|
||||
size_t old_selected;
|
||||
/* The number of the selected file before the current selected file. */
|
||||
DIR *dir;
|
||||
DIR *dir = NULL;
|
||||
/* The directory whose contents we are showing. */
|
||||
char *chosen = NULL;
|
||||
/* The name of the file that the user picked, or NULL if none. */
|
||||
@@ -429,7 +397,7 @@ char *browse(char *path)
|
||||
|
||||
path = free_and_assign(path, get_full_path(path));
|
||||
|
||||
if (path != NULL)
|
||||
if (path)
|
||||
dir = opendir(path);
|
||||
|
||||
if (path == NULL || dir == NULL) {
|
||||
@@ -446,20 +414,23 @@ char *browse(char *path)
|
||||
present_name = mallocstrcpy(present_name, filelist[selected]);
|
||||
}
|
||||
|
||||
if (dir != NULL) {
|
||||
/* Get the file list, and set longest and piles in the process. */
|
||||
if (dir) {
|
||||
/* Get the file list, and set gauge and piles in the process. */
|
||||
read_the_list(path, dir);
|
||||
closedir(dir);
|
||||
dir = NULL;
|
||||
}
|
||||
|
||||
/* If given, reselect the present_name and then discard it. */
|
||||
if (present_name != NULL) {
|
||||
browser_select_dirname(present_name);
|
||||
#ifndef NANO_TINY
|
||||
resized_for_browser = FALSE;
|
||||
#endif
|
||||
|
||||
/* If something was selected before, reselect it;
|
||||
* otherwise, just select the first item (..). */
|
||||
if (present_name) {
|
||||
reselect(present_name);
|
||||
free(present_name);
|
||||
present_name = NULL;
|
||||
/* Otherwise, select the first file or directory in the list. */
|
||||
} else
|
||||
selected = 0;
|
||||
|
||||
@@ -469,8 +440,11 @@ char *browse(char *path)
|
||||
|
||||
titlebar(path);
|
||||
|
||||
while (TRUE) {
|
||||
functionptrtype func;
|
||||
if (list_length == 0) {
|
||||
statusline(ALERT, _("No entries"));
|
||||
napms(1200);
|
||||
} else while (TRUE) {
|
||||
functionptrtype function;
|
||||
int kbinput;
|
||||
|
||||
lastmessage = VACUUM;
|
||||
@@ -484,20 +458,20 @@ char *browse(char *path)
|
||||
|
||||
old_selected = selected;
|
||||
|
||||
kbinput = get_kbinput(edit, ISSET(SHOW_CURSOR));
|
||||
kbinput = get_kbinput(midwin, ISSET(SHOW_CURSOR));
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
|
||||
/* When the user clicked in the file list, select a filename. */
|
||||
if (get_mouseinput(&mouse_y, &mouse_x, TRUE) == 0 &&
|
||||
wmouse_trafo(edit, &mouse_y, &mouse_x, FALSE)) {
|
||||
if (get_mouseinput(&mouse_y, &mouse_x) == 0 &&
|
||||
wmouse_trafo(midwin, &mouse_y, &mouse_x, FALSE)) {
|
||||
selected = selected - selected % (usable_rows * piles) +
|
||||
(mouse_y * piles) + (mouse_x / (longest + 2));
|
||||
(mouse_y * piles) + (mouse_x / (gauge + 2));
|
||||
|
||||
/* When beyond end-of-row, select the preceding filename. */
|
||||
if (mouse_x > piles * (longest + 2))
|
||||
if (mouse_x > piles * (gauge + 2))
|
||||
selected--;
|
||||
|
||||
/* When beyond end-of-list, select the last filename. */
|
||||
@@ -513,74 +487,65 @@ char *browse(char *path)
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLE_MOUSE */
|
||||
#ifndef NANO_TINY
|
||||
if (bracketed_paste || kbinput == BRACKETED_PASTE_MARKER) {
|
||||
beep();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
func = interpret(&kbinput);
|
||||
|
||||
if (func == full_refresh) {
|
||||
full_refresh();
|
||||
#ifndef NANO_TINY
|
||||
/* Simulate a terminal resize to force a directory reread. */
|
||||
kbinput = KEY_WINCH;
|
||||
#endif
|
||||
} else if (func == do_help) {
|
||||
function = interpret(kbinput);
|
||||
|
||||
if (function == do_help)
|
||||
do_help();
|
||||
#ifndef NANO_TINY
|
||||
/* The terminal dimensions might have changed, so act as if. */
|
||||
kbinput = KEY_WINCH;
|
||||
} else if (func == do_toggle) {
|
||||
else if (function == full_refresh) {
|
||||
#ifdef NANO_TINY
|
||||
full_refresh();
|
||||
#else
|
||||
kbinput = THE_WINDOW_RESIZED;
|
||||
} else if (function == do_toggle && get_shortcut(kbinput)->toggle == NO_HELP) {
|
||||
TOGGLE(NO_HELP);
|
||||
window_init();
|
||||
kbinput = KEY_WINCH;
|
||||
kbinput = THE_WINDOW_RESIZED;
|
||||
#endif
|
||||
} else if (func == do_search_backward) {
|
||||
} else if (function == do_search_backward) {
|
||||
search_filename(BACKWARD);
|
||||
} else if (func == do_search_forward) {
|
||||
} else if (function == do_search_forward) {
|
||||
search_filename(FORWARD);
|
||||
} else if (func == do_findprevious) {
|
||||
} else if (function == do_findprevious) {
|
||||
research_filename(BACKWARD);
|
||||
} else if (func == do_findnext) {
|
||||
} else if (function == do_findnext) {
|
||||
research_filename(FORWARD);
|
||||
} else if (func == do_left) {
|
||||
} else if (function == do_left) {
|
||||
if (selected > 0)
|
||||
selected--;
|
||||
} else if (func == do_right) {
|
||||
} else if (function == do_right) {
|
||||
if (selected < list_length - 1)
|
||||
selected++;
|
||||
} else if (func == to_prev_word) {
|
||||
} else if (function == to_prev_word) {
|
||||
selected -= (selected % piles);
|
||||
} else if (func == to_next_word) {
|
||||
} else if (function == to_next_word) {
|
||||
selected += piles - 1 - (selected % piles);
|
||||
if (selected >= list_length)
|
||||
selected = list_length - 1;
|
||||
} else if (func == do_up) {
|
||||
} else if (function == do_up) {
|
||||
if (selected >= piles)
|
||||
selected -= piles;
|
||||
} else if (func == do_down) {
|
||||
} else if (function == do_down) {
|
||||
if (selected + piles <= list_length - 1)
|
||||
selected += piles;
|
||||
} else if (func == to_prev_block) {
|
||||
} else if (function == to_prev_block) {
|
||||
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
||||
selected % piles;
|
||||
} else if (func == to_next_block) {
|
||||
} else if (function == to_next_block) {
|
||||
selected = ((selected / (usable_rows * piles)) * usable_rows * piles) +
|
||||
selected % piles + usable_rows * piles - piles;
|
||||
if (selected >= list_length)
|
||||
selected = (list_length / piles) * piles + selected % piles;
|
||||
if (selected >= list_length)
|
||||
selected -= piles;
|
||||
} else if (func == do_page_up) {
|
||||
} else if (function == do_page_up) {
|
||||
if (selected < piles)
|
||||
selected = 0;
|
||||
else if (selected < usable_rows * piles)
|
||||
selected = selected % piles;
|
||||
else
|
||||
selected -= usable_rows * piles;
|
||||
} else if (func == do_page_down) {
|
||||
} else if (function == do_page_down) {
|
||||
if (selected + piles >= list_length - 1)
|
||||
selected = list_length - 1;
|
||||
else if (selected + usable_rows * piles >= list_length)
|
||||
@@ -588,35 +553,32 @@ char *browse(char *path)
|
||||
list_length - piles;
|
||||
else
|
||||
selected += usable_rows * piles;
|
||||
} else if (func == to_first_file) {
|
||||
selected = 0;
|
||||
} else if (func == to_last_file) {
|
||||
selected = list_length - 1;
|
||||
} else if (func == goto_dir) {
|
||||
} else if (function == to_first_file || function == to_last_file) {
|
||||
function();
|
||||
} else if (function == goto_dir) {
|
||||
/* Ask for the directory to go to. */
|
||||
if (do_prompt(MGOTODIR, "", NULL,
|
||||
/* TRANSLATORS: This is a prompt. */
|
||||
browser_refresh, _("Go To Directory")) < 0) {
|
||||
statusbar(_("Cancelled"));
|
||||
continue;
|
||||
goto testresize;
|
||||
}
|
||||
|
||||
path = free_and_assign(path, real_dir_from_tilde(answer));
|
||||
path = free_and_assign(path, expand_leading_tilde(answer));
|
||||
|
||||
/* If the given path is relative, join it with the current path. */
|
||||
if (*path != '/') {
|
||||
path = nrealloc(path, strlen(present_path) +
|
||||
strlen(answer) + 1);
|
||||
path = nrealloc(path, strlen(present_path) + strlen(answer) + 1);
|
||||
sprintf(path, "%s%s", present_path, answer);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
if (outside_of_confinement(path, FALSE)) {
|
||||
if (operating_dir && outside_of_confinement(path, FALSE)) {
|
||||
/* TRANSLATORS: This refers to the confining effect of
|
||||
* the option --operatingdir, not of --restricted. */
|
||||
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
|
||||
path = mallocstrcpy(path, present_path);
|
||||
continue;
|
||||
goto testresize;
|
||||
}
|
||||
#endif
|
||||
/* Snip any trailing slashes, so the name can be compared. */
|
||||
@@ -631,7 +593,7 @@ char *browse(char *path)
|
||||
|
||||
/* Try opening and reading the specified directory. */
|
||||
goto read_directory_contents;
|
||||
} else if (func == do_enter) {
|
||||
} else if (function == do_enter) {
|
||||
struct stat st;
|
||||
|
||||
/* It isn't possible to move up from the root directory. */
|
||||
@@ -644,13 +606,13 @@ char *browse(char *path)
|
||||
/* Note: The selected file can be outside the operating
|
||||
* directory if it's ".." or if it's a symlink to a
|
||||
* directory outside the operating directory. */
|
||||
if (outside_of_confinement(filelist[selected], FALSE)) {
|
||||
if (operating_dir && outside_of_confinement(filelist[selected], FALSE)) {
|
||||
statusline(ALERT, _("Can't go outside of %s"), operating_dir);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
/* If for some reason the file is inaccessible, complain. */
|
||||
if (stat(filelist[selected], &st) == -1) {
|
||||
if (stat(filelist[selected], &st) < 0) {
|
||||
statusline(ALERT, _("Error reading %s: %s"),
|
||||
filelist[selected], strerror(errno));
|
||||
continue;
|
||||
@@ -671,21 +633,26 @@ char *browse(char *path)
|
||||
path = mallocstrcpy(path, filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
#ifdef ENABLE_NANORC
|
||||
} else if (func == (functionptrtype)implant) {
|
||||
implant(first_sc_for(MBROWSER, func)->expansion);
|
||||
} else if (function == (functionptrtype)implant) {
|
||||
implant(first_sc_for(MBROWSER, function)->expansion);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
} else if (kbinput == START_OF_PASTE) {
|
||||
while (get_kbinput(midwin, BLIND) != END_OF_PASTE)
|
||||
;
|
||||
statusline(AHEM, _("Paste is ignored"));
|
||||
} else if (kbinput == THE_WINDOW_RESIZED) {
|
||||
; /* Gets handled below. */
|
||||
#endif
|
||||
} else if (func == do_exit) {
|
||||
} else if (function == do_exit) {
|
||||
break;
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
|
||||
testresize:
|
||||
#ifndef NANO_TINY
|
||||
/* If the terminal resized (or might have), refresh the file list. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
if (kbinput == THE_WINDOW_RESIZED || resized_for_browser) {
|
||||
/* Remember the selected file, to be able to reselect it. */
|
||||
present_name = copy_of(filelist[selected]);
|
||||
goto read_directory_contents;
|
||||
@@ -709,23 +676,19 @@ char *browse(char *path)
|
||||
* start browsing in that directory, otherwise in the current directory. */
|
||||
char *browse_in(const char *inpath)
|
||||
{
|
||||
char *path = real_dir_from_tilde(inpath);
|
||||
char *path = expand_leading_tilde(inpath);
|
||||
struct stat fileinfo;
|
||||
|
||||
/* If path is not a directory, try to strip a filename from it; if then
|
||||
* still not a directory, use the current working directory instead. */
|
||||
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
|
||||
if (stat(path, &fileinfo) < 0 || !S_ISDIR(fileinfo.st_mode)) {
|
||||
path = free_and_assign(path, strip_last_component(path));
|
||||
|
||||
if (stat(path, &fileinfo) == -1 || !S_ISDIR(fileinfo.st_mode)) {
|
||||
char *currentdir = nmalloc(PATH_MAX + 1);
|
||||
|
||||
path = free_and_assign(path, getcwd(currentdir, PATH_MAX + 1));
|
||||
if (stat(path, &fileinfo) < 0 || !S_ISDIR(fileinfo.st_mode)) {
|
||||
path = free_and_assign(path, realpath(".", NULL));
|
||||
|
||||
if (path == NULL) {
|
||||
statusline(MILD, _("The working directory has disappeared"));
|
||||
free(currentdir);
|
||||
beep();
|
||||
statusline(ALERT, _("The working directory has disappeared"));
|
||||
napms(1200);
|
||||
return NULL;
|
||||
}
|
||||
@@ -733,9 +696,9 @@ char *browse_in(const char *inpath)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
/* If the resulting path isn't in the operating directory, use
|
||||
* the operating directory instead. */
|
||||
if (outside_of_confinement(path, FALSE))
|
||||
/* If the resulting path isn't in the operating directory,
|
||||
* use the operating directory instead. */
|
||||
if (operating_dir && outside_of_confinement(path, FALSE))
|
||||
path = mallocstrcpy(path, operating_dir);
|
||||
#endif
|
||||
|
||||
|
||||
135
src/chars.c
135
src/chars.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* chars.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016-2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -23,26 +23,10 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
static bool use_utf8 = FALSE;
|
||||
/* Whether we've enabled UTF-8 support. */
|
||||
|
||||
/* Enable UTF-8 support. */
|
||||
void utf8_init(void)
|
||||
{
|
||||
use_utf8 = TRUE;
|
||||
}
|
||||
|
||||
/* Is UTF-8 support enabled? */
|
||||
bool using_utf8(void)
|
||||
{
|
||||
return use_utf8;
|
||||
}
|
||||
#endif /* ENABLE_UTF8 */
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SPELLER
|
||||
/* Return TRUE when the given character is some kind of letter. */
|
||||
@@ -98,12 +82,12 @@ bool is_blank_char(const char *c)
|
||||
bool is_cntrl_char(const char *c)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8)
|
||||
return ((c[0] & 0xE0) == 0 || c[0] == DEL_CODE ||
|
||||
((signed char)c[0] == -62 && (signed char)c[1] < -96));
|
||||
} else
|
||||
#endif
|
||||
return ((*c & 0x60) == 0 || *c == DEL_CODE);
|
||||
|
||||
return ((*c & 0x60) == 0 || *c == DEL_CODE);
|
||||
}
|
||||
|
||||
/* Return TRUE when the given character is a punctuation character. */
|
||||
@@ -134,14 +118,15 @@ bool is_word_char(const char *c, bool allow_punct)
|
||||
if (allow_punct && is_punct_char(c))
|
||||
return TRUE;
|
||||
|
||||
if (word_chars != NULL && *word_chars != '\0') {
|
||||
if (word_chars && *word_chars) {
|
||||
char symbol[MAXCHARLEN + 1];
|
||||
int symlen = collect_char(c, symbol);
|
||||
|
||||
symbol[symlen] = '\0';
|
||||
return (strstr(word_chars, symbol) != NULL);
|
||||
} else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return the visible representation of control character c. */
|
||||
@@ -153,8 +138,8 @@ char control_rep(const signed char c)
|
||||
return '=';
|
||||
else if (c < 0)
|
||||
return c + 224;
|
||||
else
|
||||
return c + 64;
|
||||
|
||||
return c + 64;
|
||||
}
|
||||
|
||||
/* Return the visible representation of multibyte control character c. */
|
||||
@@ -165,14 +150,15 @@ char control_mbrep(const char *c, bool isdata)
|
||||
return '@';
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
if ((unsigned char)c[0] < 128)
|
||||
return control_rep(c[0]);
|
||||
else
|
||||
return control_rep(c[1]);
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return control_rep(*c);
|
||||
|
||||
return control_rep(*c);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
@@ -180,9 +166,9 @@ char control_mbrep(const char *c, bool isdata)
|
||||
* the number of bytes in the sequence, or -1 for an invalid sequence. */
|
||||
int mbtowide(wchar_t *wc, const char *c)
|
||||
{
|
||||
if ((signed char)*c < 0 && use_utf8) {
|
||||
unsigned char v1 = (unsigned char)c[0];
|
||||
unsigned char v2 = (unsigned char)c[1] ^ 0x80;
|
||||
if ((signed char)*c < 0 && using_utf8) {
|
||||
unsigned char v1 = c[0];
|
||||
unsigned char v2 = c[1] ^ 0x80;
|
||||
|
||||
if (v2 > 0x3F || v1 < 0xC2)
|
||||
return -1;
|
||||
@@ -192,7 +178,7 @@ int mbtowide(wchar_t *wc, const char *c)
|
||||
return 2;
|
||||
}
|
||||
|
||||
unsigned char v3 = (unsigned char)c[2] ^ 0x80;
|
||||
unsigned char v3 = c[2] ^ 0x80;
|
||||
|
||||
if (v3 > 0x3F)
|
||||
return -1;
|
||||
@@ -206,7 +192,7 @@ int mbtowide(wchar_t *wc, const char *c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char v4 = (unsigned char)c[3] ^ 0x80;
|
||||
unsigned char v4 = c[3] ^ 0x80;
|
||||
|
||||
if (v4 > 0x3F || v1 > 0xF4)
|
||||
return -1;
|
||||
@@ -229,7 +215,7 @@ bool is_doublewidth(const char *ch)
|
||||
wchar_t wc;
|
||||
|
||||
/* Only from U+1100 can code points have double width. */
|
||||
if ((unsigned char)*ch < 0xE1 || !use_utf8)
|
||||
if ((unsigned char)*ch < 0xE1 || !using_utf8)
|
||||
return FALSE;
|
||||
|
||||
if (mbtowide(&wc, ch) < 0)
|
||||
@@ -244,7 +230,7 @@ bool is_zerowidth(const char *ch)
|
||||
wchar_t wc;
|
||||
|
||||
/* Only from U+0300 can code points have zero width. */
|
||||
if ((unsigned char)*ch < 0xCC || !use_utf8)
|
||||
if ((unsigned char)*ch < 0xCC || !using_utf8)
|
||||
return FALSE;
|
||||
|
||||
if (mbtowide(&wc, ch) < 0)
|
||||
@@ -264,9 +250,9 @@ bool is_zerowidth(const char *ch)
|
||||
int char_length(const char *pointer)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if ((unsigned char)*pointer > 0xC1 && use_utf8) {
|
||||
unsigned char c1 = (unsigned char)pointer[0];
|
||||
unsigned char c2 = (unsigned char)pointer[1];
|
||||
if ((unsigned char)*pointer > 0xC1 && using_utf8) {
|
||||
unsigned char c1 = pointer[0];
|
||||
unsigned char c2 = pointer[1];
|
||||
|
||||
if ((c2 ^ 0x80) > 0x3F)
|
||||
return 1;
|
||||
@@ -294,7 +280,8 @@ int char_length(const char *pointer)
|
||||
return 4;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return the number of (multibyte) characters in the given string. */
|
||||
@@ -302,7 +289,7 @@ size_t mbstrlen(const char *pointer)
|
||||
{
|
||||
size_t count = 0;
|
||||
|
||||
while (*pointer != '\0') {
|
||||
while (*pointer) {
|
||||
pointer += char_length(pointer);
|
||||
count++;
|
||||
}
|
||||
@@ -327,7 +314,7 @@ int collect_char(const char *string, char *thechar)
|
||||
int advance_over(const char *string, size_t *column)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if ((signed char)*string < 0 && use_utf8) {
|
||||
if ((signed char)*string < 0 && using_utf8) {
|
||||
/* A UTF-8 upper control code has two bytes and takes two columns. */
|
||||
if (((unsigned char)string[0] == 0xC2 && (signed char)string[1] < -96)) {
|
||||
*column += 2;
|
||||
@@ -371,7 +358,7 @@ int advance_over(const char *string, size_t *column)
|
||||
size_t step_left(const char *buf, size_t pos)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
size_t before, charlen = 0;
|
||||
|
||||
if (pos < 4)
|
||||
@@ -400,9 +387,10 @@ size_t step_left(const char *buf, size_t pos)
|
||||
}
|
||||
|
||||
return before - charlen;
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return (pos == 0 ? 0 : pos - 1);
|
||||
|
||||
return (pos == 0 ? 0 : pos - 1);
|
||||
}
|
||||
|
||||
/* Return the index in buf of the beginning of the multibyte character
|
||||
@@ -422,10 +410,10 @@ int mbstrcasecmp(const char *s1, const char *s2)
|
||||
int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
wchar_t wc1, wc2;
|
||||
|
||||
while (*s1 != '\0' && *s2 != '\0' && n > 0) {
|
||||
while (*s1 && *s2 && n > 0) {
|
||||
if ((signed char)*s1 >= 0 && (signed char)*s2 >= 0) {
|
||||
if ('A' <= (*s1 & 0x5F) && (*s1 & 0x5F) <= 'Z') {
|
||||
if ('A' <= (*s2 & 0x5F) && (*s2 & 0x5F) <= 'Z') {
|
||||
@@ -464,19 +452,20 @@ int mbstrncasecmp(const char *s1, const char *s2, size_t n)
|
||||
}
|
||||
|
||||
return (n > 0) ? ((unsigned char)*s1 - (unsigned char)*s2) : 0;
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return strncasecmp(s1, s2, n);
|
||||
|
||||
return strncasecmp(s1, s2, n);
|
||||
}
|
||||
|
||||
/* This function is equivalent to strcasestr() for multibyte strings. */
|
||||
char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
size_t needle_len = mbstrlen(needle);
|
||||
|
||||
while (*haystack != '\0') {
|
||||
while (*haystack) {
|
||||
if (mbstrncasecmp(haystack, needle, needle_len) == 0)
|
||||
return (char *)haystack;
|
||||
|
||||
@@ -484,9 +473,10 @@ char *mbstrcasestr(const char *haystack, const char *needle)
|
||||
}
|
||||
|
||||
return NULL;
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return (char *)strcasestr(haystack, needle);
|
||||
|
||||
return (char *)strcasestr(haystack, needle);
|
||||
}
|
||||
|
||||
/* This function is equivalent to strstr(), except in that it scans the
|
||||
@@ -535,7 +525,7 @@ char *mbrevstrcasestr(const char *haystack, const char *needle,
|
||||
const char *pointer)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
size_t needle_len = mbstrlen(needle);
|
||||
size_t tail_len = mbstrlen(pointer);
|
||||
|
||||
@@ -554,17 +544,18 @@ char *mbrevstrcasestr(const char *haystack, const char *needle,
|
||||
|
||||
pointer = haystack + step_left(haystack, pointer - haystack);
|
||||
}
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return revstrcasestr(haystack, needle, pointer);
|
||||
|
||||
return revstrcasestr(haystack, needle, pointer);
|
||||
}
|
||||
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
/* This function is equivalent to strchr() for multibyte strings. */
|
||||
char *mbstrchr(const char *string, const char *chr)
|
||||
const char *mbstrchr(const char *string, const char *chr)
|
||||
{
|
||||
#ifdef ENABLE_UTF8
|
||||
if (use_utf8) {
|
||||
if (using_utf8) {
|
||||
bool bad_s = FALSE, bad_c = FALSE;
|
||||
wchar_t ws, wc;
|
||||
|
||||
@@ -573,7 +564,7 @@ char *mbstrchr(const char *string, const char *chr)
|
||||
bad_c = TRUE;
|
||||
}
|
||||
|
||||
while (*string != '\0') {
|
||||
while (*string) {
|
||||
int symlen = mbtowide(&ws, string);
|
||||
|
||||
if (symlen < 0) {
|
||||
@@ -591,9 +582,10 @@ char *mbstrchr(const char *string, const char *chr)
|
||||
return NULL;
|
||||
|
||||
return (char *)string;
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
return strchr(string, *chr);
|
||||
|
||||
return strchr(string, *chr);
|
||||
}
|
||||
#endif /* !NANO_TINY || ENABLE_JUSTIFY */
|
||||
|
||||
@@ -602,8 +594,8 @@ char *mbstrchr(const char *string, const char *chr)
|
||||
* the characters in accept, searching forward. */
|
||||
char *mbstrpbrk(const char *string, const char *accept)
|
||||
{
|
||||
while (*string != '\0') {
|
||||
if (mbstrchr(accept, string) != NULL)
|
||||
while (*string) {
|
||||
if (mbstrchr(accept, string))
|
||||
return (char *)string;
|
||||
|
||||
string += char_length(string);
|
||||
@@ -623,7 +615,7 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer)
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
if (mbstrchr(accept, pointer) != NULL)
|
||||
if (mbstrchr(accept, pointer))
|
||||
return (char *)pointer;
|
||||
|
||||
/* If we've reached the head of the string, we found nothing. */
|
||||
@@ -639,7 +631,7 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer)
|
||||
/* Return TRUE if the given string contains at least one blank character. */
|
||||
bool has_blank_char(const char *string)
|
||||
{
|
||||
while (*string != '\0' && !is_blank_char(string))
|
||||
while (*string && !is_blank_char(string))
|
||||
string += char_length(string);
|
||||
|
||||
return *string;
|
||||
@@ -649,8 +641,17 @@ bool has_blank_char(const char *string)
|
||||
/* Return TRUE when the given string is empty or consists of only blanks. */
|
||||
bool white_string(const char *string)
|
||||
{
|
||||
while (*string != '\0' && (is_blank_char(string) || *string == '\r'))
|
||||
while (*string && (is_blank_char(string) || *string == '\r'))
|
||||
string += char_length(string);
|
||||
|
||||
return !*string;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)
|
||||
/* Remove leading whitespace from the given string. */
|
||||
void strip_leading_blanks_from(char *string)
|
||||
{
|
||||
while (string && (*string == ' ' || *string == '\t'))
|
||||
memmove(string, string + 1, strlen(string));
|
||||
}
|
||||
#endif
|
||||
|
||||
62
src/color.c
62
src/color.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* color.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017, 2020, 2021 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -44,7 +44,7 @@ void set_interface_colorpairs(void)
|
||||
for (size_t index = 0; index < NUMBER_OF_ELEMENTS; index++) {
|
||||
colortype *combo = color_combo[index];
|
||||
|
||||
if (combo != NULL) {
|
||||
if (combo) {
|
||||
if (!defaults_allowed) {
|
||||
if (combo->fg == THE_DEFAULT)
|
||||
combo->fg = COLOR_WHITE;
|
||||
@@ -53,6 +53,7 @@ void set_interface_colorpairs(void)
|
||||
}
|
||||
init_pair(index + 1, combo->fg, combo->bg);
|
||||
interface_color_pair[index] = COLOR_PAIR(index + 1) | combo->attributes;
|
||||
rescind_colors = FALSE;
|
||||
} else {
|
||||
if (index == FUNCTION_TAG || index == SCROLL_BAR)
|
||||
interface_color_pair[index] = A_NORMAL;
|
||||
@@ -66,12 +67,24 @@ void set_interface_colorpairs(void)
|
||||
else if (index == ERROR_MESSAGE) {
|
||||
init_pair(index + 1, COLOR_WHITE, COLOR_RED);
|
||||
interface_color_pair[index] = COLOR_PAIR(index + 1) | A_BOLD;
|
||||
} else
|
||||
} else if (index == FOLDED_LINE) {
|
||||
if (COLORS > 15)
|
||||
init_pair(index + 1, COLOR_BLACK + 8, COLOR_BLACK);
|
||||
else
|
||||
init_pair(index + 1, COLOR_WHITE, COLOR_BLACK);
|
||||
interface_color_pair[index] = COLOR_PAIR(index + 1);
|
||||
} else {
|
||||
interface_color_pair[index] = hilite_attribute;
|
||||
}
|
||||
}
|
||||
|
||||
free(color_combo[index]);
|
||||
}
|
||||
|
||||
if (rescind_colors) {
|
||||
interface_color_pair[SPOTLIGHTED] = A_REVERSE;
|
||||
interface_color_pair[ERROR_MESSAGE] = A_REVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign a pair number to each of the foreground/background color combinations
|
||||
@@ -137,7 +150,7 @@ void find_and_prime_applicable_syntax(void)
|
||||
return;
|
||||
|
||||
/* If we specified a syntax-override string, use it. */
|
||||
if (syntaxstr != NULL) {
|
||||
if (syntaxstr) {
|
||||
/* An override of "none" is like having no syntax at all. */
|
||||
if (strcmp(syntaxstr, "none") == 0)
|
||||
return;
|
||||
@@ -197,7 +210,7 @@ void find_and_prime_applicable_syntax(void)
|
||||
}
|
||||
|
||||
/* Now try and find a syntax that matches the magic string. */
|
||||
if (magicstring != NULL) {
|
||||
if (magicstring) {
|
||||
for (sntx = syntaxes; sntx != NULL; sntx = sntx->next)
|
||||
if (found_in_list(sntx->magics, magicstring))
|
||||
break;
|
||||
@@ -216,7 +229,7 @@ void find_and_prime_applicable_syntax(void)
|
||||
}
|
||||
|
||||
/* When the syntax isn't loaded yet, parse it and initialize its colors. */
|
||||
if (sntx != NULL && sntx->filename != NULL) {
|
||||
if (sntx && sntx->filename) {
|
||||
parse_one_include(sntx->filename, sntx);
|
||||
set_syntax_colorpairs(sntx);
|
||||
}
|
||||
@@ -234,7 +247,7 @@ void check_the_multis(linestruct *line)
|
||||
char *afterstart;
|
||||
|
||||
/* If there is no syntax or no multiline regex, there is nothing to do. */
|
||||
if (openfile->syntax == NULL || openfile->syntax->nmultis == 0)
|
||||
if (!openfile->syntax || openfile->syntax->multiscore == 0)
|
||||
return;
|
||||
|
||||
if (line->multidata == NULL) {
|
||||
@@ -255,12 +268,13 @@ void check_the_multis(linestruct *line)
|
||||
if (line->multidata[ink->id] == NOTHING) {
|
||||
if (!astart)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] & (WHOLELINE|WOULDBE)) {
|
||||
if (!astart && !anend)
|
||||
} else if (line->multidata[ink->id] == WHOLELINE) {
|
||||
/* Ensure that a detected start match is not actually an end match. */
|
||||
if (!anend && (!astart || regexec(ink->end, line->data, 1, &endmatch, 0) != 0))
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == JUSTONTHIS) {
|
||||
if (astart && anend && regexec(ink->start, line->data + endmatch.rm_eo,
|
||||
1, &startmatch, 0) != 0)
|
||||
if (astart && anend && regexec(ink->start, line->data + startmatch.rm_eo +
|
||||
endmatch.rm_eo, 1, &startmatch, 0) != 0)
|
||||
continue;
|
||||
} else if (line->multidata[ink->id] == STARTSHERE) {
|
||||
if (astart && !anend)
|
||||
@@ -272,6 +286,7 @@ void check_the_multis(linestruct *line)
|
||||
|
||||
/* There is a mismatch, so something changed: repaint. */
|
||||
refresh_needed = TRUE;
|
||||
perturbed = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -284,7 +299,7 @@ void precalc_multicolorinfo(void)
|
||||
regmatch_t startmatch, endmatch;
|
||||
linestruct *line, *tailline;
|
||||
|
||||
if (!openfile->syntax || openfile->syntax->nmultis == 0 || ISSET(NO_SYNTAX))
|
||||
if (!openfile->syntax || openfile->syntax->multiscore == 0 || ISSET(NO_SYNTAX))
|
||||
return;
|
||||
|
||||
//#define TIMEPRECALC 123
|
||||
@@ -296,7 +311,7 @@ void precalc_multicolorinfo(void)
|
||||
/* For each line, allocate cache space for the multiline-regex info. */
|
||||
for (line = openfile->filetop; line != NULL; line = line->next)
|
||||
if (!line->multidata)
|
||||
line->multidata = nmalloc(openfile->syntax->nmultis * sizeof(short));
|
||||
line->multidata = nmalloc(openfile->syntax->multiscore * sizeof(short));
|
||||
|
||||
for (ink = openfile->syntax->color; ink != NULL; ink = ink->next) {
|
||||
/* If this is not a multi-line regex, skip it. */
|
||||
@@ -338,25 +353,20 @@ void precalc_multicolorinfo(void)
|
||||
/* Look for an end match on later lines. */
|
||||
tailline = line->next;
|
||||
|
||||
while (tailline && regexec(ink->end, tailline->data,
|
||||
1, &endmatch, 0) != 0)
|
||||
while (tailline && regexec(ink->end, tailline->data, 1, &endmatch, 0) != 0)
|
||||
tailline = tailline->next;
|
||||
|
||||
/* When there is no end match, mark relevant lines as such. */
|
||||
if (tailline == NULL) {
|
||||
for (; line->next != NULL; line = line->next)
|
||||
line->multidata[ink->id] = WOULDBE;
|
||||
line->multidata[ink->id] = WOULDBE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* We found it, we found it, la lala lala. Mark the lines. */
|
||||
line->multidata[ink->id] = STARTSHERE;
|
||||
|
||||
// Note that this also advances the line in the main loop.
|
||||
for (line = line->next; line != tailline; line = line->next)
|
||||
line->multidata[ink->id] = WHOLELINE;
|
||||
|
||||
if (tailline == NULL) {
|
||||
line = openfile->filebot;
|
||||
break;
|
||||
}
|
||||
|
||||
tailline->multidata[ink->id] = ENDSHERE;
|
||||
|
||||
/* Look for a possible new start after the end match. */
|
||||
@@ -366,7 +376,7 @@ void precalc_multicolorinfo(void)
|
||||
}
|
||||
|
||||
#ifdef TIMEPRECALC
|
||||
statusline(INFO, "Precalculation: %.1f ms", 1000 * (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
statusline(NOTICE, "Precalculation: %.1f ms", 1000 * (double)(clock() - start) / CLOCKS_PER_SEC);
|
||||
napms(1200);
|
||||
#endif
|
||||
}
|
||||
|
||||
128
src/cut.c
128
src/cut.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* cut.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mark Majeres *
|
||||
* Copyright (C) 2016, 2018-2020 Benno Schulenberg *
|
||||
* *
|
||||
@@ -16,7 +16,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Delete the character under the cursor. */
|
||||
void do_deletion(undo_type action)
|
||||
/* Delete the character at the current position, and
|
||||
* add or update an undo item for the given action. */
|
||||
void expunge(undo_type action)
|
||||
{
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* When in the middle of a line, delete the current character. */
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
if (openfile->current->data[openfile->current_x]) {
|
||||
int charlen = char_length(openfile->current->data + openfile->current_x);
|
||||
size_t line_len = strlen(openfile->current->data + openfile->current_x);
|
||||
#ifndef NANO_TINY
|
||||
@@ -48,23 +49,28 @@ void do_deletion(undo_type action)
|
||||
memmove(&openfile->current->data[openfile->current_x],
|
||||
&openfile->current->data[openfile->current_x + charlen],
|
||||
line_len - charlen + 1);
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
#ifndef NANO_TINY
|
||||
/* When softwrapping, a changed number of chunks requires a refresh. */
|
||||
if (ISSET(SOFTWRAP) && extra_chunks_in(openfile->current) != old_amount)
|
||||
refresh_needed = TRUE;
|
||||
/* When panning, and we have come near edge of the viewport... */
|
||||
else if (united_sidescroll && openfile->placewewant < openfile->brink + CUSHION)
|
||||
refresh_needed = TRUE;
|
||||
|
||||
/* Adjust the mark if it is after the cursor on the current line. */
|
||||
if (openfile->mark == openfile->current &&
|
||||
openfile->mark_x > openfile->current_x)
|
||||
if (openfile->mark == openfile->current && openfile->mark_x > openfile->current_x)
|
||||
openfile->mark_x -= charlen;
|
||||
#endif
|
||||
/* Otherwise, when not at end of buffer, join this line with the next. */
|
||||
} else if (openfile->current != openfile->filebot) {
|
||||
linestruct *joining = openfile->current->next;
|
||||
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
UNFOLD_SEGMENT(joining);
|
||||
|
||||
/* If there is a magic line, and we're before it: don't eat it. */
|
||||
if (joining == openfile->filebot && openfile->current_x != 0 &&
|
||||
!ISSET(NO_NEWLINES)) {
|
||||
if (joining == openfile->filebot && openfile->current_x != 0 && !ISSET(NO_NEWLINES)) {
|
||||
#ifndef NANO_TINY
|
||||
if (action == BACK)
|
||||
add_undo(BACK, NULL);
|
||||
@@ -97,6 +103,13 @@ void do_deletion(undo_type action)
|
||||
/* We're at the end-of-file: nothing to do. */
|
||||
return;
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (!refresh_needed)
|
||||
check_the_multis(openfile->current);
|
||||
#endif
|
||||
if (!refresh_needed)
|
||||
update_line(openfile->current, openfile->current_x);
|
||||
|
||||
/* Adjust the file size, and remember it for a possible redo. */
|
||||
openfile->totsize--;
|
||||
#ifndef NANO_TINY
|
||||
@@ -105,7 +118,8 @@ void do_deletion(undo_type action)
|
||||
set_modified();
|
||||
}
|
||||
|
||||
/* Delete the character under the cursor. */
|
||||
/* Delete the character under the cursor plus any succeeding zero-widths,
|
||||
* or, when the mark is on and --zap is active, delete the marked region. */
|
||||
void do_delete(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
@@ -114,17 +128,18 @@ void do_delete(void)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
do_deletion(DEL);
|
||||
expunge(DEL);
|
||||
#ifdef ENABLE_UTF8
|
||||
while (openfile->current->data[openfile->current_x] != '\0' &&
|
||||
while (openfile->current->data[openfile->current_x] &&
|
||||
is_zerowidth(openfile->current->data + openfile->current_x))
|
||||
do_deletion(DEL);
|
||||
expunge(DEL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Backspace over one character. That is, move the cursor left one
|
||||
* character, and then delete the character under the cursor. */
|
||||
* character, and then delete the character under the cursor. Or,
|
||||
* when mark is on and --zap is active, delete the marked region. */
|
||||
void do_backspace(void)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
@@ -134,10 +149,16 @@ void do_backspace(void)
|
||||
#endif
|
||||
if (openfile->current_x > 0) {
|
||||
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
||||
do_deletion(BACK);
|
||||
expunge(BACK);
|
||||
} else if (openfile->current != openfile->filetop) {
|
||||
do_left();
|
||||
do_deletion(BACK);
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (openfile->current->prev->folded) {
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
} else
|
||||
#endif
|
||||
do_left();
|
||||
expunge(BACK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,8 +194,8 @@ bool is_cuttable(bool test_cliff)
|
||||
void chop_word(bool forward)
|
||||
{
|
||||
/* Remember the current cursor position. */
|
||||
linestruct *is_current = openfile->current;
|
||||
size_t is_current_x = openfile->current_x;
|
||||
linestruct *was_current = openfile->current;
|
||||
size_t was_x = openfile->current_x;
|
||||
/* Remember where the cutbuffer is, then make it seem blank. */
|
||||
linestruct *is_cutbuffer = cutbuffer;
|
||||
|
||||
@@ -185,30 +206,30 @@ void chop_word(bool forward)
|
||||
* on the edge of the original line, then put the cursor on that
|
||||
* edge instead, so that lines will not be joined unexpectedly. */
|
||||
if (!forward) {
|
||||
do_prev_word();
|
||||
if (openfile->current != is_current) {
|
||||
if (is_current_x > 0) {
|
||||
openfile->current = is_current;
|
||||
do_prev_word(ALLOW_FOLDED);
|
||||
if (openfile->current != was_current) {
|
||||
if (was_x > 0) {
|
||||
openfile->current = was_current;
|
||||
openfile->current_x = 0;
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
} else {
|
||||
do_next_word(ISSET(AFTER_ENDS));
|
||||
if (openfile->current != is_current &&
|
||||
is_current->data[is_current_x] != '\0') {
|
||||
openfile->current = is_current;
|
||||
openfile->current_x = strlen(is_current->data);
|
||||
do_next_word(ISSET(AFTER_ENDS), ALLOW_FOLDED);
|
||||
if (openfile->current != was_current && was_current->data[was_x]) {
|
||||
openfile->current = was_current;
|
||||
openfile->current_x = strlen(was_current->data);
|
||||
}
|
||||
}
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
|
||||
/* Set the mark at the start of that word. */
|
||||
openfile->mark = openfile->current;
|
||||
openfile->mark_x = openfile->current_x;
|
||||
|
||||
/* Put the cursor back where it was, so an undo will put it there too. */
|
||||
openfile->current = is_current;
|
||||
openfile->current_x = is_current_x;
|
||||
openfile->current = was_current;
|
||||
openfile->current_x = was_x;
|
||||
|
||||
/* Now kill the marked region and a word is gone. */
|
||||
add_undo(CUT, NULL);
|
||||
@@ -255,9 +276,13 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
if (top == bot && top_x == bot_x)
|
||||
return;
|
||||
|
||||
if (top != bot)
|
||||
for (linestruct *line = top->next; line != bot->next; line = line->next)
|
||||
if (top != bot) {
|
||||
UNFOLD_SEGMENT(top);
|
||||
for (linestruct *line = top->next; line != bot->next; line = line->next) {
|
||||
UNFOLD_SEGMENT(line);
|
||||
had_anchor |= line->has_anchor;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (top == bot) {
|
||||
@@ -325,7 +350,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
cutbottom->next = taken->next;
|
||||
delete_node(taken);
|
||||
|
||||
if (cutbottom->next != NULL) {
|
||||
if (cutbottom->next) {
|
||||
cutbottom->next->prev = cutbottom;
|
||||
cutbottom = last;
|
||||
}
|
||||
@@ -353,7 +378,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
}
|
||||
|
||||
/* If the text doesn't end with a newline, and it should, add one. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0])
|
||||
new_magicline();
|
||||
}
|
||||
|
||||
@@ -371,7 +396,9 @@ void ingraft_buffer(linestruct *topline)
|
||||
#endif
|
||||
linestruct *botline = topline;
|
||||
|
||||
while (botline->next != NULL)
|
||||
UNFOLD_SEGMENT(line);
|
||||
|
||||
while (botline->next)
|
||||
botline = botline->next;
|
||||
|
||||
/* Add the size of the text to be grafted to the buffer size. */
|
||||
@@ -428,16 +455,26 @@ void ingraft_buffer(linestruct *topline)
|
||||
renumber_from(line);
|
||||
|
||||
/* If the text doesn't end with a newline, and it should, add one. */
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0] != '\0')
|
||||
if (!ISSET(NO_NEWLINES) && openfile->filebot->data[0])
|
||||
new_magicline();
|
||||
}
|
||||
|
||||
/* Meld a copy of the given buffer into the current file buffer. */
|
||||
void copy_from_buffer(linestruct *somebuffer)
|
||||
{
|
||||
#ifdef ENABLE_COLOR
|
||||
size_t threshold = openfile->edittop->lineno + editwinrows - 1;
|
||||
#endif
|
||||
linestruct *the_copy = copy_buffer(somebuffer);
|
||||
|
||||
ingraft_buffer(the_copy);
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
if (openfile->current->lineno > threshold || ISSET(SOFTWRAP))
|
||||
recook = TRUE;
|
||||
else
|
||||
perturbed = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -485,7 +522,7 @@ void do_snip(bool marked, bool until_eof, bool append)
|
||||
/* When not at the end of a line, move the rest of this line into
|
||||
* the cutbuffer. Otherwise, when not at the end of the buffer,
|
||||
* move just the "line separator" into the cutbuffer. */
|
||||
if (openfile->current_x < strlen(openfile->current->data))
|
||||
if (line->data[openfile->current_x])
|
||||
extract_segment(line, openfile->current_x, line, strlen(line->data));
|
||||
else if (openfile->current != openfile->filebot) {
|
||||
extract_segment(line, openfile->current_x, line->next, 0);
|
||||
@@ -509,6 +546,9 @@ void do_snip(bool marked, bool until_eof, bool append)
|
||||
|
||||
set_modified();
|
||||
refresh_needed = TRUE;
|
||||
#ifdef ENABLE_COLOR
|
||||
perturbed = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Move text from the current buffer into the cutbuffer. */
|
||||
@@ -614,6 +654,7 @@ void copy_marked_region(void)
|
||||
botline->data[bot_x] = saved_byte;
|
||||
botline->next = afterline;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Copy text from the current buffer into the cutbuffer. The text is either
|
||||
* the marked region, the whole line, the text from cursor to end-of-line,
|
||||
@@ -626,17 +667,24 @@ void copy_text(void)
|
||||
linestruct *was_current = openfile->current;
|
||||
linestruct *addition;
|
||||
|
||||
if (openfile->mark || openfile->last_action != COPY || !keep_cutbuffer) {
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark || openfile->last_action != COPY)
|
||||
keep_cutbuffer = FALSE;
|
||||
#endif
|
||||
|
||||
if (!keep_cutbuffer) {
|
||||
free_lines(cutbuffer);
|
||||
cutbuffer = NULL;
|
||||
}
|
||||
|
||||
wipe_statusbar();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (openfile->mark) {
|
||||
copy_marked_region();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* When at the very end of the buffer, there is nothing to do. */
|
||||
if (openfile->current->next == NULL && at_eol && (ISSET(CUT_FROM_CURSOR) ||
|
||||
@@ -686,10 +734,11 @@ void copy_text(void)
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
openfile->last_action = COPY;
|
||||
#endif
|
||||
keep_cutbuffer = TRUE;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Copy text from the cutbuffer into the current buffer. */
|
||||
void paste_text(void)
|
||||
@@ -708,6 +757,7 @@ void paste_text(void)
|
||||
statusline(AHEM, _("Cutbuffer is empty"));
|
||||
return;
|
||||
}
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
add_undo(PASTE, NULL);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* definitions.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017 Benno Schulenberg *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2017, 2020-2022, 2024 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -41,6 +41,11 @@
|
||||
#define ROOT_UID 0
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) && !defined(st_atim)
|
||||
#define st_atim st_atimespec
|
||||
#define st_mtim st_mtimespec
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
@@ -60,10 +65,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/* Prefer wide ncurses over normal ncurses over curses. */
|
||||
#if defined(HAVE_NCURSESW_NCURSES_H)
|
||||
#include <ncursesw/ncurses.h>
|
||||
#elif defined(HAVE_NCURSES_H)
|
||||
#ifdef HAVE_NCURSES_H
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
@@ -108,6 +110,14 @@
|
||||
#define BACKWARD FALSE
|
||||
#define FORWARD TRUE
|
||||
|
||||
#define YESORNO FALSE
|
||||
#define YESORALLORNO TRUE
|
||||
|
||||
#define YES 1
|
||||
#define ALL 2
|
||||
#define NO 0
|
||||
#define CANCEL -1
|
||||
|
||||
#define BLIND FALSE
|
||||
#define VISIBLE TRUE
|
||||
|
||||
@@ -115,11 +125,6 @@
|
||||
#define REPLACING 1
|
||||
#define INREGION 2
|
||||
|
||||
#define NORMAL TRUE
|
||||
#define SPECIAL FALSE
|
||||
#define TEMPORARY FALSE
|
||||
|
||||
#define ANNOTATE TRUE
|
||||
#define NONOTES FALSE
|
||||
|
||||
#define PRUNE_DUPLICATE TRUE
|
||||
@@ -138,6 +143,9 @@
|
||||
/* The default number of columns from end of line where wrapping occurs. */
|
||||
#define COLUMNS_FROM_EOL 8
|
||||
|
||||
/* The number of columns the cursor should stay away from the edge. */
|
||||
#define CUSHION 3
|
||||
|
||||
/* The default comment character when a syntax does not specify any. */
|
||||
#define GENERAL_COMMENT_CHARACTER "#"
|
||||
|
||||
@@ -162,8 +170,6 @@
|
||||
/* The start regex matches on an earlier line, the end regex on this one. */
|
||||
#define JUSTONTHIS (1<<5)
|
||||
/* Both the start and end regexes match within this line. */
|
||||
#define WOULDBE (1<<6)
|
||||
/* An unpaired start match is on or before this line. */
|
||||
#endif
|
||||
|
||||
/* Basic control codes. */
|
||||
@@ -189,6 +195,8 @@
|
||||
#define ALT_RIGHT 0x422
|
||||
#define ALT_UP 0x423
|
||||
#define ALT_DOWN 0x424
|
||||
#define ALT_HOME 0x425
|
||||
#define ALT_END 0x426
|
||||
#define ALT_PAGEUP 0x427
|
||||
#define ALT_PAGEDOWN 0x428
|
||||
#define ALT_INSERT 0x42C
|
||||
@@ -197,8 +205,6 @@
|
||||
#define SHIFT_ALT_RIGHT 0x432
|
||||
#define SHIFT_ALT_UP 0x433
|
||||
#define SHIFT_ALT_DOWN 0x434
|
||||
//#define SHIFT_LEFT 0x451
|
||||
//#define SHIFT_RIGHT 0x452
|
||||
#define SHIFT_UP 0x453
|
||||
#define SHIFT_DOWN 0x454
|
||||
#define SHIFT_HOME 0x455
|
||||
@@ -208,11 +214,28 @@
|
||||
#define SHIFT_DELETE 0x45D
|
||||
#define SHIFT_TAB 0x45F
|
||||
|
||||
/* A special keycode for when <Tab> is pressed while the mark is on. */
|
||||
#define INDENT_KEY 0x4F1
|
||||
#define FOCUS_IN 0x491
|
||||
#define FOCUS_OUT 0x499
|
||||
|
||||
/* A special keycode to signal the beginning and end of a bracketed paste. */
|
||||
#define BRACKETED_PASTE_MARKER 0x4FB
|
||||
/* Custom keycodes for signaling the start and end of a bracketed paste. */
|
||||
#define START_OF_PASTE 0x4B5
|
||||
#define END_OF_PASTE 0x4BE
|
||||
|
||||
/* Special keycodes for when a string bind has been partially implanted
|
||||
* or has an unpaired opening brace, or when a function in a string bind
|
||||
* needs execution or a specified function name is invalid. */
|
||||
#define MORE_PLANTS 0x4EA
|
||||
#define MISSING_BRACE 0x4EB
|
||||
#define PLANTED_A_COMMAND 0x4EC
|
||||
#define NO_SUCH_FUNCTION 0x4EF
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* A special keycode for Ctrl + the central key on the numeric keypad. */
|
||||
#define KEY_CENTER 0x4F0
|
||||
|
||||
/* A special keycode for when we get a SIGWINCH (a window resize). */
|
||||
#define THE_WINDOW_RESIZED 0x4F7
|
||||
#endif
|
||||
|
||||
/* A special keycode for when a key produces an unknown escape sequence. */
|
||||
#define FOREIGN_SEQUENCE 0x4FC
|
||||
@@ -221,9 +244,6 @@
|
||||
#define KEY_FRESH 0x4FE
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* A special keycode for when we get a SIGWINCH (a window resize). */
|
||||
#define KEY_WINCH -2
|
||||
|
||||
/* Some extra flags for the undo function. */
|
||||
#define WAS_BACKSPACE_AT_EOF (1<<1)
|
||||
#define WAS_WHOLE_LINE (1<<2)
|
||||
@@ -259,9 +279,18 @@
|
||||
#define MSOME MMAIN|MBROWSER
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
#define UNFOLD_SEGMENT(line) unfold_folded_segment(line)
|
||||
#else
|
||||
#define UNFOLD_SEGMENT(line)
|
||||
#endif
|
||||
|
||||
#define ALLOW_FOLDED TRUE
|
||||
#define DISALLOW_FOLDED FALSE
|
||||
|
||||
/* Enumeration types. */
|
||||
typedef enum {
|
||||
UNSPECIFIED, NIX_FILE, DOS_FILE, MAC_FILE
|
||||
UNSPECIFIED, NIX_FILE, DOS_FILE
|
||||
} format_type;
|
||||
|
||||
typedef enum {
|
||||
@@ -269,8 +298,8 @@ typedef enum {
|
||||
} message_type;
|
||||
|
||||
typedef enum {
|
||||
OVERWRITE, APPEND, PREPEND
|
||||
} kind_of_writing_type;
|
||||
OVERWRITE, APPEND, PREPEND, SPECIAL
|
||||
} writing_type;
|
||||
|
||||
typedef enum {
|
||||
CENTERING, FLOWING, STATIONARY
|
||||
@@ -304,6 +333,7 @@ enum {
|
||||
ERROR_MESSAGE,
|
||||
KEY_COMBO,
|
||||
FUNCTION_TAG,
|
||||
FOLDED_LINE,
|
||||
NUMBER_OF_ELEMENTS
|
||||
};
|
||||
|
||||
@@ -313,7 +343,6 @@ enum {
|
||||
CASE_SENSITIVE,
|
||||
CONSTANT_SHOW,
|
||||
NO_HELP,
|
||||
SUSPENDABLE,
|
||||
NO_WRAP,
|
||||
AUTOINDENT,
|
||||
VIEW_MODE,
|
||||
@@ -322,7 +351,7 @@ enum {
|
||||
SAVE_ON_EXIT,
|
||||
CUT_FROM_CURSOR,
|
||||
BACKWARDS_SEARCH,
|
||||
MULTIBUFFER,
|
||||
NEW_BUFFER,
|
||||
REBIND_DELETE,
|
||||
RAW_SEQUENCES,
|
||||
NO_CONVERT,
|
||||
@@ -355,12 +384,21 @@ enum {
|
||||
EMPTY_LINE,
|
||||
INDICATOR,
|
||||
BOOKSTYLE,
|
||||
COLON_PARSING,
|
||||
STATEFLAGS,
|
||||
USE_MAGIC,
|
||||
MINIBAR,
|
||||
ZERO
|
||||
ZERO,
|
||||
MODERN_BINDINGS,
|
||||
SOLO_SIDESCROLL
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
FOUND_BRACKET = 0,
|
||||
NOT_FOUND_BRACKET,
|
||||
NOT_A_BRACKET
|
||||
} bracket_search_result;
|
||||
|
||||
/* Structure types. */
|
||||
#ifdef ENABLE_COLOR
|
||||
typedef struct colortype {
|
||||
@@ -419,7 +457,7 @@ typedef struct syntaxtype {
|
||||
/* The command with which to lint this type of file. */
|
||||
char *formatter;
|
||||
/* The command with which to format/modify/arrange this type of file. */
|
||||
char *tab;
|
||||
char *tabstring;
|
||||
/* What the Tab key should produce; NULL for default behavior. */
|
||||
#ifdef ENABLE_COMMENT
|
||||
char *comment;
|
||||
@@ -427,7 +465,7 @@ typedef struct syntaxtype {
|
||||
#endif
|
||||
colortype *color;
|
||||
/* The colors and their regexes used in this syntax. */
|
||||
short nmultis;
|
||||
short multiscore;
|
||||
/* How many multiline regex strings this syntax has. */
|
||||
struct syntaxtype *next;
|
||||
/* Next syntax. */
|
||||
@@ -467,6 +505,10 @@ typedef struct linestruct {
|
||||
bool has_anchor;
|
||||
/* Whether the user has placed an anchor at this line. */
|
||||
#endif
|
||||
#ifdef ENABLE_FOLDING
|
||||
bool folded;
|
||||
/* Whether or not this line is in a fold segment */
|
||||
#endif
|
||||
} linestruct;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -510,16 +552,18 @@ typedef struct undostruct {
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifdef ENABLE_HISTORIES
|
||||
typedef struct poshiststruct {
|
||||
typedef struct positionstruct {
|
||||
char *filename;
|
||||
/* The full path plus name of the file. */
|
||||
ssize_t linenumber;
|
||||
/* The line where the cursor was when we closed the file. */
|
||||
/* The line where the cursor was when the file was closed. */
|
||||
ssize_t columnnumber;
|
||||
/* The column where the cursor was. */
|
||||
struct poshiststruct *next;
|
||||
/* The next item of position history. */
|
||||
} poshiststruct;
|
||||
char *anchors;
|
||||
/* The line numbers where anchors were placed, in string form. */
|
||||
struct positionstruct *next;
|
||||
/* The next item in the positions register. */
|
||||
} positionstruct;
|
||||
#endif
|
||||
|
||||
typedef struct openfilestruct {
|
||||
@@ -541,9 +585,11 @@ typedef struct openfilestruct {
|
||||
size_t current_x;
|
||||
/* The file's x-coordinate position. */
|
||||
size_t placewewant;
|
||||
/* The file's x position we would like. */
|
||||
ssize_t current_y;
|
||||
/* The file's y-coordinate position. */
|
||||
/* The preferred column for the cursor. */
|
||||
size_t brink;
|
||||
/* From which column the edit window is drawn (when panning). */
|
||||
ssize_t cursor_row;
|
||||
/* The row in the edit window that the cursor is on. */
|
||||
struct stat *statinfo;
|
||||
/* The file's stat information from when it was opened or last saved. */
|
||||
#ifdef ENABLE_WRAPPING
|
||||
@@ -558,7 +604,7 @@ typedef struct openfilestruct {
|
||||
bool softmark;
|
||||
/* Whether a marked region was made by holding Shift. */
|
||||
format_type fmt;
|
||||
/* The file's format -- Unix or DOS or Mac. */
|
||||
/* The file's format -- Unix or DOS. */
|
||||
char *lock_filename;
|
||||
/* The path of the lockfile, if we created one. */
|
||||
undostruct *undotop;
|
||||
@@ -622,17 +668,14 @@ typedef struct keystruct {
|
||||
typedef struct funcstruct {
|
||||
void (*func)(void);
|
||||
/* The actual function to call. */
|
||||
const char *desc;
|
||||
/* The function's short description, for example "Where Is". */
|
||||
const char *tag;
|
||||
/* The function's help-line label, for example "Where Is". */
|
||||
#ifdef ENABLE_HELP
|
||||
const char *help;
|
||||
/* The help-screen text for this function. */
|
||||
const char *phrase;
|
||||
/* The function's description for in the help viewer. */
|
||||
bool blank_after;
|
||||
/* Whether there should be a blank line after the help text
|
||||
* for this function. */
|
||||
/* Whether to distance this function from the next in the help viewer. */
|
||||
#endif
|
||||
bool viewok;
|
||||
/* Is this function allowed when in view mode? */
|
||||
int menus;
|
||||
/* In what menus this function applies. */
|
||||
struct funcstruct *next;
|
||||
|
||||
800
src/files.c
800
src/files.c
File diff suppressed because it is too large
Load Diff
158
src/folding.c
Normal file
158
src/folding.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/**************************************************************************
|
||||
* folding.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2023 rexy712 *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
* by the Free Software Foundation, either version 3 of the License, *
|
||||
* or (at your option) any later version. *
|
||||
* *
|
||||
* GNU nano is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty *
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "prototypes.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
|
||||
/* Unfold a folded segment containing the given line. */
|
||||
void unfold_folded_segment(linestruct *line)
|
||||
{
|
||||
line = get_start_of_folded_segment(line);
|
||||
if (line != NULL)
|
||||
refresh_needed = TRUE;
|
||||
for (; line != NULL && line->folded; line = line->next)
|
||||
line->folded = FALSE;
|
||||
}
|
||||
|
||||
/* Get the first line of the folded segment. */
|
||||
linestruct *get_start_of_folded_segment(linestruct *line)
|
||||
{
|
||||
if (!line->folded)
|
||||
return line;
|
||||
|
||||
while (line->prev != NULL && line->prev->folded)
|
||||
line = line->prev;
|
||||
|
||||
return line;
|
||||
}
|
||||
/* Get the last line of the folded segment. */
|
||||
linestruct *get_end_of_folded_segment(linestruct *line)
|
||||
{
|
||||
if (!line->folded)
|
||||
return line;
|
||||
|
||||
while (line->next != NULL && line->next->folded)
|
||||
line = line->next;
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/* Get the number of lines in a folded segment. */
|
||||
int get_folded_segment_length(linestruct *line)
|
||||
{
|
||||
int i = 1;
|
||||
|
||||
if (!line->folded)
|
||||
return 0;
|
||||
|
||||
line = get_start_of_folded_segment(line);
|
||||
for (; line->next != NULL && line->next->folded; line = line->next)
|
||||
++i;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Unfolds a folded segment containing line, or if line is not folded
|
||||
* does nothing. Returns true if any segments are unfolded. */
|
||||
bool do_unfold_segment(linestruct *line)
|
||||
{
|
||||
/* If current line is folded, just unfold and finish. */
|
||||
if (line->folded) {
|
||||
unfold_folded_segment(line);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* If all else fails, attempt to find the next folded line in the file. */
|
||||
for (line = openfile->current; line != NULL; line = line->next) {
|
||||
if (line->folded) {
|
||||
unfold_folded_segment(line);
|
||||
openfile->current = line;
|
||||
if (line->prev)
|
||||
do_up();
|
||||
else
|
||||
move_cursor_to_proper_column();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Fold the currently selected lines unless the current line is
|
||||
* a folded lines. In that case, remove unfold the lines. */
|
||||
void do_fold_segment(void)
|
||||
{
|
||||
linestruct *top, *bot, *line;
|
||||
get_range(&top, &bot);
|
||||
size_t top_pos, bot_pos;
|
||||
bool region_found = (top != bot);
|
||||
|
||||
if (top == bot) {
|
||||
/* First try to unfold if this line/bracketed region is folded. */
|
||||
if (top->folded) {
|
||||
unfold_folded_segment(top);
|
||||
return;
|
||||
}
|
||||
|
||||
/* When no selection is made, attempt to find the next line
|
||||
* ending with an opening bracket as the top bound. */
|
||||
for (; find_terminus_of_bracketed_region(&top, &top_pos, get_matchbrackets_halfway(), FALSE)
|
||||
; top = top->next) {
|
||||
bot = top;
|
||||
bot_pos = top_pos;
|
||||
if (find_matching_bracket_pos(&bot, &bot_pos) == FOUND_BRACKET
|
||||
&& bot->lineno - top->lineno >= 2) {
|
||||
top = top->next;
|
||||
bot = bot->prev;
|
||||
/* Unfold if already folded. */
|
||||
region_found = !top->folded;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (region_found == TRUE) {
|
||||
for (line = top; line != bot->next; line = line->next)
|
||||
line->folded = TRUE;
|
||||
|
||||
/* Place the cursor after the new fold, accounting for possible
|
||||
* fold concatenations occurring. */
|
||||
openfile->current = get_end_of_folded_segment(bot);
|
||||
if (bot->next)
|
||||
do_down();
|
||||
else
|
||||
move_cursor_to_proper_column();
|
||||
|
||||
if (top->lineno < openfile->edittop->lineno &&
|
||||
bot->lineno > openfile->edittop->lineno)
|
||||
openfile->edittop = top;
|
||||
|
||||
openfile->mark = NULL;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
} else
|
||||
if (!do_unfold_segment(openfile->current))
|
||||
statusline(AHEM, _("No valid region found for automatic fold"));
|
||||
}
|
||||
|
||||
#endif /* ENABLE_FOLDING */
|
||||
766
src/global.c
766
src/global.c
File diff suppressed because it is too large
Load Diff
137
src/help.c
137
src/help.c
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* help.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2000-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2000-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2017 Rishabh Dave *
|
||||
* Copyright (C) 2014-2019 Benno Schulenberg *
|
||||
* *
|
||||
@@ -16,7 +16,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -50,7 +50,7 @@ void help_init(void)
|
||||
char *ptr;
|
||||
|
||||
/* First, set up the initial help text for the current function. */
|
||||
if (currmenu & (MWHEREIS|MREPLACE|MREPLACEWITH)) {
|
||||
if (currmenu & (MWHEREIS|MREPLACE)) {
|
||||
htx[0] = N_("Search Command Help Text\n\n "
|
||||
"Enter the words or characters you would like to "
|
||||
"search for, and then press Enter. If there is a "
|
||||
@@ -65,6 +65,13 @@ void help_init(void)
|
||||
"will be replaced.\n\n The following function keys are "
|
||||
"available in Search mode:\n\n");
|
||||
htx[2] = NULL;
|
||||
} else if (currmenu == MREPLACEWITH) {
|
||||
htx[0] = N_("=== Replacement ===\n\n "
|
||||
"Type the characters that should replace what you "
|
||||
"typed at the previous prompt, and press Enter.\n\n");
|
||||
htx[1] = N_(" The following function keys "
|
||||
"are available at this prompt:\n\n");
|
||||
htx[2] = NULL;
|
||||
} else if (currmenu == MGOTOLINE) {
|
||||
htx[0] = N_("Go To Line Help Text\n\n "
|
||||
"Enter the line number that you wish to go to and hit "
|
||||
@@ -126,8 +133,8 @@ void help_init(void)
|
||||
"shown in brackets after the search prompt. Hitting "
|
||||
"Enter without entering any text will perform the "
|
||||
"previous search.\n\n");
|
||||
htx[1] = N_(" The following function keys are available in "
|
||||
"Browser Search mode:\n\n");
|
||||
htx[1] = N_(" The following function keys "
|
||||
"are available at this prompt:\n\n");
|
||||
htx[2] = NULL;
|
||||
} else if (currmenu == MGOTODIR) {
|
||||
htx[0] = N_("Browser Go To Directory Help Text\n\n "
|
||||
@@ -143,16 +150,14 @@ void help_init(void)
|
||||
#endif /* ENABLE_BROWSER */
|
||||
#ifdef ENABLE_SPELLER
|
||||
else if (currmenu == MSPELL) {
|
||||
htx[0] = N_("Spell Check Help Text\n\n "
|
||||
"The spell checker checks the spelling of all text in "
|
||||
"the current file. When an unknown word is "
|
||||
"encountered, it is highlighted and a replacement can "
|
||||
"be edited. It will then prompt to replace every "
|
||||
"instance of the given misspelled word in the current "
|
||||
"file, or, if you have selected text with the mark, in "
|
||||
"the selected text.\n\n The following function keys "
|
||||
"are available in Spell Check mode:\n\n");
|
||||
htx[1] = NULL;
|
||||
htx[0] = N_("=== Spelling correction ===\n\n "
|
||||
"The spell checker has examined the spelling of all text "
|
||||
"in the current buffer or marked region. An unknown word "
|
||||
"has been encountered -- it is highlighted and a replacement "
|
||||
"can now be edited. After this you will be asked whether "
|
||||
"to replace each instance of that unknown word.\n\n");
|
||||
htx[1] = N_(" The following function keys "
|
||||
"are available at this prompt:\n\n");
|
||||
htx[2] = NULL;
|
||||
}
|
||||
#endif /* ENABLE_SPELLER */
|
||||
@@ -167,8 +172,8 @@ void help_init(void)
|
||||
htx[1] = N_("If you just need another blank buffer, do not enter any "
|
||||
"command.\n\n You can also pick one of four tools, or cut a "
|
||||
"large piece of the buffer, or put the editor to sleep.\n\n");
|
||||
htx[2] = N_(" The following function keys are "
|
||||
"available in Execute Command mode:\n\n");
|
||||
htx[2] = N_(" The following function keys "
|
||||
"are available at this prompt:\n\n");
|
||||
} else if (currmenu == MLINTER) {
|
||||
htx[0] = N_("=== Linter ===\n\n "
|
||||
"In this mode, the status bar shows an error message or "
|
||||
@@ -208,15 +213,15 @@ void help_init(void)
|
||||
}
|
||||
|
||||
htx[0] = _(htx[0]);
|
||||
if (htx[1] != NULL)
|
||||
if (htx[1])
|
||||
htx[1] = _(htx[1]);
|
||||
if (htx[2] != NULL)
|
||||
if (htx[2])
|
||||
htx[2] = _(htx[2]);
|
||||
|
||||
allocsize += strlen(htx[0]);
|
||||
if (htx[1] != NULL)
|
||||
if (htx[1])
|
||||
allocsize += strlen(htx[1]);
|
||||
if (htx[2] != NULL)
|
||||
if (htx[2])
|
||||
allocsize += strlen(htx[2]);
|
||||
|
||||
/* Calculate the length of the descriptions of the shortcuts.
|
||||
@@ -224,7 +229,7 @@ void help_init(void)
|
||||
* plus translated text, plus one or two \n's. */
|
||||
for (f = allfuncs; f != NULL; f = f->next)
|
||||
if (f->menus & currmenu)
|
||||
allocsize += strlen(_(f->help)) + 21;
|
||||
allocsize += strlen(_(f->phrase)) + 21;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If we're on the main list, we also count the toggle help text.
|
||||
@@ -244,9 +249,9 @@ void help_init(void)
|
||||
|
||||
/* Now add the text we want. */
|
||||
strcpy(help_text, htx[0]);
|
||||
if (htx[1] != NULL)
|
||||
if (htx[1])
|
||||
strcat(help_text, htx[1]);
|
||||
if (htx[2] != NULL)
|
||||
if (htx[2])
|
||||
strcat(help_text, htx[2]);
|
||||
|
||||
/* Remember this end-of-introduction, start-of-shortcuts. */
|
||||
@@ -267,10 +272,10 @@ void help_init(void)
|
||||
if (++tally == 1) {
|
||||
sprintf(ptr, "%s ", s->keystr);
|
||||
/* Unicode arrows take three bytes instead of one. */
|
||||
ptr += (strstr(s->keystr, "\xE2") != NULL ? 9 : 7);
|
||||
ptr += (strstr(s->keystr, "\xE2") ? 9 : 7);
|
||||
} else {
|
||||
sprintf(ptr, "(%s) ", s->keystr);
|
||||
ptr += (strstr(s->keystr, "\xE2") != NULL ? 12 : 10);
|
||||
ptr += (strstr(s->keystr, "\xE2") ? 12 : 10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -282,7 +287,7 @@ void help_init(void)
|
||||
ptr += 10;
|
||||
|
||||
/* The shortcut's description. */
|
||||
ptr += sprintf(ptr, "%s\n", _(f->help));
|
||||
ptr += sprintf(ptr, "%s\n", _(f->phrase));
|
||||
|
||||
if (f->blank_after)
|
||||
ptr += sprintf(ptr, "\n");
|
||||
@@ -317,10 +322,10 @@ void help_init(void)
|
||||
/* Hard-wrap the concatenated help text, and write it into a new buffer. */
|
||||
void wrap_help_text_into_buffer(void)
|
||||
{
|
||||
size_t sum = 0;
|
||||
/* Avoid overtight and overwide paragraphs in the introductory text. */
|
||||
size_t wrapping_point = ((COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS) - thebar;
|
||||
size_t wrapping_point = ((COLS < 40) ? 40 : (COLS > 74) ? 74 : COLS) - sidebar;
|
||||
const char *ptr = start_of_body;
|
||||
size_t sum = 0;
|
||||
|
||||
make_new_buffer();
|
||||
|
||||
@@ -332,12 +337,12 @@ void wrap_help_text_into_buffer(void)
|
||||
}
|
||||
|
||||
/* Copy the help text into the just-created new buffer. */
|
||||
while (*ptr != '\0') {
|
||||
while (*ptr) {
|
||||
int length, shim;
|
||||
char *oneline;
|
||||
|
||||
if (ptr == end_of_intro)
|
||||
wrapping_point = ((COLS < 40) ? 40 : COLS) - thebar;
|
||||
wrapping_point = ((COLS < 40) ? 40 : COLS) - sidebar;
|
||||
|
||||
if (ptr < end_of_intro || *(ptr - 1) == '\n') {
|
||||
length = break_line(ptr, wrapping_point, TRUE);
|
||||
@@ -345,7 +350,7 @@ void wrap_help_text_into_buffer(void)
|
||||
shim = (*(ptr + length - 1) == ' ') ? 0 : 1;
|
||||
snprintf(oneline, length + shim, "%s", ptr);
|
||||
} else {
|
||||
length = break_line(ptr, ((COLS < 40) ? 22 : COLS - 18) - thebar, TRUE);
|
||||
length = break_line(ptr, ((COLS < 40) ? 22 : COLS - 18) - sidebar, TRUE);
|
||||
oneline = nmalloc(length + 5);
|
||||
snprintf(oneline, length + 5, "\t\t %s", ptr);
|
||||
}
|
||||
@@ -389,7 +394,7 @@ void wrap_help_text_into_buffer(void)
|
||||
void show_help(void)
|
||||
{
|
||||
int kbinput = ERR;
|
||||
functionptrtype func;
|
||||
functionptrtype function;
|
||||
/* The function of the key the user typed in. */
|
||||
int oldmenu = currmenu;
|
||||
/* The menu we were called from. */
|
||||
@@ -397,10 +402,13 @@ void show_help(void)
|
||||
int was_margin = margin;
|
||||
#endif
|
||||
ssize_t was_tabsize = tabsize;
|
||||
#ifndef NANO_TINY
|
||||
bool was_lighted = spotlighted;
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
char *was_syntax = syntaxstr;
|
||||
#endif
|
||||
char *saved_answer = (answer != NULL) ? copy_of(answer) : NULL;
|
||||
char *saved_answer = (answer) ? copy_of(answer) : NULL;
|
||||
/* The current answer when the user invokes help at the prompt. */
|
||||
unsigned stash[sizeof(flags) / sizeof(flags[0])];
|
||||
/* A storage place for the current flag settings. */
|
||||
@@ -426,10 +434,13 @@ void show_help(void)
|
||||
UNSET(WHITESPACE_DISPLAY);
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
editwincols = COLS - thebar;
|
||||
editwincols = COLS - sidebar;
|
||||
margin = 0;
|
||||
#endif
|
||||
tabsize = 8;
|
||||
#ifndef NANO_TINY
|
||||
spotlighted = FALSE;
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxstr = "nanohelp";
|
||||
#endif
|
||||
@@ -463,51 +474,50 @@ void show_help(void)
|
||||
focusing = TRUE;
|
||||
|
||||
/* Show the cursor when we searched and found something. */
|
||||
kbinput = get_kbinput(edit, didfind == 1 || ISSET(SHOW_CURSOR));
|
||||
kbinput = get_kbinput(midwin, didfind == 1 || ISSET(SHOW_CURSOR));
|
||||
|
||||
didfind = 0;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
spotlighted = FALSE;
|
||||
|
||||
if (bracketed_paste || kbinput == BRACKETED_PASTE_MARKER) {
|
||||
beep();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
func = interpret(&kbinput);
|
||||
function = interpret(kbinput);
|
||||
|
||||
if (func == full_refresh) {
|
||||
full_refresh();
|
||||
} else if (ISSET(SHOW_CURSOR) && (func == do_left || func == do_right ||
|
||||
func == do_up || func == do_down)) {
|
||||
func();
|
||||
} else if (func == do_up || func == do_scroll_up) {
|
||||
if (ISSET(SHOW_CURSOR) && (function == do_left || function == do_right ||
|
||||
function == do_up || function == do_down)) {
|
||||
function();
|
||||
} else if (function == do_up || function == do_scroll_up) {
|
||||
do_scroll_up();
|
||||
} else if (func == do_down || func == do_scroll_down) {
|
||||
} else if (function == do_down || function == do_scroll_down) {
|
||||
if (openfile->edittop->lineno + editwinrows - 1 < openfile->filebot->lineno)
|
||||
do_scroll_down();
|
||||
} else if (func == do_page_up || func == do_page_down ||
|
||||
func == to_first_line || func == to_last_line) {
|
||||
func();
|
||||
} else if (func == do_search_backward || func == do_search_forward ||
|
||||
func == do_findprevious || func == do_findnext) {
|
||||
func();
|
||||
} else if (function == do_page_up || function == do_page_down ||
|
||||
function == to_first_line || function == to_last_line) {
|
||||
function();
|
||||
} else if (function == do_search_backward || function == do_search_forward ||
|
||||
function == do_findprevious || function == do_findnext) {
|
||||
function();
|
||||
bottombars(MHELP);
|
||||
#ifdef ENABLE_NANORC
|
||||
} else if (func == (functionptrtype)implant) {
|
||||
implant(first_sc_for(MHELP, func)->expansion);
|
||||
} else if (function == (functionptrtype)implant) {
|
||||
implant(first_sc_for(MHELP, function)->expansion);
|
||||
#endif
|
||||
#ifdef ENABLE_MOUSE
|
||||
} else if (kbinput == KEY_MOUSE) {
|
||||
int dummy_row, dummy_col;
|
||||
get_mouseinput(&dummy_row, &dummy_col, TRUE);
|
||||
get_mouseinput(&dummy_row, &dummy_col);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
} else if (kbinput == KEY_WINCH) {
|
||||
} else if (kbinput == START_OF_PASTE) {
|
||||
while (get_kbinput(midwin, BLIND) != END_OF_PASTE)
|
||||
;
|
||||
statusline(AHEM, _("Paste is ignored"));
|
||||
} else if (kbinput == THE_WINDOW_RESIZED) {
|
||||
; /* Nothing to do. */
|
||||
#endif
|
||||
} else if (func == do_exit) {
|
||||
} else if (function == full_refresh) {
|
||||
full_refresh();
|
||||
} else if (function == do_exit) {
|
||||
break;
|
||||
} else
|
||||
unbound_key(kbinput);
|
||||
@@ -532,9 +542,12 @@ void show_help(void)
|
||||
|
||||
#ifdef ENABLE_LINENUMBERS
|
||||
margin = was_margin;
|
||||
editwincols = COLS - margin - thebar;
|
||||
editwincols = COLS - margin - sidebar;
|
||||
#endif
|
||||
tabsize = was_tabsize;
|
||||
#ifndef NANO_TINY
|
||||
spotlighted = was_lighted;
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
syntaxstr = was_syntax;
|
||||
have_palette = FALSE;
|
||||
@@ -557,7 +570,7 @@ void show_help(void)
|
||||
bottombars(oldmenu);
|
||||
|
||||
#ifdef ENABLE_BROWSER
|
||||
if (oldmenu & (MBROWSER|MWHEREISFILE|MGOTODIR))
|
||||
if (oldmenu & (MBROWSER|MGOTODIR|MWHEREISFILE))
|
||||
browser_refresh();
|
||||
else
|
||||
#endif
|
||||
|
||||
381
src/history.c
381
src/history.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* history.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2003-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||
* Copyright (C) 2003-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019, 2025 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -36,12 +36,12 @@
|
||||
|
||||
static bool history_changed = FALSE;
|
||||
/* Whether any of the history lists has changed. */
|
||||
static char *poshistname = NULL;
|
||||
/* The name of the positions-history file. */
|
||||
static char *registername = NULL;
|
||||
/* The name of the positions-register file. */
|
||||
static time_t latest_timestamp = 942927132;
|
||||
/* The last time the positions-history file was written. */
|
||||
static poshiststruct *position_history = NULL;
|
||||
/* The list of filenames with their last cursor positions. */
|
||||
/* The last time the positions-register file was written. */
|
||||
static positionstruct *positions_register = NULL;
|
||||
/* A list of recently opened files with their last cursor position. */
|
||||
|
||||
/* Initialize the lists of historical search and replace strings
|
||||
* and the list of historical executed commands. */
|
||||
@@ -114,29 +114,30 @@ void update_history(linestruct **item, const char *text, bool avoid_duplicates)
|
||||
|
||||
/* If an identical string was found, delete that item. */
|
||||
if (thesame) {
|
||||
linestruct *after = thesame->next;
|
||||
|
||||
/* If the string is at the head of the list, move the head. */
|
||||
if (thesame == *htop)
|
||||
*htop = after;
|
||||
*htop = thesame->next;
|
||||
else
|
||||
thesame->prev->next = thesame->next;
|
||||
thesame->next->prev = thesame->prev;
|
||||
|
||||
unlink_node(thesame);
|
||||
renumber_from(after);
|
||||
free(thesame->data);
|
||||
free(thesame);
|
||||
(*hbot)->lineno--;
|
||||
}
|
||||
|
||||
/* If the history is full, delete the oldest item (the one at the
|
||||
* head of the list), to make room for a new item at the end. */
|
||||
if ((*hbot)->lineno == MAX_SEARCH_HISTORY + 1) {
|
||||
linestruct *oldest = *htop;
|
||||
|
||||
if ((*hbot)->lineno > MAX_SEARCH_HISTORY) {
|
||||
*htop = (*htop)->next;
|
||||
unlink_node(oldest);
|
||||
renumber_from(*htop);
|
||||
free((*htop)->prev->data);
|
||||
free((*htop)->prev);
|
||||
(*htop)->prev = NULL;
|
||||
(*hbot)->lineno--;
|
||||
}
|
||||
|
||||
/* Store the fresh string in the last item, then create a new item. */
|
||||
(*hbot)->data = mallocstrcpy((*hbot)->data, text);
|
||||
splice_node(*hbot, make_new_node(*hbot));
|
||||
(*hbot)->next = make_new_node(*hbot);
|
||||
*hbot = (*hbot)->next;
|
||||
(*hbot)->data = copy_of("");
|
||||
|
||||
@@ -172,7 +173,7 @@ char *get_history_completion(linestruct **here, char *string, size_t len)
|
||||
* for a match of len characters. Skip over an exact match. */
|
||||
item = find_in_history((*here)->prev, htop, string, len);
|
||||
|
||||
while (item != NULL && strcmp(item->data, string) == 0)
|
||||
while (item && strcmp(item->data, string) == 0)
|
||||
item = find_in_history(item->prev, htop, string, len);
|
||||
|
||||
if (item) {
|
||||
@@ -183,7 +184,7 @@ char *get_history_completion(linestruct **here, char *string, size_t len)
|
||||
/* Now search from the bottom of the list to the original position. */
|
||||
item = find_in_history(hbot, *here, string, len);
|
||||
|
||||
while (item != NULL && strcmp(item->data, string) == 0)
|
||||
while (item && strcmp(item->data, string) == 0)
|
||||
item = find_in_history(item->prev, *here, string, len);
|
||||
|
||||
if (item) {
|
||||
@@ -204,11 +205,11 @@ bool have_statedir(void)
|
||||
|
||||
get_homedir();
|
||||
|
||||
if (homedir != NULL) {
|
||||
if (homedir) {
|
||||
statedir = concatenate(homedir, "/.nano/");
|
||||
|
||||
if (stat(statedir, &dirinfo) == 0 && S_ISDIR(dirinfo.st_mode)) {
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
registername = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -219,21 +220,21 @@ bool have_statedir(void)
|
||||
if (homedir == NULL && xdgdatadir == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (xdgdatadir != NULL)
|
||||
if (xdgdatadir)
|
||||
statedir = concatenate(xdgdatadir, "/nano/");
|
||||
else
|
||||
statedir = concatenate(homedir, "/.local/share/nano/");
|
||||
|
||||
if (stat(statedir, &dirinfo) == -1) {
|
||||
if (stat(statedir, &dirinfo) < 0) {
|
||||
if (xdgdatadir == NULL) {
|
||||
char *statepath = concatenate(homedir, "/.local");
|
||||
mkdir(statepath, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
mkdir(statepath, S_IRWXU);
|
||||
free(statepath);
|
||||
statepath = concatenate(homedir, "/.local/share");
|
||||
mkdir(statepath, S_IRWXU);
|
||||
free(statepath);
|
||||
}
|
||||
if (mkdir(statedir, S_IRWXU) == -1) {
|
||||
if (mkdir(statedir, S_IRWXU) < 0) {
|
||||
jot_error(N_("Unable to create directory %s: %s\n"
|
||||
"It is required for saving/loading "
|
||||
"search history or cursor positions.\n"),
|
||||
@@ -248,49 +249,49 @@ bool have_statedir(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
poshistname = concatenate(statedir, POSITION_HISTORY);
|
||||
registername = concatenate(statedir, POSITION_HISTORY);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Load the histories for Search, Replace With, and Execute Command. */
|
||||
void load_history(void)
|
||||
{
|
||||
char *histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *histfile = fopen(histname, "rb");
|
||||
char *historyname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *histories = fopen(historyname, "rb");
|
||||
|
||||
/* If reading an existing file failed, don't save history when we quit. */
|
||||
if (histfile == NULL && errno != ENOENT) {
|
||||
jot_error(N_("Error reading %s: %s"), histname, strerror(errno));
|
||||
if (histories == NULL && errno != ENOENT) {
|
||||
jot_error(N_("Error reading %s: %s"), historyname, strerror(errno));
|
||||
UNSET(HISTORYLOG);
|
||||
}
|
||||
|
||||
if (histfile == NULL) {
|
||||
free(histname);
|
||||
if (histories == NULL) {
|
||||
free(historyname);
|
||||
return;
|
||||
}
|
||||
|
||||
linestruct **history = &search_history;
|
||||
linestruct **list = &search_history;
|
||||
char *stanza = NULL;
|
||||
size_t dummy = 0;
|
||||
ssize_t read;
|
||||
|
||||
/* Load the three history lists (first search, then replace, then execute)
|
||||
* from oldest entry to newest. Between two lists there is an empty line. */
|
||||
while ((read = getline(&stanza, &dummy, histfile)) > 0) {
|
||||
while ((read = getline(&stanza, &dummy, histories)) > 0) {
|
||||
stanza[--read] = '\0';
|
||||
if (read > 0) {
|
||||
recode_NUL_to_LF(stanza, read);
|
||||
update_history(history, stanza, IGNORE_DUPLICATES);
|
||||
} else if (history == &search_history)
|
||||
history = &replace_history;
|
||||
update_history(list, stanza, IGNORE_DUPLICATES);
|
||||
} else if (list == &search_history)
|
||||
list = &replace_history;
|
||||
else
|
||||
history = &execute_history;
|
||||
list = &execute_history;
|
||||
}
|
||||
|
||||
if (fclose(histfile) == EOF)
|
||||
jot_error(N_("Error reading %s: %s"), histname, strerror(errno));
|
||||
if (fclose(histories) == EOF)
|
||||
jot_error(N_("Error reading %s: %s"), historyname, strerror(errno));
|
||||
|
||||
free(histname);
|
||||
free(historyname);
|
||||
free(stanza);
|
||||
|
||||
/* Reading in the lists has marked them as changed; undo this side effect. */
|
||||
@@ -299,19 +300,17 @@ void load_history(void)
|
||||
|
||||
/* Write the lines of a history list, starting at head, from oldest to newest,
|
||||
* to the given file. Return TRUE if writing succeeded, and FALSE otherwise. */
|
||||
bool write_list(const linestruct *head, FILE *histfile)
|
||||
bool write_list(const linestruct *head, FILE *histories)
|
||||
{
|
||||
const linestruct *item;
|
||||
|
||||
for (item = head; item != NULL; item = item->next) {
|
||||
size_t length = strlen(item->data);
|
||||
|
||||
/* Decode 0x0A bytes as embedded NULs. */
|
||||
recode_LF_to_NUL(item->data);
|
||||
size_t length = recode_LF_to_NUL(item->data);
|
||||
|
||||
if (fwrite(item->data, sizeof(char), length, histfile) < length)
|
||||
if (fwrite(item->data, 1, length, histories) < length)
|
||||
return FALSE;
|
||||
if (putc('\n', histfile) == EOF)
|
||||
if (putc('\n', histories) == EOF)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -321,66 +320,108 @@ bool write_list(const linestruct *head, FILE *histfile)
|
||||
/* Save the histories for Search, Replace With, and Execute Command. */
|
||||
void save_history(void)
|
||||
{
|
||||
char *histname;
|
||||
FILE *histfile;
|
||||
|
||||
/* If the histories are unchanged, don't bother saving them. */
|
||||
if (!history_changed)
|
||||
return;
|
||||
|
||||
histname = concatenate(statedir, SEARCH_HISTORY);
|
||||
histfile = fopen(histname, "wb");
|
||||
char *historyname = concatenate(statedir, SEARCH_HISTORY);
|
||||
FILE *histories = fopen(historyname, "wb");
|
||||
|
||||
if (histfile == NULL) {
|
||||
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
|
||||
free(histname);
|
||||
if (histories == NULL) {
|
||||
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
|
||||
free(historyname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't allow others to read or write the history file. */
|
||||
if (chmod(histname, S_IRUSR | S_IWUSR) < 0)
|
||||
jot_error(N_("Cannot limit permissions on %s: %s"), histname, strerror(errno));
|
||||
if (chmod(historyname, S_IRUSR | S_IWUSR) < 0)
|
||||
jot_error(N_("Cannot limit permissions on %s: %s"), historyname, strerror(errno));
|
||||
|
||||
if (!write_list(searchtop, histfile) || !write_list(replacetop, histfile) ||
|
||||
!write_list(executetop, histfile))
|
||||
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
|
||||
if (!write_list(searchtop, histories) || !write_list(replacetop, histories) ||
|
||||
!write_list(executetop, histories))
|
||||
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
|
||||
|
||||
if (fclose(histfile) == EOF)
|
||||
jot_error(N_("Error writing %s: %s"), histname, strerror(errno));
|
||||
if (fclose(histories) == EOF)
|
||||
jot_error(N_("Error writing %s: %s"), historyname, strerror(errno));
|
||||
|
||||
free(histname);
|
||||
free(historyname);
|
||||
}
|
||||
|
||||
/* Load the recorded cursor positions for files that were edited. */
|
||||
void load_poshistory(void)
|
||||
/* Return as a string... the line numbers of the lines with an anchor. */
|
||||
char *stringify_anchors(void)
|
||||
{
|
||||
FILE *histfile = fopen(poshistname, "rb");
|
||||
char *string = copy_of("");
|
||||
#ifndef NANO_TINY
|
||||
char number[24];
|
||||
|
||||
/* If reading an existing file failed, don't save history when we quit. */
|
||||
if (histfile == NULL && errno != ENOENT) {
|
||||
jot_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
|
||||
for (linestruct *line = openfile->filetop; line != NULL; line = line->next)
|
||||
if (line->has_anchor) {
|
||||
sprintf(number, "%zi ", line->lineno);
|
||||
string = nrealloc(string, strlen(string) + strlen(number) + 1);
|
||||
strcat(string, number);
|
||||
}
|
||||
#endif
|
||||
return string;
|
||||
}
|
||||
|
||||
/* Set an anchor for each line number in the given string. */
|
||||
void restore_anchors(char *string)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
linestruct *line = openfile->filetop;
|
||||
ssize_t number;
|
||||
char *space;
|
||||
|
||||
while (*string) {
|
||||
if ((space = strchr(string, ' ')) == NULL)
|
||||
return;
|
||||
*space = '\0';
|
||||
number = atoi(string);
|
||||
*space = ' ';
|
||||
string = space + 1;
|
||||
|
||||
while (line->lineno < number)
|
||||
if ((line = line->next) == NULL)
|
||||
return;
|
||||
|
||||
line->has_anchor = TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Load the recorded cursor positions for files that were opened. */
|
||||
void load_positions_register(void)
|
||||
{
|
||||
FILE *registry = fopen(registername, "rb");
|
||||
|
||||
/* If reading an existing file failed, don't save the register when we quit. */
|
||||
if (registry == NULL && errno != ENOENT) {
|
||||
jot_error(N_("Error reading %s: %s"), registername, strerror(errno));
|
||||
UNSET(POSITIONLOG);
|
||||
}
|
||||
|
||||
if (histfile == NULL)
|
||||
if (registry == NULL)
|
||||
return;
|
||||
|
||||
poshiststruct *lastitem = NULL;
|
||||
poshiststruct *newitem;
|
||||
char *lineptr, *columnptr;
|
||||
char *stanza = NULL;
|
||||
positionstruct *lastitem = NULL;
|
||||
positionstruct *newitem;
|
||||
char *stanza, *lineptr, *columnptr;
|
||||
char *phrase = NULL;
|
||||
struct stat fileinfo;
|
||||
size_t dummy = 0;
|
||||
ssize_t count = 0;
|
||||
ssize_t read;
|
||||
int count = 0;
|
||||
ssize_t length;
|
||||
|
||||
/* Read and parse each line, and store the extracted data. */
|
||||
while ((read = getline(&stanza, &dummy, histfile)) > 5) {
|
||||
while (count++ < 200 && (length = getline(&phrase, &dummy, registry)) > 1) {
|
||||
stanza = strchr(phrase, '/');
|
||||
length -= (stanza ? stanza - phrase : 0);
|
||||
|
||||
/* Decode NULs as embedded newlines. */
|
||||
recode_NUL_to_LF(stanza, read);
|
||||
recode_NUL_to_LF(stanza, length);
|
||||
|
||||
/* Find the spaces before column number and line number. */
|
||||
columnptr = revstrstr(stanza, " ", stanza + read - 3);
|
||||
columnptr = revstrstr(stanza, " ", stanza + length - 3);
|
||||
if (columnptr == NULL)
|
||||
continue;
|
||||
lineptr = revstrstr(stanza, " ", columnptr - 2);
|
||||
@@ -392,197 +433,167 @@ void load_poshistory(void)
|
||||
*(lineptr++) = '\0';
|
||||
|
||||
/* Create a new position record. */
|
||||
newitem = nmalloc(sizeof(poshiststruct));
|
||||
newitem = nmalloc(sizeof(positionstruct));
|
||||
newitem->filename = copy_of(stanza);
|
||||
newitem->linenumber = atoi(lineptr);
|
||||
newitem->columnnumber = atoi(columnptr);
|
||||
newitem->anchors = (phrase == stanza) ? NULL : measured_copy(phrase, stanza - phrase);
|
||||
newitem->next = NULL;
|
||||
|
||||
/* Add the record to the list. */
|
||||
if (position_history == NULL)
|
||||
position_history = newitem;
|
||||
if (positions_register == NULL)
|
||||
positions_register = newitem;
|
||||
else
|
||||
lastitem->next = newitem;
|
||||
|
||||
lastitem = newitem;
|
||||
|
||||
/* Impose a limit, so the file will not grow indefinitely. */
|
||||
if (++count > 200) {
|
||||
poshiststruct *drop_record = position_history;
|
||||
|
||||
position_history = position_history->next;
|
||||
|
||||
free(drop_record->filename);
|
||||
free(drop_record);
|
||||
}
|
||||
}
|
||||
|
||||
if (fclose(histfile) == EOF)
|
||||
jot_error(N_("Error reading %s: %s"), poshistname, strerror(errno));
|
||||
if (fclose(registry) == EOF)
|
||||
jot_error(N_("Error reading %s: %s"), registername, strerror(errno));
|
||||
|
||||
free(stanza);
|
||||
free(phrase);
|
||||
|
||||
if (stat(poshistname, &fileinfo) == 0)
|
||||
if (stat(registername, &fileinfo) == 0)
|
||||
latest_timestamp = fileinfo.st_mtime;
|
||||
}
|
||||
|
||||
/* Save the recorded cursor positions for files that were edited. */
|
||||
void save_poshistory(void)
|
||||
/* Save the recorded cursor positions for files that were opened. */
|
||||
void save_positions_register(void)
|
||||
{
|
||||
FILE *histfile = fopen(poshistname, "wb");
|
||||
FILE *registry = fopen(registername, "wb");
|
||||
struct stat fileinfo;
|
||||
poshiststruct *item;
|
||||
positionstruct *item;
|
||||
int count = 0;
|
||||
|
||||
if (histfile == NULL) {
|
||||
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
|
||||
if (registry == NULL) {
|
||||
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't allow others to read or write the history file. */
|
||||
if (chmod(poshistname, S_IRUSR | S_IWUSR) < 0)
|
||||
jot_error(N_("Cannot limit permissions on %s: %s"), poshistname, strerror(errno));
|
||||
/* Don't allow others to read or write the positions-register file. */
|
||||
if (chmod(registername, S_IRUSR | S_IWUSR) < 0)
|
||||
jot_error(N_("Cannot limit permissions on %s: %s"), registername, strerror(errno));
|
||||
|
||||
for (item = position_history; item != NULL; item = item->next) {
|
||||
for (item = positions_register; item != NULL && count++ < 200; item = item->next) {
|
||||
char *path_and_place;
|
||||
size_t length;
|
||||
size_t length = (item->anchors == NULL) ? 0 : strlen(item->anchors);
|
||||
|
||||
/* First write the string of line numbers with anchors, if any. */
|
||||
if (length && fwrite(item->anchors, 1, length, registry) < length)
|
||||
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
|
||||
|
||||
/* Assume 20 decimal positions each for line and column number,
|
||||
* plus two spaces, plus the line feed, plus the null byte. */
|
||||
path_and_place = nmalloc(strlen(item->filename) + 44);
|
||||
sprintf(path_and_place, "%s %zd %zd\n",
|
||||
item->filename, item->linenumber, item->columnnumber);
|
||||
length = strlen(path_and_place);
|
||||
|
||||
/* Encode newlines in filenames as NULs. */
|
||||
recode_LF_to_NUL(path_and_place);
|
||||
length = recode_LF_to_NUL(path_and_place);
|
||||
/* Restore the terminating newline. */
|
||||
path_and_place[length - 1] = '\n';
|
||||
|
||||
if (fwrite(path_and_place, sizeof(char), length, histfile) < length)
|
||||
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
|
||||
if (fwrite(path_and_place, 1, length, registry) < length)
|
||||
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
|
||||
|
||||
free(path_and_place);
|
||||
}
|
||||
|
||||
if (fclose(histfile) == EOF)
|
||||
jot_error(N_("Error writing %s: %s"), poshistname, strerror(errno));
|
||||
if (fclose(registry) == EOF)
|
||||
jot_error(N_("Error writing %s: %s"), registername, strerror(errno));
|
||||
|
||||
if (stat(poshistname, &fileinfo) == 0)
|
||||
if (stat(registername, &fileinfo) == 0)
|
||||
latest_timestamp = fileinfo.st_mtime;
|
||||
}
|
||||
|
||||
/* Reload the position history file if it has been modified since last load. */
|
||||
/* Reload the positions-register file if it has been modified since last load. */
|
||||
void reload_positions_if_needed(void)
|
||||
{
|
||||
poshiststruct *item, *nextone;
|
||||
positionstruct *item, *nextone;
|
||||
struct stat fileinfo;
|
||||
|
||||
if (stat(poshistname, &fileinfo) != 0 || fileinfo.st_mtime == latest_timestamp)
|
||||
if (stat(registername, &fileinfo) < 0 || fileinfo.st_mtime == latest_timestamp)
|
||||
return;
|
||||
|
||||
for (item = position_history; item != NULL; item = nextone) {
|
||||
for (item = positions_register; item != NULL; item = nextone) {
|
||||
nextone = item->next;
|
||||
free(item->filename);
|
||||
free(item->anchors);
|
||||
free(item);
|
||||
}
|
||||
|
||||
position_history = NULL;
|
||||
positions_register = NULL;
|
||||
|
||||
load_poshistory();
|
||||
load_positions_register();
|
||||
}
|
||||
|
||||
/* Update the recorded last file positions with the current position in the
|
||||
* current buffer. If no existing entry is found, add a new one at the end. */
|
||||
void update_poshistory(void)
|
||||
* current buffer. If no existing entry is found, add a new one at the top. */
|
||||
void update_positions_register(void)
|
||||
{
|
||||
char *fullpath = get_full_path(openfile->filename);
|
||||
poshiststruct *previous = NULL;
|
||||
poshiststruct *item, *theone;
|
||||
positionstruct *previous = NULL;
|
||||
positionstruct *item;
|
||||
|
||||
if (fullpath == NULL || openfile->filename[0] == '\0') {
|
||||
free(fullpath);
|
||||
if (fullpath == NULL)
|
||||
return;
|
||||
}
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
/* Look for a matching filename in the list. */
|
||||
for (item = position_history; item != NULL; item = item->next) {
|
||||
for (item = positions_register; item != NULL; item = item->next) {
|
||||
if (!strcmp(item->filename, fullpath))
|
||||
break;
|
||||
previous = item;
|
||||
}
|
||||
|
||||
/* Don't record files that have the default cursor position. */
|
||||
if (openfile->current->lineno == 1 && openfile->current_x == 0) {
|
||||
if (item != NULL) {
|
||||
if (previous == NULL)
|
||||
position_history = item->next;
|
||||
else
|
||||
previous->next = item->next;
|
||||
free(item->filename);
|
||||
free(item);
|
||||
save_poshistory();
|
||||
}
|
||||
free(fullpath);
|
||||
return;
|
||||
/* If no match was found, make a new node; otherwise, unlink the match. */
|
||||
if (item == NULL) {
|
||||
item = nmalloc(sizeof(positionstruct));
|
||||
item->filename = copy_of(fullpath);
|
||||
item->anchors = NULL;
|
||||
} else if (previous)
|
||||
previous->next = item->next;
|
||||
|
||||
/* Place the found or new node at the beginning, if not already there. */
|
||||
if (item != positions_register) {
|
||||
item->next = positions_register;
|
||||
positions_register = item;
|
||||
}
|
||||
|
||||
theone = item;
|
||||
|
||||
/* If we didn't find it, make a new node; otherwise, if we're
|
||||
* not at the end, move the matching one to the end. */
|
||||
if (theone == NULL) {
|
||||
theone = nmalloc(sizeof(poshiststruct));
|
||||
theone->filename = copy_of(fullpath);
|
||||
if (position_history == NULL)
|
||||
position_history = theone;
|
||||
else
|
||||
previous->next = theone;
|
||||
} else if (item->next != NULL) {
|
||||
if (previous == NULL)
|
||||
position_history = item->next;
|
||||
else
|
||||
previous->next = item->next;
|
||||
while (item->next != NULL)
|
||||
item = item->next;
|
||||
item->next = theone;
|
||||
}
|
||||
|
||||
/* Store the last cursor position. */
|
||||
theone->linenumber = openfile->current->lineno;
|
||||
theone->columnnumber = xplustabs() + 1;
|
||||
theone->next = NULL;
|
||||
/* Record the last cursor position and any anchors. */
|
||||
item->linenumber = openfile->current->lineno;
|
||||
item->columnnumber = xplustabs() + 1;
|
||||
free(item->anchors);
|
||||
item->anchors = stringify_anchors();
|
||||
|
||||
free(fullpath);
|
||||
|
||||
save_poshistory();
|
||||
save_positions_register();
|
||||
}
|
||||
|
||||
/* Check whether the given file matches an existing entry in the recorded
|
||||
* last file positions. If not, return FALSE. If yes, return TRUE and
|
||||
* set line and column to the retrieved values. */
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column)
|
||||
/* Check whether the current filename matches an entry in the list of
|
||||
* recorded positions. If yes, restore the relevant cursor position. */
|
||||
void restore_cursor_position_if_any(void)
|
||||
{
|
||||
char *fullpath = get_full_path(file);
|
||||
poshiststruct *item;
|
||||
char *fullpath = get_full_path(openfile->filename);
|
||||
positionstruct *item;
|
||||
|
||||
if (fullpath == NULL)
|
||||
return FALSE;
|
||||
return;
|
||||
|
||||
reload_positions_if_needed();
|
||||
|
||||
item = position_history;
|
||||
while (item != NULL && strcmp(item->filename, fullpath) != 0)
|
||||
item = positions_register;
|
||||
while (item && strcmp(item->filename, fullpath) != 0)
|
||||
item = item->next;
|
||||
|
||||
free(fullpath);
|
||||
|
||||
if (item == NULL)
|
||||
return FALSE;
|
||||
|
||||
*line = item->linenumber;
|
||||
*column = item->columnnumber;
|
||||
return TRUE;
|
||||
if (item && item->anchors)
|
||||
restore_anchors(item->anchors);
|
||||
if (item)
|
||||
goto_line_and_column(item->linenumber, item->columnnumber, TRUE);
|
||||
}
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
|
||||
340
src/move.c
340
src/move.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* move.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2018 Benno Schulenberg *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014-2018, 2020, 2024, 2026 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -37,13 +37,22 @@ void to_first_line(void)
|
||||
void to_last_line(void)
|
||||
{
|
||||
openfile->current = openfile->filebot;
|
||||
openfile->current_x = (inhelp) ? 0 : strlen(openfile->filebot->data);
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (openfile->current->folded) {
|
||||
openfile->current = get_start_of_folded_segment(openfile->current);
|
||||
openfile->current_x = 0;
|
||||
} else
|
||||
#endif
|
||||
openfile->current_x = (inhelp) ? 0 : strlen(openfile->filebot->data);
|
||||
openfile->placewewant = xplustabs();
|
||||
|
||||
/* Set the last line of the screen as the target for the cursor. */
|
||||
openfile->current_y = editwinrows - 1;
|
||||
openfile->cursor_row = editwinrows - 1;
|
||||
|
||||
refresh_needed = TRUE;
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
focusing = FALSE;
|
||||
}
|
||||
|
||||
@@ -80,7 +89,7 @@ size_t proper_x(linestruct *line, size_t *leftedge, bool forward,
|
||||
column / tabsize < (*leftedge + editwincols - 1) / tabsize))) {
|
||||
index++;
|
||||
|
||||
if (shifted != NULL)
|
||||
if (shifted)
|
||||
*shifted = TRUE;
|
||||
}
|
||||
|
||||
@@ -95,8 +104,8 @@ size_t proper_x(linestruct *line, size_t *leftedge, bool forward,
|
||||
* the middle of a tab that crosses a row boundary. */
|
||||
void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
||||
{
|
||||
bool shifted = FALSE;
|
||||
size_t was_edge = *leftedge;
|
||||
bool shifted = FALSE;
|
||||
|
||||
openfile->current_x = proper_x(openfile->current, leftedge, forward,
|
||||
actual_last_column(*leftedge, target), &shifted);
|
||||
@@ -109,6 +118,15 @@ void set_proper_index_and_pww(size_t *leftedge, size_t target, bool forward)
|
||||
openfile->placewewant = *leftedge + target;
|
||||
}
|
||||
|
||||
/* Move the cursor position on the current line to the desired column */
|
||||
void move_cursor_to_proper_column(void)
|
||||
{
|
||||
size_t leftedge;
|
||||
size_t target_column;
|
||||
get_edge_and_target(&leftedge, &target_column);
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
}
|
||||
|
||||
/* Move up almost one screenful. */
|
||||
void do_page_up(void)
|
||||
{
|
||||
@@ -121,7 +139,7 @@ void do_page_up(void)
|
||||
if (ISSET(JUMPY_SCROLLING)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
openfile->cursor_row = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
#endif
|
||||
@@ -153,7 +171,7 @@ void do_page_down(void)
|
||||
if (ISSET(JUMPY_SCROLLING)) {
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
openfile->current_y = 0;
|
||||
openfile->cursor_row = 0;
|
||||
target_column = 0;
|
||||
} else
|
||||
#endif
|
||||
@@ -173,11 +191,68 @@ void do_page_down(void)
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Place the cursor on the first row in the viewport. */
|
||||
void to_top_row(void)
|
||||
{
|
||||
size_t leftedge, offset;
|
||||
|
||||
get_edge_and_target(&leftedge, &offset);
|
||||
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
|
||||
set_proper_index_and_pww(&leftedge, offset, FALSE);
|
||||
|
||||
refresh_needed = (openfile->mark != NULL);
|
||||
}
|
||||
|
||||
/* Place the cursor on the last row in the viewport, when possible. */
|
||||
void to_bottom_row(void)
|
||||
{
|
||||
size_t leftedge, offset;
|
||||
|
||||
get_edge_and_target(&leftedge, &offset);
|
||||
|
||||
openfile->current = openfile->edittop;
|
||||
leftedge = openfile->firstcolumn;
|
||||
|
||||
go_forward_chunks(editwinrows - 1, &openfile->current, &leftedge);
|
||||
set_proper_index_and_pww(&leftedge, offset, TRUE);
|
||||
|
||||
refresh_needed = (openfile->mark != NULL);
|
||||
}
|
||||
|
||||
/* Put the cursor line at the center, then the top, then the bottom. */
|
||||
void do_cycle(void)
|
||||
{
|
||||
if (cycling_aim == 0)
|
||||
adjust_viewport(CENTERING);
|
||||
else {
|
||||
openfile->cursor_row = (cycling_aim == 1) ? 0 : editwinrows - 1;
|
||||
adjust_viewport(STATIONARY);
|
||||
}
|
||||
|
||||
cycling_aim = (cycling_aim + 1) % 3;
|
||||
|
||||
draw_all_subwindows();
|
||||
full_refresh();
|
||||
}
|
||||
|
||||
/* Scroll the line with the cursor to the center of the screen. */
|
||||
void do_center(void)
|
||||
{
|
||||
adjust_viewport(CENTERING);
|
||||
draw_all_subwindows();
|
||||
full_refresh();
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
/* Move to the first beginning of a paragraph before the current line. */
|
||||
void do_para_begin(linestruct **line)
|
||||
{
|
||||
if ((*line)->prev != NULL)
|
||||
if ((*line)->prev)
|
||||
*line = (*line)->prev;
|
||||
|
||||
while (!begpar(*line, 0))
|
||||
@@ -187,11 +262,10 @@ void do_para_begin(linestruct **line)
|
||||
/* Move down to the last line of the first found paragraph. */
|
||||
void do_para_end(linestruct **line)
|
||||
{
|
||||
while ((*line)->next != NULL && !inpar(*line))
|
||||
while ((*line)->next && !inpar(*line))
|
||||
*line = (*line)->next;
|
||||
|
||||
while ((*line)->next != NULL && inpar((*line)->next) &&
|
||||
!begpar((*line)->next, 0))
|
||||
while ((*line)->next && inpar((*line)->next) && !begpar((*line)->next, 0))
|
||||
*line = (*line)->next;
|
||||
}
|
||||
|
||||
@@ -215,13 +289,16 @@ void to_para_end(void)
|
||||
|
||||
/* Step beyond the last line of the paragraph, if possible;
|
||||
* otherwise, move to the end of the line. */
|
||||
if (openfile->current->next != NULL) {
|
||||
if (openfile->current->next) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
} else
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
|
||||
edit_redraw(was_current, CENTERING);
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
}
|
||||
#endif /* ENABLE_JUSTIFY */
|
||||
|
||||
@@ -229,19 +306,28 @@ void to_para_end(void)
|
||||
void to_prev_block(void)
|
||||
{
|
||||
linestruct *was_current = openfile->current;
|
||||
linestruct *line_step = get_prev_visible_line(openfile->current);
|
||||
bool is_text = FALSE, seen_text = FALSE;
|
||||
|
||||
/* Skip backward until first blank line after some nonblank line(s). */
|
||||
while (openfile->current->prev != NULL && (!seen_text || is_text)) {
|
||||
openfile->current = openfile->current->prev;
|
||||
while (line_step && (!seen_text || is_text)) {
|
||||
openfile->current = line_step;
|
||||
line_step = get_prev_visible_line(line_step);
|
||||
#ifdef ENABLE_FOLDING
|
||||
/* Skip over the visibly drawn line of the folded segment */
|
||||
if (openfile->current->folded)
|
||||
continue;
|
||||
#endif
|
||||
is_text = !white_string(openfile->current->data);
|
||||
seen_text = seen_text || is_text;
|
||||
}
|
||||
|
||||
/* Step forward one line again if we passed text but this line is blank. */
|
||||
if (seen_text && openfile->current->next != NULL &&
|
||||
white_string(openfile->current->data))
|
||||
openfile->current = openfile->current->next;
|
||||
line_step = get_next_visible_line(openfile->current);
|
||||
if (seen_text && line_step && white_string(openfile->current->data)) {
|
||||
openfile->current = line_step;
|
||||
line_step = get_next_visible_line(line_step);
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
@@ -251,39 +337,64 @@ void to_prev_block(void)
|
||||
void to_next_block(void)
|
||||
{
|
||||
linestruct *was_current = openfile->current;
|
||||
linestruct *line_step = get_next_visible_line(openfile->current);
|
||||
bool is_white = white_string(openfile->current->data);
|
||||
bool seen_white = is_white;
|
||||
|
||||
/* Skip forward until first nonblank line after some blank line(s). */
|
||||
while (openfile->current->next != NULL && (!seen_white || is_white)) {
|
||||
openfile->current = openfile->current->next;
|
||||
while (line_step && (!seen_white || is_white)) {
|
||||
openfile->current = line_step;
|
||||
line_step = get_next_visible_line(line_step);
|
||||
#ifdef ENABLE_FOLDING
|
||||
/* Skip over the visibly drawn line of the folded segment */
|
||||
if (openfile->current->folded)
|
||||
continue;
|
||||
#endif
|
||||
is_white = white_string(openfile->current->data);
|
||||
seen_white = seen_white || is_white;
|
||||
}
|
||||
|
||||
openfile->current_x = 0;
|
||||
edit_redraw(was_current, CENTERING);
|
||||
#ifdef ENABLE_COLOR
|
||||
recook |= perturbed;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Move to the previous word. */
|
||||
void do_prev_word(void)
|
||||
/* Move to the previous word.
|
||||
* When allow_folded is true, will move to previous word even if inside
|
||||
* a folded segment. */
|
||||
void do_prev_word(bool allow_folded)
|
||||
{
|
||||
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (!allow_folded && openfile->current->folded) {
|
||||
openfile->current = get_prev_visible_line(openfile->current);
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the head of a line, move to the end of the preceding one. */
|
||||
if (openfile->current_x == 0) {
|
||||
if (openfile->current->prev == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->prev;
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (!allow_folded) {
|
||||
openfile->current = get_prev_visible_line(openfile->current);
|
||||
if (openfile->current->folded)
|
||||
openfile->current = openfile->current->prev;
|
||||
} else
|
||||
#endif
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
|
||||
/* Step back one character. */
|
||||
openfile->current_x = step_left(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
||||
|
||||
if (is_word_char(openfile->current->data + openfile->current_x,
|
||||
punctuation_as_letters)) {
|
||||
@@ -304,13 +415,14 @@ void do_prev_word(void)
|
||||
|
||||
if (step_forward)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
openfile->current_x = step_right(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
}
|
||||
|
||||
/* Move to the next word. If after_ends is TRUE, stop at the ends of words
|
||||
* instead of at their beginnings. Return TRUE if we started on a word. */
|
||||
bool do_next_word(bool after_ends)
|
||||
* instead of at their beginnings. If allow_folded is true, go to next word
|
||||
* even if it's inside a folded segment. Return TRUE if we started on a word. */
|
||||
bool do_next_word(bool after_ends, bool allow_folded)
|
||||
{
|
||||
bool punctuation_as_letters = ISSET(WORD_BOUNDS);
|
||||
bool started_on_word = is_word_char(openfile->current->data +
|
||||
@@ -320,6 +432,12 @@ bool do_next_word(bool after_ends)
|
||||
bool seen_word = started_on_word;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (!allow_folded & openfile->current->folded) {
|
||||
openfile->current = get_next_visible_line(openfile->current);
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
#endif
|
||||
/* Move forward until we reach the start of a word. */
|
||||
while (TRUE) {
|
||||
/* If at the end of a line, move to the beginning of the next one. */
|
||||
@@ -327,13 +445,23 @@ bool do_next_word(bool after_ends)
|
||||
/* When at end of file, stop. */
|
||||
if (openfile->current->next == NULL)
|
||||
break;
|
||||
openfile->current = openfile->current->next;
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (!allow_folded) {
|
||||
openfile->current = get_next_visible_line(openfile->current);
|
||||
if (openfile->current->folded) {
|
||||
/* get_next_visible_line() gives the start of a folded segment,
|
||||
* so skip to the end. */
|
||||
openfile->current = get_end_of_folded_segment(openfile->current);
|
||||
openfile->current = openfile->current->next;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current_x = 0;
|
||||
seen_space = TRUE;
|
||||
} else {
|
||||
/* Step forward one character. */
|
||||
openfile->current_x = step_right(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
@@ -367,6 +495,8 @@ bool do_next_word(bool after_ends)
|
||||
}
|
||||
}
|
||||
|
||||
UNFOLD_SEGMENT(openfile->current);
|
||||
|
||||
return started_on_word;
|
||||
}
|
||||
|
||||
@@ -375,7 +505,7 @@ void to_prev_word(void)
|
||||
{
|
||||
linestruct *was_current = openfile->current;
|
||||
|
||||
do_prev_word();
|
||||
do_prev_word(DISALLOW_FOLDED);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
@@ -386,7 +516,7 @@ void to_next_word(void)
|
||||
{
|
||||
linestruct *was_current = openfile->current;
|
||||
|
||||
do_next_word(ISSET(AFTER_ENDS));
|
||||
do_next_word(ISSET(AFTER_ENDS), DISALLOW_FOLDED);
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
@@ -401,25 +531,30 @@ void do_home(void)
|
||||
bool moved_off_chunk = TRUE;
|
||||
#ifndef NANO_TINY
|
||||
bool moved = FALSE;
|
||||
size_t leftedge = 0, leftedge_x = 0;
|
||||
size_t leftedge = 0;
|
||||
size_t left_x = 0;
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (openfile->current->folded)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
leftedge = leftedge_for(was_column, openfile->current);
|
||||
leftedge_x = proper_x(openfile->current, &leftedge, FALSE, leftedge,
|
||||
NULL);
|
||||
left_x = proper_x(openfile->current, &leftedge, FALSE, leftedge, NULL);
|
||||
}
|
||||
|
||||
if (ISSET(SMART_HOME)) {
|
||||
size_t indent_x = indent_length(openfile->current->data);
|
||||
|
||||
if (openfile->current->data[indent_x] != '\0') {
|
||||
if (openfile->current->data[indent_x]) {
|
||||
/* If we're exactly on the indent, move fully home. Otherwise,
|
||||
* when not softwrapping or not after the first nonblank chunk,
|
||||
* move to the first nonblank character. */
|
||||
if (openfile->current_x == indent_x) {
|
||||
openfile->current_x = 0;
|
||||
moved = TRUE;
|
||||
} else if (!ISSET(SOFTWRAP) || leftedge_x <= indent_x) {
|
||||
} else if (left_x <= indent_x) {
|
||||
openfile->current_x = indent_x;
|
||||
moved = TRUE;
|
||||
}
|
||||
@@ -429,10 +564,10 @@ void do_home(void)
|
||||
if (!moved && ISSET(SOFTWRAP)) {
|
||||
/* If already at the left edge of the screen, move fully home.
|
||||
* Otherwise, move to the left edge. */
|
||||
if (openfile->current_x == leftedge_x)
|
||||
if (openfile->current_x == left_x)
|
||||
openfile->current_x = 0;
|
||||
else {
|
||||
openfile->current_x = leftedge_x;
|
||||
openfile->current_x = left_x;
|
||||
openfile->placewewant = leftedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
@@ -461,13 +596,19 @@ void do_end(void)
|
||||
size_t line_len = strlen(openfile->current->data);
|
||||
bool moved_off_chunk = TRUE;
|
||||
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (openfile->current->folded)
|
||||
return;
|
||||
#endif
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (ISSET(SOFTWRAP)) {
|
||||
bool kickoff = TRUE;
|
||||
bool last_chunk = FALSE;
|
||||
size_t leftedge = leftedge_for(was_column, openfile->current);
|
||||
size_t rightedge = get_softwrap_breakpoint(openfile->current->data,
|
||||
leftedge, &last_chunk);
|
||||
size_t rightedge_x;
|
||||
leftedge, &kickoff, &last_chunk);
|
||||
size_t right_x;
|
||||
|
||||
/* If we're on the last chunk, we're already at the end of the line.
|
||||
* Otherwise, we're one column past the end of the line. Shifting
|
||||
@@ -476,14 +617,14 @@ void do_end(void)
|
||||
if (!last_chunk)
|
||||
rightedge--;
|
||||
|
||||
rightedge_x = actual_x(openfile->current->data, rightedge);
|
||||
right_x = actual_x(openfile->current->data, rightedge);
|
||||
|
||||
/* If already at the right edge of the screen, move fully to
|
||||
* the end of the line. Otherwise, move to the right edge. */
|
||||
if (openfile->current_x == rightedge_x)
|
||||
if (openfile->current_x == right_x)
|
||||
openfile->current_x = line_len;
|
||||
else {
|
||||
openfile->current_x = rightedge_x;
|
||||
openfile->current_x = right_x;
|
||||
openfile->placewewant = rightedge;
|
||||
moved_off_chunk = FALSE;
|
||||
}
|
||||
@@ -516,7 +657,8 @@ void do_up(void)
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, FALSE);
|
||||
|
||||
if (openfile->current_y == 0 && !ISSET(JUMPY_SCROLLING))
|
||||
if (openfile->cursor_row == 0 && !ISSET(JUMPY_SCROLLING) &&
|
||||
(tabsize < editwincols || !ISSET(SOFTWRAP)))
|
||||
edit_scroll(BACKWARD);
|
||||
else
|
||||
edit_redraw(was_current, FLOWING);
|
||||
@@ -539,7 +681,8 @@ void do_down(void)
|
||||
|
||||
set_proper_index_and_pww(&leftedge, target_column, TRUE);
|
||||
|
||||
if (openfile->current_y == editwinrows - 1 && !ISSET(JUMPY_SCROLLING))
|
||||
if (openfile->cursor_row == editwinrows - 1 && !ISSET(JUMPY_SCROLLING) &&
|
||||
(tabsize < editwincols || !ISSET(SOFTWRAP)))
|
||||
edit_scroll(FORWARD);
|
||||
else
|
||||
edit_redraw(was_current, FLOWING);
|
||||
@@ -556,7 +699,7 @@ void do_scroll_up(void)
|
||||
if (openfile->edittop->prev == NULL && openfile->firstcolumn == 0)
|
||||
return;
|
||||
|
||||
if (openfile->current_y == editwinrows - 1)
|
||||
if (openfile->cursor_row == editwinrows - 1)
|
||||
do_up();
|
||||
|
||||
if (editwinrows > 1)
|
||||
@@ -566,10 +709,10 @@ void do_scroll_up(void)
|
||||
/* Scroll down one line or chunk without moving the cursor textwise. */
|
||||
void do_scroll_down(void)
|
||||
{
|
||||
if (openfile->current_y == 0)
|
||||
if (openfile->cursor_row == 0)
|
||||
do_down();
|
||||
|
||||
if (editwinrows > 1 && (openfile->edittop->next != NULL
|
||||
if (editwinrows > 1 && (openfile->edittop->next
|
||||
#ifndef NANO_TINY
|
||||
|| (ISSET(SOFTWRAP) && (extra_chunks_in(openfile->edittop) >
|
||||
chunk_for(openfile->firstcolumn, openfile->edittop)))
|
||||
@@ -577,14 +720,6 @@ void do_scroll_down(void)
|
||||
))
|
||||
edit_scroll(FORWARD);
|
||||
}
|
||||
|
||||
/* Scroll the line with the cursor to the center of the screen. */
|
||||
void do_center(void)
|
||||
{
|
||||
adjust_viewport(CENTERING);
|
||||
draw_all_subwindows();
|
||||
full_refresh();
|
||||
}
|
||||
#endif /* !NANO_TINY || ENABLE_HELP */
|
||||
|
||||
/* Move left one character. */
|
||||
@@ -593,16 +728,14 @@ void do_left(void)
|
||||
linestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current_x > 0) {
|
||||
openfile->current_x = step_left(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
||||
#ifdef ENABLE_UTF8
|
||||
while (openfile->current_x > 0 &&
|
||||
is_zerowidth(openfile->current->data + openfile->current_x))
|
||||
openfile->current_x = step_left(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_left(openfile->current->data, openfile->current_x);
|
||||
#endif
|
||||
} else if (openfile->current != openfile->filetop) {
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->current = get_prev_visible_line(openfile->current);
|
||||
openfile->current_x = strlen(openfile->current->data);
|
||||
}
|
||||
|
||||
@@ -614,19 +747,82 @@ void do_right(void)
|
||||
{
|
||||
linestruct *was_current = openfile->current;
|
||||
|
||||
if (openfile->current->data[openfile->current_x] != '\0') {
|
||||
openfile->current_x = step_right(openfile->current->data,
|
||||
openfile->current_x);
|
||||
#ifdef ENABLE_FOLDING
|
||||
if (openfile->current->folded) {
|
||||
openfile->current = get_next_visible_line(openfile->current);
|
||||
if (openfile->current == NULL)
|
||||
openfile->current = was_current;
|
||||
} else
|
||||
#endif
|
||||
if (openfile->current->data[openfile->current_x]) {
|
||||
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
|
||||
#ifdef ENABLE_UTF8
|
||||
while (openfile->current->data[openfile->current_x] != '\0' &&
|
||||
while (openfile->current->data[openfile->current_x] &&
|
||||
is_zerowidth(openfile->current->data + openfile->current_x))
|
||||
openfile->current_x = step_right(openfile->current->data,
|
||||
openfile->current_x);
|
||||
openfile->current_x = step_right(openfile->current->data, openfile->current_x);
|
||||
#endif
|
||||
} else if (openfile->current != openfile->filebot) {
|
||||
openfile->current = openfile->current->next;
|
||||
openfile->current = get_next_visible_line(openfile->current);
|
||||
openfile->current_x = 0;
|
||||
}
|
||||
|
||||
edit_redraw(was_current, FLOWING);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Scroll the viewport horizontally to the left. */
|
||||
void do_scroll_left(void)
|
||||
{
|
||||
size_t frame_x;
|
||||
|
||||
if (ISSET(SOFTWRAP) || ISSET(SOLO_SIDESCROLL)) {
|
||||
/* TRANSLATORS: The %s is the name of an option. */
|
||||
statusline(AHEM, _("Not possible with '%s'"), ISSET(SOFTWRAP) ? "--softwrap" : "--solo");
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->brink -= (openfile->brink < tabsize) ? openfile->brink : (tabsize < 2) ? 2 : tabsize;
|
||||
|
||||
frame_x = actual_x(openfile->current->data, openfile->brink + editwincols - CUSHION - 1);
|
||||
|
||||
if (openfile->current_x > frame_x) {
|
||||
openfile->current_x = frame_x;
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
|
||||
/* Scroll the viewport horizontally to the right. */
|
||||
void do_scroll_right(void)
|
||||
{
|
||||
size_t sill = openfile->edittop->lineno + editwinrows;
|
||||
linestruct *line = openfile->current;
|
||||
size_t frame_x;
|
||||
|
||||
if (ISSET(SOFTWRAP) || ISSET(SOLO_SIDESCROLL)) {
|
||||
statusline(AHEM, _("Not possible with '%s'"), ISSET(SOFTWRAP) ? "--softwrap" : "--solo");
|
||||
return;
|
||||
}
|
||||
|
||||
openfile->brink += (tabsize < 2) ? 2 : tabsize;
|
||||
|
||||
/* If the current line does not allow further scrolling, seek
|
||||
* in the viewport an earlier or later line that does allow it. */
|
||||
while (line != openfile->edittop && breadth(line->data) < openfile->brink + CUSHION)
|
||||
line = line->prev;
|
||||
while (line->lineno < sill && breadth(line->data) < openfile->brink + CUSHION && line->next)
|
||||
line = line->next;
|
||||
if (line->lineno < sill && breadth(line->data) >= openfile->brink + CUSHION)
|
||||
openfile->current = line;
|
||||
|
||||
frame_x = actual_x(openfile->current->data, openfile->brink + CUSHION);
|
||||
|
||||
if (openfile->current_x < frame_x) {
|
||||
openfile->current_x = frame_x;
|
||||
openfile->placewewant = xplustabs();
|
||||
}
|
||||
|
||||
refresh_needed = TRUE;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
762
src/nano.c
762
src/nano.c
File diff suppressed because it is too large
Load Diff
633
src/prompt.c
633
src/prompt.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* prompt.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2018, 2020 Benno Schulenberg *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2018, 2020-2022, 2025 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -41,6 +41,33 @@ void do_statusbar_end(void)
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Move to the previous word in the answer. */
|
||||
void do_statusbar_prev_word(void)
|
||||
{
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (typing_x != 0) {
|
||||
typing_x = step_left(answer, typing_x);
|
||||
|
||||
if (is_word_char(answer + typing_x, FALSE))
|
||||
seen_a_word = TRUE;
|
||||
#ifdef ENABLE_UTF8
|
||||
else if (is_zerowidth(answer + typing_x))
|
||||
; /* skip */
|
||||
#endif
|
||||
else if (seen_a_word) {
|
||||
/* This is space now: we've overshot the start of the word. */
|
||||
step_forward = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (step_forward)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
typing_x = step_right(answer, typing_x);
|
||||
}
|
||||
|
||||
/* Move to the next word in the answer. */
|
||||
void do_statusbar_next_word(void)
|
||||
{
|
||||
@@ -49,7 +76,7 @@ void do_statusbar_next_word(void)
|
||||
|
||||
/* Move forward until we reach either the end or the start of a word,
|
||||
* depending on whether the AFTER_ENDS flag is set or not. */
|
||||
while (answer[typing_x] != '\0') {
|
||||
while (answer[typing_x]) {
|
||||
typing_x = step_right(answer, typing_x);
|
||||
|
||||
if (ISSET(AFTER_ENDS)) {
|
||||
@@ -78,33 +105,6 @@ void do_statusbar_next_word(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to the previous word in the answer. */
|
||||
void do_statusbar_prev_word(void)
|
||||
{
|
||||
bool seen_a_word = FALSE, step_forward = FALSE;
|
||||
|
||||
/* Move backward until we pass over the start of a word. */
|
||||
while (typing_x != 0) {
|
||||
typing_x = step_left(answer, typing_x);
|
||||
|
||||
if (is_word_char(answer + typing_x, FALSE))
|
||||
seen_a_word = TRUE;
|
||||
#ifdef ENABLE_UTF8
|
||||
else if (is_zerowidth(answer + typing_x))
|
||||
; /* skip */
|
||||
#endif
|
||||
else if (seen_a_word) {
|
||||
/* This is space now: we've overshot the start of the word. */
|
||||
step_forward = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (step_forward)
|
||||
/* Move one character forward again to sit on the start of the word. */
|
||||
typing_x = step_right(answer, typing_x);
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Move left one character in the answer. */
|
||||
@@ -122,30 +122,15 @@ void do_statusbar_left(void)
|
||||
/* Move right one character in the answer. */
|
||||
void do_statusbar_right(void)
|
||||
{
|
||||
if (answer[typing_x] != '\0') {
|
||||
if (answer[typing_x]) {
|
||||
typing_x = step_right(answer, typing_x);
|
||||
#ifdef ENABLE_UTF8
|
||||
while (answer[typing_x] != '\0' && is_zerowidth(answer + typing_x))
|
||||
while (answer[typing_x] && is_zerowidth(answer + typing_x))
|
||||
typing_x = step_right(answer, typing_x);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete one character in the answer. */
|
||||
void do_statusbar_delete(void)
|
||||
{
|
||||
if (answer[typing_x] != '\0') {
|
||||
int charlen = char_length(answer + typing_x);
|
||||
|
||||
memmove(answer + typing_x, answer + typing_x + charlen,
|
||||
strlen(answer) - typing_x - charlen + 1);
|
||||
#ifdef ENABLE_UTF8
|
||||
if (is_zerowidth(answer + typing_x))
|
||||
do_statusbar_delete();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Backspace over one character in the answer. */
|
||||
void do_statusbar_backspace(void)
|
||||
{
|
||||
@@ -157,48 +142,71 @@ void do_statusbar_backspace(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Zap some or all text from the answer. */
|
||||
void do_statusbar_cut_text(void)
|
||||
/* Delete one character in the answer. */
|
||||
void do_statusbar_delete(void)
|
||||
{
|
||||
if (!ISSET(CUT_FROM_CURSOR))
|
||||
if (answer[typing_x]) {
|
||||
int charlen = char_length(answer + typing_x);
|
||||
|
||||
memmove(answer + typing_x, answer + typing_x + charlen,
|
||||
strlen(answer) - typing_x - charlen + 1);
|
||||
#ifdef ENABLE_UTF8
|
||||
if (is_zerowidth(answer + typing_x))
|
||||
do_statusbar_delete();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Zap the part of the answer after the cursor, or the whole answer. */
|
||||
void lop_the_answer(void)
|
||||
{
|
||||
if (answer[typing_x] == '\0')
|
||||
typing_x = 0;
|
||||
|
||||
answer[typing_x] = '\0';
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Copy the current answer (if any) into the cutbuffer. */
|
||||
void copy_the_answer(void)
|
||||
{
|
||||
if (*answer) {
|
||||
free_lines(cutbuffer);
|
||||
cutbuffer = make_new_node(NULL);
|
||||
cutbuffer->data = copy_of(answer);
|
||||
typing_x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Paste the first line of the cutbuffer into the current answer. */
|
||||
void paste_into_answer(void)
|
||||
{
|
||||
size_t pastelen = strlen(cutbuffer->data);
|
||||
char *fusion = nmalloc(strlen(answer) + pastelen + 1);
|
||||
|
||||
/* Concatenate: the current answer before the cursor, the first line
|
||||
* of the cutbuffer, plus the rest of the current answer. */
|
||||
strncpy(fusion, answer, typing_x);
|
||||
strncpy(fusion + typing_x, cutbuffer->data, pastelen);
|
||||
strcpy(fusion + typing_x + pastelen, answer + typing_x);
|
||||
answer = nrealloc(answer, strlen(answer) + pastelen + 1);
|
||||
memmove(answer + typing_x + pastelen, answer + typing_x, strlen(answer) - typing_x + 1);
|
||||
strncpy(answer + typing_x, cutbuffer->data, pastelen);
|
||||
|
||||
free(answer);
|
||||
answer = fusion;
|
||||
typing_x += pastelen;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
/* Handle a mouse click on the status-bar prompt or the shortcut list. */
|
||||
int do_statusbar_mouse(void)
|
||||
/* Handle a mouse click in the prompt bar or the help lines. */
|
||||
int process_prompt_click(void)
|
||||
{
|
||||
int click_row, click_col;
|
||||
int retval = get_mouseinput(&click_row, &click_col, TRUE);
|
||||
int retval = get_mouseinput(&click_row, &click_col); /* Handles shortcuts. */
|
||||
|
||||
/* We can click on the status-bar window text to move the cursor. */
|
||||
if (retval == 0 && wmouse_trafo(bottomwin, &click_row, &click_col, FALSE)) {
|
||||
/* When the click is in the prompt bar, position the cursor. */
|
||||
if (retval == 0 && wmouse_trafo(footwin, &click_row, &click_col, FALSE)) {
|
||||
size_t start_col = breadth(prompt) + 2;
|
||||
|
||||
/* Move to where the click occurred. */
|
||||
if (click_row == 0 && click_col >= start_col)
|
||||
typing_x = actual_x(answer,
|
||||
get_statusbar_page_start(start_col, start_col +
|
||||
wideness(answer, typing_x)) + click_col - start_col);
|
||||
if (click_col >= start_col)
|
||||
typing_x = actual_x(answer, get_statusbar_page_start(start_col, start_col +
|
||||
wideness(answer, typing_x)) + click_col - start_col);
|
||||
else
|
||||
typing_x = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@@ -214,9 +222,8 @@ void inject_into_answer(char *burst, size_t count)
|
||||
burst[index] = '\n';
|
||||
|
||||
answer = nrealloc(answer, strlen(answer) + count + 1);
|
||||
memmove(answer + typing_x + count, answer + typing_x,
|
||||
strlen(answer) - typing_x + 1);
|
||||
strncpy(answer + typing_x, burst , count);
|
||||
memmove(answer + typing_x + count, answer + typing_x, strlen(answer) - typing_x + 1);
|
||||
strncpy(answer + typing_x, burst, count);
|
||||
|
||||
typing_x += count;
|
||||
}
|
||||
@@ -227,7 +234,7 @@ void do_statusbar_verbatim_input(void)
|
||||
size_t count = 1;
|
||||
char *bytes;
|
||||
|
||||
bytes = get_verbatim_kbinput(bottomwin, &count);
|
||||
bytes = get_verbatim_kbinput(footwin, &count);
|
||||
|
||||
if (0 < count && count < 999)
|
||||
inject_into_answer(bytes, count);
|
||||
@@ -237,127 +244,90 @@ void do_statusbar_verbatim_input(void)
|
||||
free(bytes);
|
||||
}
|
||||
|
||||
/* Read in a keystroke, interpret it if it is a shortcut or toggle, and
|
||||
* return it. Set finished to TRUE if we're done after running
|
||||
* or trying to run a function associated with a shortcut key. */
|
||||
int do_statusbar_input(bool *finished)
|
||||
/* Add the given input to the input buffer when it's a normal byte,
|
||||
* and inject the gathered bytes into the answer when ready. */
|
||||
void absorb_character(int input, functionptrtype function)
|
||||
{
|
||||
int input;
|
||||
/* The character we read in. */
|
||||
static char *puddle = NULL;
|
||||
/* The input buffer. */
|
||||
static size_t capacity = 8;
|
||||
/* The size of the input buffer; gets doubled whenever needed. */
|
||||
static size_t depth = 0;
|
||||
/* The length of the input buffer. */
|
||||
const keystruct *shortcut;
|
||||
|
||||
*finished = FALSE;
|
||||
|
||||
/* Read in a character. */
|
||||
input = get_kbinput(bottomwin, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (input == KEY_WINCH)
|
||||
return KEY_WINCH;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MOUSE
|
||||
/* If we got a mouse click and it was on a shortcut, read in the
|
||||
* shortcut character. */
|
||||
if (input == KEY_MOUSE) {
|
||||
if (do_statusbar_mouse() == 1)
|
||||
input = get_kbinput(bottomwin, BLIND);
|
||||
else
|
||||
return ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for a shortcut in the current list. */
|
||||
shortcut = get_shortcut(&input);
|
||||
|
||||
/* If not a command, discard anything that is not a normal character byte.
|
||||
* Apart from that, only accept input when not in restricted mode, or when
|
||||
* not at the "Write File" prompt, or when there is no filename yet. */
|
||||
if (shortcut == NULL) {
|
||||
if (input < 0x20 || input > 0xFF || meta_key)
|
||||
if (!function) {
|
||||
if ((input < 0x20 && input != '\t') || meta_key || input > 0xFF)
|
||||
beep();
|
||||
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
|
||||
openfile->filename[0] == '\0') {
|
||||
puddle = nrealloc(puddle, depth + 2);
|
||||
else if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE || openfile->filename[0] == '\0') {
|
||||
/* When the input buffer (plus room for terminating NUL) is full,
|
||||
* extend it; otherwise, if it does not exist yet, create it. */
|
||||
if (depth + 1 == capacity) {
|
||||
capacity = 2 * capacity;
|
||||
puddle = nrealloc(puddle, capacity);
|
||||
} else if (!puddle)
|
||||
puddle = nmalloc(capacity);
|
||||
|
||||
puddle[depth++] = (char)input;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we got a shortcut, or if there aren't any other keystrokes waiting,
|
||||
* it's time to insert all characters in the input buffer (if not empty)
|
||||
* into the answer, and then clear the input buffer. */
|
||||
if ((shortcut || get_key_buffer_len() == 0) && puddle != NULL) {
|
||||
/* If there are gathered bytes and we have a command or no other key codes
|
||||
* are waiting, it's time to insert these bytes into the answer. */
|
||||
if (depth > 0 && (function || waiting_keycodes() == 0)) {
|
||||
puddle[depth] = '\0';
|
||||
|
||||
inject_into_answer(puddle, depth);
|
||||
|
||||
free(puddle);
|
||||
puddle = NULL;
|
||||
depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (shortcut) {
|
||||
if (shortcut->func == do_tab || shortcut->func == do_enter)
|
||||
;
|
||||
#ifdef ENABLE_HISTORIES
|
||||
else if (shortcut->func == get_older_item ||
|
||||
shortcut->func == get_newer_item)
|
||||
;
|
||||
#endif
|
||||
else if (shortcut->func == do_left)
|
||||
do_statusbar_left();
|
||||
else if (shortcut->func == do_right)
|
||||
do_statusbar_right();
|
||||
/* Handle any editing shortcut, and return TRUE when handled. */
|
||||
bool handle_editing(functionptrtype function)
|
||||
{
|
||||
if (function == do_left)
|
||||
do_statusbar_left();
|
||||
else if (function == do_right)
|
||||
do_statusbar_right();
|
||||
#ifndef NANO_TINY
|
||||
else if (shortcut->func == to_prev_word)
|
||||
do_statusbar_prev_word();
|
||||
else if (shortcut->func == to_next_word)
|
||||
do_statusbar_next_word();
|
||||
else if (function == to_prev_word)
|
||||
do_statusbar_prev_word();
|
||||
else if (function == to_next_word)
|
||||
do_statusbar_next_word();
|
||||
#endif
|
||||
else if (shortcut->func == do_home)
|
||||
do_statusbar_home();
|
||||
else if (shortcut->func == do_end)
|
||||
do_statusbar_end();
|
||||
/* When in restricted mode at the "Write File" prompt and the
|
||||
* filename isn't blank, disallow any input and deletion. */
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE &&
|
||||
openfile->filename[0] != '\0' &&
|
||||
(shortcut->func == do_verbatim_input ||
|
||||
shortcut->func == cut_text ||
|
||||
shortcut->func == paste_text ||
|
||||
shortcut->func == do_delete ||
|
||||
shortcut->func == do_backspace))
|
||||
;
|
||||
#ifdef ENABLE_NANORC
|
||||
else if (shortcut->func == (functionptrtype)implant)
|
||||
implant(shortcut->expansion);
|
||||
#endif
|
||||
else if (shortcut->func == do_verbatim_input)
|
||||
do_statusbar_verbatim_input();
|
||||
else if (shortcut->func == cut_text)
|
||||
do_statusbar_cut_text();
|
||||
else if (shortcut->func == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (shortcut->func == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else if (shortcut->func == paste_text) {
|
||||
if (cutbuffer != NULL)
|
||||
paste_into_answer();
|
||||
} else {
|
||||
/* Handle any other shortcut in the current menu, setting finished
|
||||
* to TRUE to indicate that we're done after running or trying to
|
||||
* run its associated function. */
|
||||
if (!ISSET(VIEW_MODE) || okay_for_view(shortcut))
|
||||
shortcut->func();
|
||||
*finished = TRUE;
|
||||
}
|
||||
else if (function == do_home)
|
||||
do_statusbar_home();
|
||||
else if (function == do_end)
|
||||
do_statusbar_end();
|
||||
/* When in restricted mode at the "Write File" prompt and the
|
||||
* filename isn't blank, disallow any input and deletion. */
|
||||
else if (ISSET(RESTRICTED) && currmenu == MWRITEFILE && openfile->filename[0] &&
|
||||
(function == do_verbatim_input ||
|
||||
function == do_delete || function == do_backspace ||
|
||||
function == cut_text || function == paste_text))
|
||||
;
|
||||
else if (function == do_verbatim_input)
|
||||
do_statusbar_verbatim_input();
|
||||
else if (function == do_delete)
|
||||
do_statusbar_delete();
|
||||
else if (function == do_backspace)
|
||||
do_statusbar_backspace();
|
||||
else if (function == cut_text)
|
||||
lop_the_answer();
|
||||
#ifndef NANO_TINY
|
||||
else if (function == copy_text)
|
||||
copy_the_answer();
|
||||
else if (function == paste_text) {
|
||||
if (cutbuffer)
|
||||
paste_into_answer();
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
return input;
|
||||
/* Don't handle any handled function again. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return the column number of the first character of the answer that is
|
||||
@@ -392,47 +362,48 @@ void draw_the_promptbar(void)
|
||||
end_page = get_statusbar_page_start(base, base + breadth(answer) - 1);
|
||||
|
||||
/* Color the prompt bar over its full width. */
|
||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
||||
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||
|
||||
mvwaddstr(bottomwin, 0, 0, prompt);
|
||||
waddch(bottomwin, ':');
|
||||
waddch(bottomwin, (the_page == 0) ? ' ' : '<');
|
||||
mvwaddstr(footwin, 0, 0, prompt);
|
||||
waddch(footwin, ':');
|
||||
waddch(footwin, (the_page == 0) ? ' ' : '<');
|
||||
|
||||
expanded = display_string(answer, the_page, COLS - base, FALSE, TRUE);
|
||||
waddstr(bottomwin, expanded);
|
||||
waddstr(footwin, expanded);
|
||||
free(expanded);
|
||||
|
||||
if (the_page < end_page && base + breadth(answer) - the_page > COLS)
|
||||
mvwaddch(bottomwin, 0, COLS - 1, '>');
|
||||
mvwaddch(footwin, 0, COLS - 1, '>');
|
||||
|
||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
|
||||
#if defined(NCURSES_VERSION_PATCH) && (NCURSES_VERSION_PATCH < 20210220)
|
||||
/* Work around a cursor-misplacement bug -- https://sv.gnu.org/bugs/?59808. */
|
||||
if (ISSET(NO_HELP)) {
|
||||
wmove(bottomwin, 0, 0);
|
||||
wrefresh(bottomwin);
|
||||
wmove(footwin, 0, 0);
|
||||
wrefresh(footwin);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Place the cursor at the right spot. */
|
||||
wmove(bottomwin, 0, column - the_page);
|
||||
wnoutrefresh(bottomwin);
|
||||
wmove(footwin, 0, column - the_page);
|
||||
|
||||
wnoutrefresh(footwin);
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Remove or add the pipe character at the answer's head. */
|
||||
void add_or_remove_pipe_symbol_from_answer(void)
|
||||
{
|
||||
if (answer[0] == '|') {
|
||||
if (*answer == '|') {
|
||||
memmove(answer, answer + 1, strlen(answer));
|
||||
if (typing_x > 0)
|
||||
typing_x--;
|
||||
} else {
|
||||
answer = nrealloc(answer, strlen(answer) + 2);
|
||||
memmove(answer + 1, answer, strlen(answer) + 1);
|
||||
answer[0] = '|';
|
||||
*answer = '|';
|
||||
typing_x++;
|
||||
}
|
||||
}
|
||||
@@ -442,9 +413,6 @@ void add_or_remove_pipe_symbol_from_answer(void)
|
||||
functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
linestruct **history_list, void (*refresh_func)(void))
|
||||
{
|
||||
int kbinput = ERR;
|
||||
bool finished;
|
||||
functionptrtype func;
|
||||
#ifdef ENABLE_HISTORIES
|
||||
char *stored_string = NULL;
|
||||
/* Whatever the answer was before the user foraged into history. */
|
||||
@@ -454,7 +422,13 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
size_t fragment_length = 0;
|
||||
/* The length of the fragment that the user tries to tab complete. */
|
||||
#endif
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
bool bracketed_paste = FALSE;
|
||||
#endif
|
||||
const keystruct *shortcut;
|
||||
functionptrtype function;
|
||||
int input;
|
||||
|
||||
if (typing_x > strlen(answer))
|
||||
typing_x = strlen(answer);
|
||||
@@ -462,35 +436,61 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
while (TRUE) {
|
||||
draw_the_promptbar();
|
||||
|
||||
kbinput = do_statusbar_input(&finished);
|
||||
/* Read in one keystroke. */
|
||||
input = get_kbinput(footwin, VISIBLE);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* If the window size changed, go reformat the prompt string. */
|
||||
if (kbinput == KEY_WINCH) {
|
||||
refresh_func();
|
||||
*actual = KEY_WINCH;
|
||||
if (input == THE_WINDOW_RESIZED) {
|
||||
*actual = THE_WINDOW_RESIZED;
|
||||
#ifdef ENABLE_HISTORIES
|
||||
free(stored_string);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
if (input == START_OF_PASTE || input == END_OF_PASTE)
|
||||
bracketed_paste = (input == START_OF_PASTE);
|
||||
#endif
|
||||
#ifdef ENABLE_MOUSE
|
||||
/* For a click on a shortcut, read in the resulting keycode. */
|
||||
if (input == KEY_MOUSE && process_prompt_click() == 1)
|
||||
input = get_kbinput(footwin, BLIND);
|
||||
if (input == KEY_MOUSE)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
func = func_from_key(&kbinput);
|
||||
/* Check for a shortcut in the current list. */
|
||||
shortcut = get_shortcut(input);
|
||||
function = (shortcut ? shortcut->func : NULL);
|
||||
#ifndef NANO_TINY
|
||||
/* Tabs in an external paste are not commands. */
|
||||
if (input == '\t' && bracketed_paste)
|
||||
function = NULL;
|
||||
#endif
|
||||
/* When it's a normal character, add it to the answer. */
|
||||
absorb_character(input, function);
|
||||
|
||||
if (func == do_cancel || func == do_enter)
|
||||
#ifndef NANO_TINY
|
||||
/* Ignore any commands inside an external paste. */
|
||||
if (bracketed_paste) {
|
||||
if (function && function != do_nothing)
|
||||
beep();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (function == do_cancel || function == do_enter)
|
||||
break;
|
||||
|
||||
#ifdef ENABLE_TABCOMP
|
||||
if (func == do_tab) {
|
||||
if (function == do_tab) {
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (history_list != NULL) {
|
||||
if (history_list) {
|
||||
if (!previous_was_tab)
|
||||
fragment_length = strlen(answer);
|
||||
|
||||
if (fragment_length > 0) {
|
||||
answer = get_history_completion(history_list,
|
||||
answer, fragment_length);
|
||||
answer = get_history_completion(history_list, answer, fragment_length);
|
||||
typing_x = strlen(answer);
|
||||
}
|
||||
} else
|
||||
@@ -499,9 +499,9 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
if ((currmenu & (MINSERTFILE|MWRITEFILE|MGOTODIR)) && !ISSET(RESTRICTED))
|
||||
answer = input_tab(answer, &typing_x, refresh_func, listed);
|
||||
} else
|
||||
#endif /* ENABLE_TABCOMP */
|
||||
#endif
|
||||
#ifdef ENABLE_HISTORIES
|
||||
if (func == get_older_item && history_list != NULL) {
|
||||
if (function == get_older_item && history_list) {
|
||||
/* If this is the first step into history, start at the bottom. */
|
||||
if (stored_string == NULL)
|
||||
reset_history_pointer_for(*history_list);
|
||||
@@ -511,14 +511,14 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
stored_string = mallocstrcpy(stored_string, answer);
|
||||
|
||||
/* If there is an older item, move to it and copy its string. */
|
||||
if ((*history_list)->prev != NULL) {
|
||||
if ((*history_list)->prev) {
|
||||
*history_list = (*history_list)->prev;
|
||||
answer = mallocstrcpy(answer, (*history_list)->data);
|
||||
typing_x = strlen(answer);
|
||||
}
|
||||
} else if (func == get_newer_item && history_list != NULL) {
|
||||
} else if (function == get_newer_item && history_list) {
|
||||
/* If there is a newer item, move to it and copy its string. */
|
||||
if ((*history_list)->next != NULL) {
|
||||
if ((*history_list)->next) {
|
||||
*history_list = (*history_list)->next;
|
||||
answer = mallocstrcpy(answer, (*history_list)->data);
|
||||
typing_x = strlen(answer);
|
||||
@@ -531,43 +531,57 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
}
|
||||
} else
|
||||
#endif /* ENABLE_HISTORIES */
|
||||
/* If we ran a function that should not exit from the prompt... */
|
||||
if (func == do_help || func == full_refresh)
|
||||
finished = FALSE;
|
||||
if (function == do_help || function == full_refresh)
|
||||
function();
|
||||
#ifndef NANO_TINY
|
||||
else if (func == do_nothing)
|
||||
finished = FALSE;
|
||||
else if (func == do_toggle) {
|
||||
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
|
||||
TOGGLE(NO_HELP);
|
||||
window_init();
|
||||
focusing = FALSE;
|
||||
refresh_func();
|
||||
bottombars(currmenu);
|
||||
finished = FALSE;
|
||||
}
|
||||
} else if (function == do_nothing)
|
||||
;
|
||||
#endif
|
||||
|
||||
/* If we have a shortcut with an associated function, break out if
|
||||
* we're finished after running or trying to run the function. */
|
||||
if (finished)
|
||||
break;
|
||||
#ifdef ENABLE_NANORC
|
||||
else if (function == (functionptrtype)implant)
|
||||
implant(shortcut->expansion);
|
||||
#endif
|
||||
else if (function && !handle_editing(function)) {
|
||||
/* When it's a permissible shortcut, run it and done. */
|
||||
if (!ISSET(VIEW_MODE) || !changes_something(function)) {
|
||||
#ifndef NANO_TINY
|
||||
/* When invoking a tool at the Execute prompt, stash an "answer". */
|
||||
if (currmenu == MEXECUTE)
|
||||
foretext = mallocstrcpy(foretext, answer);
|
||||
#endif
|
||||
function();
|
||||
break;
|
||||
} else
|
||||
beep();
|
||||
}
|
||||
|
||||
#if defined(ENABLE_HISTORIES) && defined(ENABLE_TABCOMP)
|
||||
previous_was_tab = (func == do_tab);
|
||||
previous_was_tab = (function == do_tab);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* When an external command was run, clear a possibly stashed answer. */
|
||||
if (currmenu == MEXECUTE && function == do_enter)
|
||||
*foretext = '\0';
|
||||
#endif
|
||||
#ifdef ENABLE_HISTORIES
|
||||
/* If the history pointer was moved, point it at the bottom again. */
|
||||
if (stored_string != NULL) {
|
||||
if (stored_string) {
|
||||
reset_history_pointer_for(*history_list);
|
||||
free(stored_string);
|
||||
}
|
||||
#endif
|
||||
|
||||
*actual = kbinput;
|
||||
*actual = input;
|
||||
|
||||
return func;
|
||||
return function;
|
||||
}
|
||||
|
||||
/* Ask a question on the status bar. Return 0 when text was entered,
|
||||
@@ -577,10 +591,10 @@ functionptrtype acquire_an_answer(int *actual, bool *listed,
|
||||
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...)
|
||||
{
|
||||
functionptrtype function = NULL;
|
||||
bool listed = FALSE;
|
||||
va_list ap;
|
||||
int retval;
|
||||
functionptrtype func = NULL;
|
||||
bool listed = FALSE;
|
||||
/* Save a possible current status-bar x position and prompt. */
|
||||
size_t was_typing_x = typing_x;
|
||||
char *saved_prompt = prompt;
|
||||
@@ -602,25 +616,27 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
|
||||
lastmessage = VACUUM;
|
||||
|
||||
func = acquire_an_answer(&retval, &listed, history_list, refresh_func);
|
||||
function = acquire_an_answer(&retval, &listed, history_list, refresh_func);
|
||||
free(prompt);
|
||||
prompt = saved_prompt;
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (retval == KEY_WINCH)
|
||||
if (retval == THE_WINDOW_RESIZED)
|
||||
goto redo_theprompt;
|
||||
#endif
|
||||
|
||||
/* If we're done with this prompt, restore the x position to what
|
||||
* it was at a possible previous prompt. */
|
||||
if (func == do_cancel || func == do_enter)
|
||||
/* Restore a possible previous prompt and maybe the typing position. */
|
||||
prompt = saved_prompt;
|
||||
if (function == do_cancel || function == do_enter ||
|
||||
#ifdef ENABLE_BROWSER
|
||||
function == to_first_file || function == to_last_file ||
|
||||
#endif
|
||||
function == to_first_line || function == to_last_line)
|
||||
typing_x = was_typing_x;
|
||||
|
||||
/* If we left the prompt via Cancel or Enter, set the return value
|
||||
* properly. */
|
||||
if (func == do_cancel)
|
||||
/* Set the proper return value for Cancel and Enter. */
|
||||
if (function == do_cancel)
|
||||
retval = -1;
|
||||
else if (func == do_enter)
|
||||
else if (function == do_enter)
|
||||
retval = (*answer == '\0') ? -2 : 0;
|
||||
|
||||
if (lastmessage == VACUUM)
|
||||
@@ -635,20 +651,24 @@ int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
|
||||
* on the status bar. Return 1 for Yes, 0 for No, 2 for All (if all is
|
||||
* TRUE when passed in), and -1 for Cancel. */
|
||||
int do_yesno_prompt(bool all, const char *msg)
|
||||
#define UNDECIDED -2
|
||||
|
||||
/* Ask a simple Yes/No (and optionally All) question on the status bar
|
||||
* and return the choice -- either YES or NO or ALL or CANCEL. */
|
||||
int ask_user(bool withall, const char *question)
|
||||
{
|
||||
int choice = -2, width = 16;
|
||||
int choice = UNDECIDED;
|
||||
int width = 16;
|
||||
/* TRANSLATORS: For the next three strings, specify the starting letters
|
||||
* of the translations for "Yes"/"No"/"All". The first letter of each of
|
||||
* these strings MUST be a single-byte letter; others may be multi-byte. */
|
||||
const char *yesstr = _("Yy");
|
||||
const char *nostr = _("Nn");
|
||||
const char *allstr = _("Aa");
|
||||
const keystruct *shortcut;
|
||||
functionptrtype function;
|
||||
|
||||
while (choice == -2) {
|
||||
while (choice == UNDECIDED) {
|
||||
#ifdef ENABLE_NLS
|
||||
char letter[MAXCHARLEN + 1];
|
||||
int index = 0;
|
||||
@@ -669,42 +689,45 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
|
||||
/* Now show the ones for "Yes", "No", "Cancel" and maybe "All". */
|
||||
sprintf(shortstr, " %c", yesstr[0]);
|
||||
wmove(bottomwin, 1, 0);
|
||||
wmove(footwin, 1, 0);
|
||||
post_one_key(shortstr, _("Yes"), width);
|
||||
|
||||
shortstr[1] = nostr[0];
|
||||
wmove(bottomwin, 2, 0);
|
||||
wmove(footwin, 2, 0);
|
||||
post_one_key(shortstr, _("No"), width);
|
||||
|
||||
if (all) {
|
||||
if (withall) {
|
||||
shortstr[1] = allstr[0];
|
||||
wmove(bottomwin, 1, width);
|
||||
wmove(footwin, 1, width);
|
||||
post_one_key(shortstr, _("All"), width);
|
||||
}
|
||||
|
||||
wmove(bottomwin, 2, width);
|
||||
wmove(footwin, 2, width);
|
||||
post_one_key(cancelshortcut->keystr, _("Cancel"), width);
|
||||
}
|
||||
|
||||
/* Color the prompt bar over its full width and display the question. */
|
||||
wattron(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(bottomwin, 0, 0, "%*s", COLS, " ");
|
||||
mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));
|
||||
wattroff(bottomwin, interface_color_pair[PROMPT_BAR]);
|
||||
wnoutrefresh(bottomwin);
|
||||
wattron(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
mvwprintw(footwin, 0, 0, "%*s", COLS, " ");
|
||||
mvwaddnstr(footwin, 0, 0, question, actual_x(question, COLS - 1));
|
||||
wattroff(footwin, interface_color_pair[PROMPT_BAR]);
|
||||
wnoutrefresh(footwin);
|
||||
|
||||
currmenu = MYESNO;
|
||||
|
||||
/* When not replacing, show the cursor while waiting for a key. */
|
||||
kbinput = get_kbinput(bottomwin, !all);
|
||||
kbinput = get_kbinput(footwin, !withall);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
if (kbinput == KEY_WINCH)
|
||||
if (kbinput == THE_WINDOW_RESIZED)
|
||||
continue;
|
||||
|
||||
/* Accept the first character of an external paste. */
|
||||
if (bracketed_paste && kbinput == BRACKETED_PASTE_MARKER)
|
||||
kbinput = get_kbinput(bottomwin, BLIND);
|
||||
/* Accept first character of an external paste and ignore the rest. */
|
||||
if (kbinput == START_OF_PASTE) {
|
||||
kbinput = get_kbinput(footwin, BLIND);
|
||||
while (get_kbinput(footwin, BLIND) != END_OF_PASTE)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_NLS
|
||||
@@ -712,60 +735,43 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
#ifdef ENABLE_UTF8
|
||||
/* If the received code is a UTF-8 starter byte, get also the
|
||||
* continuation bytes and assemble them into one letter. */
|
||||
if (using_utf8() && 0xC0 <= kbinput && kbinput <= 0xF7) {
|
||||
if (0xC0 <= kbinput && kbinput <= 0xF7 && using_utf8) {
|
||||
int extras = (kbinput / 16) % 4 + (kbinput <= 0xCF ? 1 : 0);
|
||||
|
||||
while (extras <= get_key_buffer_len() && extras-- > 0)
|
||||
letter[index++] = (unsigned char)get_kbinput(bottomwin, !all);
|
||||
while (extras <= waiting_keycodes() && extras-- > 0)
|
||||
letter[index++] = (unsigned char)get_kbinput(footwin, !withall);
|
||||
}
|
||||
#endif
|
||||
letter[index] = '\0';
|
||||
|
||||
/* See if the typed letter is in the Yes, No, or All strings. */
|
||||
if (strstr(yesstr, letter) != NULL)
|
||||
choice = 1;
|
||||
else if (strstr(nostr, letter) != NULL)
|
||||
choice = 0;
|
||||
else if (all && strstr(allstr, letter) != NULL)
|
||||
choice = 2;
|
||||
if (strstr(yesstr, letter))
|
||||
choice = YES;
|
||||
else if (strstr(nostr, letter))
|
||||
choice = NO;
|
||||
else if (withall && strstr(allstr, letter))
|
||||
choice = ALL;
|
||||
else
|
||||
#endif /* ENABLE_NLS */
|
||||
if (strchr("Yy", kbinput) != NULL)
|
||||
choice = 1;
|
||||
else if (strchr("Nn", kbinput) != NULL)
|
||||
choice = 0;
|
||||
else if (all && strchr("Aa", kbinput) != NULL)
|
||||
choice = 2;
|
||||
else if (func_from_key(&kbinput) == do_cancel)
|
||||
choice = -1;
|
||||
/* Interpret ^N and ^Q as "No", to allow exiting in anger. */
|
||||
else if (kbinput == '\x0E' || kbinput == '\x11')
|
||||
choice = 0;
|
||||
/* And interpret ^Y as "Yes". */
|
||||
else if (kbinput == '\x19')
|
||||
choice = 1;
|
||||
#ifdef ENABLE_MOUSE
|
||||
else if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
||||
if (get_mouseinput(&mouse_y, &mouse_x, FALSE) == 0 &&
|
||||
wmouse_trafo(bottomwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
mouse_x < (width * 2) && mouse_y > 0) {
|
||||
int x = mouse_x / width;
|
||||
int y = mouse_y - 1;
|
||||
if (strchr("Yy", kbinput))
|
||||
choice = YES;
|
||||
else if (strchr("Nn", kbinput))
|
||||
choice = NO;
|
||||
else if (withall && strchr("Aa", kbinput))
|
||||
choice = ALL;
|
||||
|
||||
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
||||
choice = -2 * x * y + x - y + 1;
|
||||
if (choice != UNDECIDED)
|
||||
break;
|
||||
|
||||
if (choice == 2 && !all)
|
||||
choice = -2;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (func_from_key(&kbinput) == full_refresh)
|
||||
shortcut = get_shortcut(kbinput);
|
||||
function = (shortcut ? shortcut->func : NULL);
|
||||
|
||||
if (function == do_cancel)
|
||||
choice = CANCEL;
|
||||
else if (function == full_refresh)
|
||||
full_refresh();
|
||||
#ifndef NANO_TINY
|
||||
else if (func_from_key(&kbinput) == do_toggle) {
|
||||
else if (function == do_toggle && shortcut->toggle == NO_HELP) {
|
||||
TOGGLE(NO_HELP);
|
||||
window_init();
|
||||
titlebar(NULL);
|
||||
@@ -773,15 +779,38 @@ int do_yesno_prompt(bool all, const char *msg)
|
||||
edit_refresh();
|
||||
focusing = TRUE;
|
||||
}
|
||||
#endif
|
||||
/* Interpret ^N as "No", to allow exiting in anger, and ^Q or ^X too. */
|
||||
else if (kbinput == '\x0E' || (kbinput == '\x11' && !ISSET(MODERN_BINDINGS)) ||
|
||||
(kbinput == '\x18' && ISSET(MODERN_BINDINGS))) {
|
||||
choice = NO;
|
||||
if (kbinput != '\x0E') /* ^X^Q makes nano exit with an error. */
|
||||
final_status = 2;
|
||||
/* Also, interpret ^Y as "Yes, and ^A as "All". */
|
||||
} else if (kbinput == '\x19')
|
||||
choice = YES;
|
||||
else if (kbinput == '\x01' && withall)
|
||||
choice = ALL;
|
||||
#ifdef ENABLE_MOUSE
|
||||
else if (kbinput == KEY_MOUSE) {
|
||||
int mouse_x, mouse_y;
|
||||
/* We can click on the Yes/No/All shortcuts to select an answer. */
|
||||
if (get_mouseinput(&mouse_y, &mouse_x) == 0 &&
|
||||
wmouse_trafo(footwin, &mouse_y, &mouse_x, FALSE) &&
|
||||
mouse_x < (width * 2) && mouse_y > 0) {
|
||||
int x = mouse_x / width;
|
||||
int y = mouse_y - 1;
|
||||
|
||||
/* x == 0 means Yes or No, y == 0 means Yes or All. */
|
||||
choice = -2 * x * y + x - y + 1;
|
||||
|
||||
if (choice == ALL && !withall)
|
||||
choice = UNDECIDED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
beep();
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Ignore the rest of an external paste. */
|
||||
while (bracketed_paste)
|
||||
kbinput = get_kbinput(bottomwin, BLIND);
|
||||
#endif
|
||||
}
|
||||
|
||||
return choice;
|
||||
|
||||
140
src/prototypes.h
140
src/prototypes.h
@@ -1,7 +1,7 @@
|
||||
/**************************************************************************
|
||||
* prototypes.h -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -14,7 +14,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -24,24 +24,31 @@
|
||||
|
||||
#ifndef NANO_TINY
|
||||
extern volatile sig_atomic_t the_window_resized;
|
||||
extern volatile sig_atomic_t resized_for_browser;
|
||||
#endif
|
||||
|
||||
extern bool on_a_vt;
|
||||
extern bool using_utf8;
|
||||
extern bool shifted_metas;
|
||||
|
||||
extern bool meta_key;
|
||||
extern bool shift_held;
|
||||
extern bool mute_modifiers;
|
||||
extern bool bracketed_paste;
|
||||
|
||||
extern bool we_are_running;
|
||||
extern bool more_than_one;
|
||||
extern bool report_size;
|
||||
|
||||
extern bool ran_a_tool;
|
||||
extern char *foretext;
|
||||
|
||||
extern int final_status;
|
||||
|
||||
extern bool inhelp;
|
||||
extern char *title;
|
||||
|
||||
extern bool united_sidescroll;
|
||||
|
||||
extern bool focusing;
|
||||
|
||||
extern bool as_an_at;
|
||||
@@ -68,18 +75,19 @@ extern int controlup, controldown;
|
||||
extern int controlhome, controlend;
|
||||
#ifndef NANO_TINY
|
||||
extern int controldelete, controlshiftdelete;
|
||||
extern int shiftleft, shiftright;
|
||||
extern int shiftup, shiftdown;
|
||||
extern int shiftcontrolleft, shiftcontrolright;
|
||||
extern int shiftcontrolup, shiftcontroldown;
|
||||
extern int shiftcontrolhome, shiftcontrolend;
|
||||
extern int altleft, altright;
|
||||
extern int altup, altdown;
|
||||
extern int althome, altend;
|
||||
extern int altpageup, altpagedown;
|
||||
extern int altinsert, altdelete;
|
||||
extern int shiftaltleft, shiftaltright;
|
||||
extern int shiftaltup, shiftaltdown;
|
||||
#endif
|
||||
extern int mousefocusin, mousefocusout;
|
||||
|
||||
#ifdef ENABLED_WRAPORJUSTIFY
|
||||
extern ssize_t fill;
|
||||
@@ -87,15 +95,16 @@ extern size_t wrap_at;
|
||||
#endif
|
||||
|
||||
extern WINDOW *topwin;
|
||||
extern WINDOW *edit;
|
||||
extern WINDOW *bottomwin;
|
||||
extern WINDOW *midwin;
|
||||
extern WINDOW *footwin;
|
||||
extern int editwinrows;
|
||||
extern int editwincols;
|
||||
extern int margin;
|
||||
extern int thebar;
|
||||
extern int sidebar;
|
||||
#ifndef NANO_TINY
|
||||
extern int *bardata;
|
||||
extern ssize_t stripe_column;
|
||||
extern int cycling_aim;
|
||||
#endif
|
||||
|
||||
extern linestruct *cutbuffer;
|
||||
@@ -141,6 +150,9 @@ extern char *alt_speller;
|
||||
extern syntaxtype *syntaxes;
|
||||
extern char *syntaxstr;
|
||||
extern bool have_palette;
|
||||
extern bool rescind_colors;
|
||||
extern bool perturbed;
|
||||
extern bool recook;
|
||||
#endif
|
||||
|
||||
extern bool refresh_needed;
|
||||
@@ -178,6 +190,9 @@ extern char *startup_problem;
|
||||
#endif
|
||||
#ifdef ENABLE_NANORC
|
||||
extern char *custom_nanorc;
|
||||
|
||||
extern char *commandname;
|
||||
extern keystruct *planted_shortcut;
|
||||
#endif
|
||||
|
||||
extern bool spotlighted;
|
||||
@@ -195,10 +210,6 @@ void to_last_file(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in chars.c. */
|
||||
#ifdef ENABLE_UTF8
|
||||
void utf8_init(void);
|
||||
bool using_utf8(void);
|
||||
#endif
|
||||
bool is_alpha_char(const char *c);
|
||||
bool is_blank_char(const char *c);
|
||||
bool is_cntrl_char(const char *c);
|
||||
@@ -221,7 +232,7 @@ char *mbstrcasestr(const char *haystack, const char *needle);
|
||||
char *revstrstr(const char *haystack, const char *needle, const char *pointer);
|
||||
char *mbrevstrcasestr(const char *haystack, const char *needle, const char *pointer);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_JUSTIFY)
|
||||
char *mbstrchr(const char *string, const char *chr);
|
||||
const char *mbstrchr(const char *string, const char *chr);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
char *mbstrpbrk(const char *string, const char *accept);
|
||||
@@ -231,6 +242,9 @@ char *mbrevstrpbrk(const char *head, const char *accept, const char *pointer);
|
||||
bool has_blank_char(const char *string);
|
||||
#endif
|
||||
bool white_string(const char *string);
|
||||
#if defined(ENABLE_SPELLER) || defined(ENABLE_COLOR)
|
||||
void strip_leading_blanks_from(char *string);
|
||||
#endif
|
||||
|
||||
/* Most functions in color.c. */
|
||||
#ifdef ENABLE_COLOR
|
||||
@@ -242,6 +256,7 @@ void precalc_multicolorinfo(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in cut.c. */
|
||||
void expunge(undo_type action);
|
||||
void do_delete(void);
|
||||
void do_backspace(void);
|
||||
#ifndef NANO_TINY
|
||||
@@ -260,8 +275,8 @@ void cut_text(void);
|
||||
void cut_till_eof(void);
|
||||
void zap_text(void);
|
||||
void copy_marked_region(void);
|
||||
void copy_text(void);
|
||||
#endif
|
||||
void copy_text(void);
|
||||
void paste_text(void);
|
||||
|
||||
/* Most functions in files.c. */
|
||||
@@ -295,16 +310,14 @@ bool outside_of_confinement(const char *currpath, bool allow_tabcomp);
|
||||
void init_backup_dir(void);
|
||||
#endif
|
||||
int copy_file(FILE *inn, FILE *out, bool close_out);
|
||||
bool write_file(const char *name, FILE *thefile, bool normal,
|
||||
kind_of_writing_type method, bool annotate);
|
||||
bool write_file(const char *name, FILE *thefile, writing_type method, bool annotate);
|
||||
#ifndef NANO_TINY
|
||||
bool write_region_to_file(const char *name, FILE *stream, bool normal,
|
||||
kind_of_writing_type method);
|
||||
bool write_region_to_file(const char *name, FILE *stream, writing_type method);
|
||||
#endif
|
||||
int write_it_out(bool exiting, bool withprompt);
|
||||
void do_writeout(void);
|
||||
void do_savefile(void);
|
||||
char *real_dir_from_tilde(const char *path);
|
||||
char *expand_leading_tilde(const char *path);
|
||||
#if defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
int diralphasort(const void *va, const void *vb);
|
||||
#endif
|
||||
@@ -313,12 +326,12 @@ char *input_tab(char *buf, size_t *place, void (*refresh_func)(void), bool *list
|
||||
#endif
|
||||
|
||||
/* Some functions in global.c. */
|
||||
const keystruct *first_sc_for(int menu, void (*func)(void));
|
||||
const keystruct *first_sc_for(int menu, void (*function)(void));
|
||||
size_t shown_entries_for(int menu);
|
||||
const keystruct *get_shortcut(int *keycode);
|
||||
functionptrtype func_from_key(int *keycode);
|
||||
const keystruct *get_shortcut(const int keycode);
|
||||
functionptrtype func_from_key(const int keycode);
|
||||
#if defined(ENABLE_BROWSER) || defined(ENABLE_HELP)
|
||||
functionptrtype interpret(int *keycode);
|
||||
functionptrtype interpret(const int keycode);
|
||||
#endif
|
||||
int keycode_from_string(const char *keystring);
|
||||
void shortcut_init(void);
|
||||
@@ -341,9 +354,9 @@ char *get_history_completion(linestruct **h, char *s, size_t len);
|
||||
bool have_statedir(void);
|
||||
void load_history(void);
|
||||
void save_history(void);
|
||||
void load_poshistory(void);
|
||||
void update_poshistory(void);
|
||||
bool has_old_position(const char *file, ssize_t *line, ssize_t *column);
|
||||
void load_positions_register(void);
|
||||
void update_positions_register(void);
|
||||
void restore_cursor_position_if_any(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in move.c. */
|
||||
@@ -351,6 +364,12 @@ void to_first_line(void);
|
||||
void to_last_line(void);
|
||||
void do_page_up(void);
|
||||
void do_page_down(void);
|
||||
#ifndef NANO_TINY
|
||||
void to_top_row(void);
|
||||
void to_bottom_row(void);
|
||||
void do_cycle(void);
|
||||
void do_center(void);
|
||||
#endif
|
||||
#ifdef ENABLE_JUSTIFY
|
||||
void do_para_begin(linestruct **line);
|
||||
void do_para_end(linestruct **line);
|
||||
@@ -359,8 +378,8 @@ void to_para_end(void);
|
||||
#endif
|
||||
void to_prev_block(void);
|
||||
void to_next_block(void);
|
||||
void do_prev_word(void);
|
||||
bool do_next_word(bool after_ends);
|
||||
void do_prev_word(bool allow_folded);
|
||||
bool do_next_word(bool after_ends, bool allow_folded);
|
||||
void to_prev_word(void);
|
||||
void to_next_word(void);
|
||||
void do_home(void);
|
||||
@@ -370,10 +389,14 @@ void do_down(void);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||
void do_scroll_up(void);
|
||||
void do_scroll_down(void);
|
||||
void do_center(void);
|
||||
#endif
|
||||
void do_left(void);
|
||||
void do_right(void);
|
||||
void move_cursor_to_proper_column(void);
|
||||
#ifndef NANO_TINY
|
||||
void do_scroll_left(void);
|
||||
void do_scroll_right(void);
|
||||
#endif
|
||||
|
||||
/* Most functions in nano.c. */
|
||||
linestruct *make_new_node(linestruct *prevnode);
|
||||
@@ -421,7 +444,8 @@ void terminal_init(void);
|
||||
void confirm_margin(void);
|
||||
#endif
|
||||
void unbound_key(int code);
|
||||
bool okay_for_view(const keystruct *shortcut);
|
||||
bool changes_something(functionptrtype f);
|
||||
void suck_up_input_and_paste_it(void);
|
||||
void inject(char *burst, size_t count);
|
||||
|
||||
/* Most functions in prompt.c. */
|
||||
@@ -430,7 +454,7 @@ void put_cursor_at_end_of_answer(void);
|
||||
void add_or_remove_pipe_symbol_from_answer(void);
|
||||
int do_prompt(int menu, const char *provided, linestruct **history_list,
|
||||
void (*refresh_func)(void), const char *msg, ...);
|
||||
int do_yesno_prompt(bool all, const char *msg);
|
||||
int ask_user(bool withall, const char *question);
|
||||
|
||||
/* Most functions in rcfile.c. */
|
||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||
@@ -438,6 +462,7 @@ void display_rcfile_errors(void);
|
||||
void jot_error(const char *msg, ...);
|
||||
#endif
|
||||
#ifdef ENABLE_NANORC
|
||||
keystruct *strtosc(const char *input);
|
||||
#ifdef ENABLE_COLOR
|
||||
void parse_one_include(char *file, syntaxtype *syntax);
|
||||
void grab_and_store(const char *kind, char *ptr, regexlisttype **storage);
|
||||
@@ -462,11 +487,18 @@ ssize_t do_replace_loop(const char *needle, bool whole_word_only,
|
||||
const linestruct *real_current, size_t *real_current_x);
|
||||
void do_replace(void);
|
||||
void ask_for_and_do_replacements(void);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||
void goto_line_posx(ssize_t line, size_t pos_x);
|
||||
void goto_line_and_column(ssize_t line, ssize_t column, bool retain_answer,
|
||||
bool interactive);
|
||||
#endif
|
||||
void do_gotolinecolumn(void);
|
||||
void ask_for_line_and_column(char *provided);
|
||||
void goto_line_and_column(ssize_t line, ssize_t column, bool hugfloor);
|
||||
#ifndef NANO_TINY
|
||||
size_t get_matchbrackets_halfway(void);
|
||||
int find_matching_bracket_pos(linestruct **line, size_t *xpos);
|
||||
bool find_terminus_of_bracketed_region(linestruct **line, size_t *xpos, size_t bracket_half, bool reverse);
|
||||
bool find_bracketed_region(linestruct *in_region,
|
||||
linestruct **top, linestruct **bot);
|
||||
void do_find_bracket(void);
|
||||
void put_or_lift_anchor(void);
|
||||
void to_prev_anchor(void);
|
||||
@@ -513,15 +545,19 @@ void do_full_justify(void);
|
||||
#ifdef ENABLE_SPELLER
|
||||
void do_spell(void);
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
#ifdef ENABLE_LINTER
|
||||
void do_linter(void);
|
||||
#endif
|
||||
#ifdef ENABLE_FORMATTER
|
||||
void do_formatter(void);
|
||||
#endif
|
||||
#ifndef NANO_TINY
|
||||
void count_lines_words_and_characters(void);
|
||||
#endif
|
||||
void do_verbatim_input(void);
|
||||
#ifdef ENABLE_WORDCOMPLETION
|
||||
void complete_a_word(void);
|
||||
#endif
|
||||
|
||||
/* All functions in utils.c. */
|
||||
void get_homedir(void);
|
||||
@@ -531,7 +567,7 @@ int digits(ssize_t n);
|
||||
bool parse_num(const char *str, ssize_t *result);
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column);
|
||||
void recode_NUL_to_LF(char *string, size_t length);
|
||||
void recode_LF_to_NUL(char *string);
|
||||
size_t recode_LF_to_NUL(char *string);
|
||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
void free_chararray(char **array, size_t len);
|
||||
#endif
|
||||
@@ -542,15 +578,15 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
const char *start);
|
||||
void *nmalloc(size_t howmuch);
|
||||
void *nrealloc(void *ptr, size_t howmuch);
|
||||
char *measured_copy(const char *string, size_t count);
|
||||
char *mallocstrcpy(char *dest, const char *src);
|
||||
char *measured_copy(const char *string, size_t count);
|
||||
char *copy_of(const char *string);
|
||||
char *free_and_assign(char *dest, char *src);
|
||||
size_t get_page_start(size_t column);
|
||||
size_t xplustabs(void);
|
||||
size_t actual_x(const char *text, size_t column);
|
||||
size_t wideness(const char *text, size_t maxlen);
|
||||
size_t wideness(const char *text, size_t count);
|
||||
size_t breadth(const char *text);
|
||||
size_t xplustabs(void);
|
||||
void new_magicline(void);
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||
void remove_magicline(void);
|
||||
@@ -561,28 +597,33 @@ void get_region(linestruct **top, size_t *top_x, linestruct **bot, size_t *bot_x
|
||||
void get_range(linestruct **top, linestruct **bot);
|
||||
#endif
|
||||
size_t number_of_characters_in(const linestruct *begin, const linestruct *end);
|
||||
#ifndef NANO_TINY
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||
linestruct *line_from_number(ssize_t number);
|
||||
#endif
|
||||
|
||||
/* Most functions in winio.c. */
|
||||
linestruct *get_next_visible_line(linestruct *line);
|
||||
linestruct *get_prev_visible_line(linestruct *line);
|
||||
#ifndef NANO_TINY
|
||||
void record_macro(void);
|
||||
void run_macro(void);
|
||||
size_t get_key_buffer_len(void);
|
||||
#endif
|
||||
size_t waiting_keycodes(void);
|
||||
void put_back(int keycode);
|
||||
#ifdef ENABLE_NANORC
|
||||
void implant(const char *string);
|
||||
#endif
|
||||
int parse_kbinput(WINDOW *win);
|
||||
int get_input(WINDOW *win);
|
||||
int get_kbinput(WINDOW *win, bool showcursor);
|
||||
char *get_verbatim_kbinput(WINDOW *win, size_t *count);
|
||||
#ifdef ENABLE_MOUSE
|
||||
int get_mouseinput(int *mouse_y, int *mouse_x, bool allow_shortcuts);
|
||||
int get_mouseinput(int *mouse_y, int *mouse_x);
|
||||
#endif
|
||||
void blank_edit(void);
|
||||
void blank_statusbar(void);
|
||||
void wipe_statusbar(void);
|
||||
void blank_bottombars(void);
|
||||
void check_statusblank(void);
|
||||
void blank_it_when_expired(void);
|
||||
void set_blankdelay_to_one(void);
|
||||
char *display_string(const char *buf, size_t column, size_t span,
|
||||
bool isdata, bool isprompt);
|
||||
@@ -594,6 +635,7 @@ void warn_and_briefly_pause(const char *msg);
|
||||
void bottombars(int menu);
|
||||
void post_one_key(const char *keystroke, const char *tag, int width);
|
||||
void place_the_cursor(void);
|
||||
int update_line_at(linestruct *line, size_t index, int row);
|
||||
int update_line(linestruct *line, size_t index);
|
||||
#ifndef NANO_TINY
|
||||
int update_softwrapped_line(linestruct *line);
|
||||
@@ -604,8 +646,8 @@ int go_forward_chunks(int nrows, linestruct **line, size_t *leftedge);
|
||||
bool less_than_a_screenful(size_t was_lineno, size_t was_leftedge);
|
||||
void edit_scroll(bool direction);
|
||||
#ifndef NANO_TINY
|
||||
size_t get_softwrap_breakpoint(const char *text, size_t leftedge,
|
||||
bool *end_of_line);
|
||||
size_t get_softwrap_breakpoint(const char *linedata, size_t leftedge,
|
||||
bool *kickoff, bool *end_of_line);
|
||||
size_t get_chunk_and_edge(size_t column, linestruct *line, size_t *leftedge);
|
||||
size_t chunk_for(size_t column, linestruct *line);
|
||||
size_t leftedge_for(size_t column, linestruct *line);
|
||||
@@ -645,7 +687,6 @@ void goto_dir(void);
|
||||
void do_nothing(void);
|
||||
void do_toggle(void);
|
||||
void dos_format(void);
|
||||
void mac_format(void);
|
||||
void append_it(void);
|
||||
void prepend_it(void);
|
||||
void back_it_up(void);
|
||||
@@ -658,3 +699,12 @@ void flip_newbuffer(void);
|
||||
#endif
|
||||
void discard_buffer(void);
|
||||
void do_cancel(void);
|
||||
|
||||
/* Most functions in folding.c. */
|
||||
#ifdef ENABLE_FOLDING
|
||||
void do_fold_segment(void);
|
||||
void unfold_folded_segment(linestruct *line);
|
||||
linestruct *get_start_of_folded_segment(linestruct* line);
|
||||
linestruct *get_end_of_folded_segment(linestruct* line);
|
||||
int get_folded_segment_length(linestruct *line);
|
||||
#endif
|
||||
|
||||
338
src/rcfile.c
338
src/rcfile.c
@@ -1,10 +1,10 @@
|
||||
/**************************************************************************
|
||||
* rcfile.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 2001-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2001-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2014 Mike Frysinger *
|
||||
* Copyright (C) 2019 Brand Huntsman *
|
||||
* Copyright (C) 2014-2020 Benno Schulenberg *
|
||||
* Copyright (C) 2014-2021, 2024 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -17,7 +17,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -64,12 +64,13 @@ static const rcoption rcopts[] = {
|
||||
{"mouse", USE_MOUSE},
|
||||
#endif
|
||||
#ifdef ENABLE_MULTIBUFFER
|
||||
{"multibuffer", MULTIBUFFER},
|
||||
{"multibuffer", NEW_BUFFER}, /* Deprecated; remove in 2031. */
|
||||
{"newbuffer", NEW_BUFFER},
|
||||
#endif
|
||||
{"nohelp", NO_HELP},
|
||||
{"nonewlines", NO_NEWLINES},
|
||||
#ifdef ENABLE_WRAPPING
|
||||
{"nowrap", NO_WRAP}, /* Deprecated; remove in 2024. */
|
||||
{"nowrap", NO_WRAP}, /* Deprecated; remove in 2027. */
|
||||
#endif
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
{"operatingdir", 0},
|
||||
@@ -90,9 +91,6 @@ static const rcoption rcopts[] = {
|
||||
#ifdef ENABLE_SPELLER
|
||||
{"speller", 0},
|
||||
#endif
|
||||
{"suspend", SUSPENDABLE}, /* Deprecated; remove in 2022. */
|
||||
{"suspendable", SUSPENDABLE}, /* Obsolete; remove in 2022. */
|
||||
{"tempfile", SAVE_ON_EXIT}, /* Deprecated; remove in 2022. */
|
||||
#ifndef NANO_TINY
|
||||
{"afterends", AFTER_ENDS},
|
||||
{"allow_insecure_backup", INSECURE_BACKUP},
|
||||
@@ -101,6 +99,7 @@ static const rcoption rcopts[] = {
|
||||
{"backup", MAKE_BACKUP},
|
||||
{"backupdir", 0},
|
||||
{"bookstyle", BOOKSTYLE},
|
||||
{"colonparsing", COLON_PARSING},
|
||||
{"cutfromcursor", CUT_FROM_CURSOR},
|
||||
{"emptyline", EMPTY_LINE},
|
||||
{"guidestripe", 0},
|
||||
@@ -113,12 +112,14 @@ static const rcoption rcopts[] = {
|
||||
{"showcursor", SHOW_CURSOR},
|
||||
{"smarthome", SMART_HOME},
|
||||
{"softwrap", SOFTWRAP},
|
||||
{"solosidescroll", SOLO_SIDESCROLL},
|
||||
{"stateflags", STATEFLAGS},
|
||||
{"tabsize", 0},
|
||||
{"tabstospaces", TABS_TO_SPACES},
|
||||
{"trimblanks", TRIM_BLANKS},
|
||||
{"unix", MAKE_IT_UNIX},
|
||||
{"whitespace", 0},
|
||||
{"whitespacedisplay", WHITESPACE_DISPLAY},
|
||||
{"wordbounds", WORD_BOUNDS},
|
||||
{"wordchars", 0},
|
||||
{"zap", LET_THEM_ZAP},
|
||||
@@ -137,6 +138,7 @@ static const rcoption rcopts[] = {
|
||||
{"errorcolor", 0},
|
||||
{"keycolor", 0},
|
||||
{"functioncolor", 0},
|
||||
{"foldedcolor", 0},
|
||||
#endif
|
||||
{NULL, 0}
|
||||
};
|
||||
@@ -156,18 +158,6 @@ static bool seen_color_command = FALSE;
|
||||
static colortype *lastcolor = NULL;
|
||||
/* The end of the color list for the current syntax. */
|
||||
#endif
|
||||
|
||||
#define NUMBER_OF_MENUS 17 /* Remove the deprecated 'extcmd' in 2022. */
|
||||
char *menunames[NUMBER_OF_MENUS] = { "main", "search", "replace", "replacewith",
|
||||
"yesno", "gotoline", "writeout", "insert",
|
||||
"execute", "extcmd", "help", "spell", "linter",
|
||||
"browser", "whereisfile", "gotodir",
|
||||
"all" };
|
||||
int menusymbols[NUMBER_OF_MENUS] = { MMAIN, MWHEREIS, MREPLACE, MREPLACEWITH,
|
||||
MYESNO, MGOTOLINE, MWRITEFILE, MINSERTFILE,
|
||||
MEXECUTE, MEXECUTE, MHELP, MSPELL, MLINTER,
|
||||
MBROWSER, MWHEREISFILE, MGOTODIR,
|
||||
MMOST|MBROWSER|MHELP|MYESNO };
|
||||
#endif /* ENABLE_NANORC */
|
||||
|
||||
#if defined(ENABLE_NANORC) || defined(ENABLE_HISTORIES)
|
||||
@@ -200,7 +190,7 @@ void jot_error(const char *msg, ...)
|
||||
|
||||
if (startup_problem == NULL) {
|
||||
#ifdef ENABLE_NANORC
|
||||
if (nanorc != NULL) {
|
||||
if (nanorc) {
|
||||
snprintf(textbuf, MAXSIZE, _("Mistakes in '%s'"), nanorc);
|
||||
startup_problem = copy_of(textbuf);
|
||||
} else
|
||||
@@ -209,8 +199,7 @@ void jot_error(const char *msg, ...)
|
||||
}
|
||||
#ifdef ENABLE_NANORC
|
||||
if (lineno > 0)
|
||||
length = snprintf(textbuf, MAXSIZE, _("Error in %s on line %zu: "),
|
||||
nanorc, lineno);
|
||||
length = snprintf(textbuf, MAXSIZE, _("Error in %s on line %zu: "), nanorc, lineno);
|
||||
#endif
|
||||
va_start(ap, msg);
|
||||
length += vsnprintf(textbuf + length, MAXSIZE - length, _(msg), ap);
|
||||
@@ -260,6 +249,8 @@ keystruct *strtosc(const char *input)
|
||||
s->func = do_replace;
|
||||
else if (!strcmp(input, "cut"))
|
||||
s->func = cut_text;
|
||||
else if (!strcmp(input, "copy"))
|
||||
s->func = copy_text;
|
||||
else if (!strcmp(input, "paste"))
|
||||
s->func = paste_text;
|
||||
#ifndef NANO_TINY
|
||||
@@ -267,8 +258,6 @@ keystruct *strtosc(const char *input)
|
||||
s->func = do_execute;
|
||||
else if (!strcmp(input, "cutrestoffile"))
|
||||
s->func = cut_till_eof;
|
||||
else if (!strcmp(input, "copy"))
|
||||
s->func = copy_text;
|
||||
else if (!strcmp(input, "zap"))
|
||||
s->func = zap_text;
|
||||
else if (!strcmp(input, "mark"))
|
||||
@@ -279,14 +268,15 @@ keystruct *strtosc(const char *input)
|
||||
!strcmp(input, "speller"))
|
||||
s->func = do_spell;
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
#ifdef ENABLE_LINTER
|
||||
else if (!strcmp(input, "linter"))
|
||||
s->func = do_linter;
|
||||
#endif
|
||||
#ifdef ENABLE_FORMATTER
|
||||
else if (!strcmp(input, "formatter"))
|
||||
s->func = do_formatter;
|
||||
#endif
|
||||
else if (!strcmp(input, "location") ||
|
||||
!strcmp(input, "curpos")) /* Deprecated; remove in 2022. */
|
||||
else if (!strcmp(input, "location"))
|
||||
s->func = report_cursor_position;
|
||||
else if (!strcmp(input, "gotoline"))
|
||||
s->func = do_gotolinecolumn;
|
||||
@@ -335,6 +325,8 @@ keystruct *strtosc(const char *input)
|
||||
s->func = do_undo;
|
||||
else if (!strcmp(input, "redo"))
|
||||
s->func = do_redo;
|
||||
else if (!strcmp(input, "suspend"))
|
||||
s->func = do_suspend;
|
||||
#endif
|
||||
else if (!strcmp(input, "left") ||
|
||||
!strcmp(input, "back"))
|
||||
@@ -348,13 +340,17 @@ keystruct *strtosc(const char *input)
|
||||
else if (!strcmp(input, "down") ||
|
||||
!strcmp(input, "nextline"))
|
||||
s->func = do_down;
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcmp(input, "scrollleft"))
|
||||
s->func = do_scroll_left;
|
||||
else if (!strcmp(input, "scrollright"))
|
||||
s->func = do_scroll_right;
|
||||
#endif
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_HELP)
|
||||
else if (!strcmp(input, "scrollup"))
|
||||
s->func = do_scroll_up;
|
||||
else if (!strcmp(input, "scrolldown"))
|
||||
s->func = do_scroll_down;
|
||||
else if (!strcmp(input, "center"))
|
||||
s->func = do_center;
|
||||
#endif
|
||||
else if (!strcmp(input, "prevword"))
|
||||
s->func = to_prev_word;
|
||||
@@ -368,6 +364,16 @@ keystruct *strtosc(const char *input)
|
||||
s->func = to_prev_block;
|
||||
else if (!strcmp(input, "nextblock"))
|
||||
s->func = to_next_block;
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcmp(input, "toprow"))
|
||||
s->func = to_top_row;
|
||||
else if (!strcmp(input, "bottomrow"))
|
||||
s->func = to_bottom_row;
|
||||
else if (!strcmp(input, "center"))
|
||||
s->func = do_center;
|
||||
else if (!strcmp(input, "cycle"))
|
||||
s->func = do_cycle;
|
||||
#endif
|
||||
else if (!strcmp(input, "pageup") ||
|
||||
!strcmp(input, "prevpage"))
|
||||
s->func = do_page_up;
|
||||
@@ -396,10 +402,6 @@ keystruct *strtosc(const char *input)
|
||||
s->func = do_backspace;
|
||||
else if (!strcmp(input, "refresh"))
|
||||
s->func = full_refresh;
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcmp(input, "suspend"))
|
||||
s->func = do_suspend;
|
||||
#endif
|
||||
else if (!strcmp(input, "casesens"))
|
||||
s->func = case_sens_void;
|
||||
else if (!strcmp(input, "regexp"))
|
||||
@@ -408,8 +410,6 @@ keystruct *strtosc(const char *input)
|
||||
s->func = backwards_void;
|
||||
else if (!strcmp(input, "flipreplace"))
|
||||
s->func = flip_replace;
|
||||
else if (!strcmp(input, "flipgoto"))
|
||||
s->func = flip_goto;
|
||||
#ifdef ENABLE_HISTORIES
|
||||
else if (!strcmp(input, "older"))
|
||||
s->func = get_older_item;
|
||||
@@ -419,8 +419,6 @@ keystruct *strtosc(const char *input)
|
||||
#ifndef NANO_TINY
|
||||
else if (!strcmp(input, "dosformat"))
|
||||
s->func = dos_format;
|
||||
else if (!strcmp(input, "macformat"))
|
||||
s->func = mac_format;
|
||||
else if (!strcmp(input, "append"))
|
||||
s->func = append_it;
|
||||
else if (!strcmp(input, "prepend"))
|
||||
@@ -477,8 +475,7 @@ keystruct *strtosc(const char *input)
|
||||
else if (!strcmp(input, "cutfromcursor"))
|
||||
s->toggle = CUT_FROM_CURSOR;
|
||||
#ifdef ENABLE_WRAPPING
|
||||
else if (!strcmp(input, "breaklonglines") ||
|
||||
!strcmp(input, "nowrap")) /* Deprecated; remove in 2024. */
|
||||
else if (!strcmp(input, "breaklonglines"))
|
||||
s->toggle = BREAK_LONG_LINES;
|
||||
#endif
|
||||
else if (!strcmp(input, "tabstospaces"))
|
||||
@@ -497,6 +494,18 @@ keystruct *strtosc(const char *input)
|
||||
return s;
|
||||
}
|
||||
|
||||
#define NUMBER_OF_MENUS 16
|
||||
char *menunames[NUMBER_OF_MENUS] = { "main", "search", "replace", "replacewith",
|
||||
"yesno", "gotoline", "writeout", "insert",
|
||||
"execute", "help", "spell", "linter",
|
||||
"browser", "whereisfile", "gotodir",
|
||||
"all" };
|
||||
int menusymbols[NUMBER_OF_MENUS] = { MMAIN, MWHEREIS, MREPLACE, MREPLACEWITH,
|
||||
MYESNO, MGOTOLINE, MWRITEFILE, MINSERTFILE,
|
||||
MEXECUTE, MHELP, MSPELL, MLINTER,
|
||||
MBROWSER, MWHEREISFILE, MGOTODIR,
|
||||
MMOST|MBROWSER|MHELP|MYESNO };
|
||||
|
||||
/* Return the symbol that corresponds to the given menu name. */
|
||||
int name_to_menu(const char *name)
|
||||
{
|
||||
@@ -506,7 +515,7 @@ int name_to_menu(const char *name)
|
||||
if (strcmp(name, menunames[index]) == 0)
|
||||
return menusymbols[index];
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the name that corresponds to the given menu symbol. */
|
||||
@@ -521,12 +530,12 @@ char *menu_to_name(int menu)
|
||||
return "boooo";
|
||||
}
|
||||
|
||||
/* Parse the next word from the string, null-terminate it, and return
|
||||
* a pointer to the first character after the null terminator. The
|
||||
* returned pointer will point to '\0' if we hit the end of the line. */
|
||||
/* Parse the next word from the string (if any), null-terminate it,
|
||||
* and return a pointer to the next word. The returned pointer will
|
||||
* point to '\0' when end-of-line was reached. */
|
||||
char *parse_next_word(char *ptr)
|
||||
{
|
||||
while (!isblank((unsigned char)*ptr) && *ptr != '\0')
|
||||
while (*ptr && !isblank((unsigned char)*ptr))
|
||||
ptr++;
|
||||
|
||||
if (*ptr == '\0')
|
||||
@@ -541,25 +550,23 @@ char *parse_next_word(char *ptr)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Parse an argument, with optional quotes, after a keyword that takes
|
||||
* one. If the next word starts with a ", we say that it ends with the
|
||||
* last " of the line. Otherwise, we interpret it as usual, so that the
|
||||
* arguments can contain "'s too. */
|
||||
/* Parse an argument (optionally enveloped in double quotes). When the
|
||||
* argument starts with a ", then the last " of the line indicates its
|
||||
* end -- meaning that an argument can contain "'s either way. */
|
||||
char *parse_argument(char *ptr)
|
||||
{
|
||||
const char *ptr_save = ptr;
|
||||
const char *the_start = ptr;
|
||||
char *last_quote = NULL;
|
||||
|
||||
if (*ptr != '"')
|
||||
return parse_next_word(ptr);
|
||||
|
||||
while (*ptr != '\0') {
|
||||
while (*ptr)
|
||||
if (*++ptr == '"')
|
||||
last_quote = ptr;
|
||||
}
|
||||
|
||||
if (last_quote == NULL) {
|
||||
jot_error(N_("Argument '%s' has an unterminated \""), ptr_save);
|
||||
jot_error(N_("Argument '%s' has an unterminated \""), the_start);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -586,8 +593,7 @@ char *parse_next_regex(char *ptr)
|
||||
|
||||
/* Continue until the end of the line, or until a double quote followed
|
||||
* by end-of-line or a blank. */
|
||||
while (*ptr != '\0' && (*ptr != '"' ||
|
||||
(ptr[1] != '\0' && !isblank((unsigned char)ptr[1]))))
|
||||
while (*ptr && (*ptr != '"' || (ptr[1] && !isblank((unsigned char)ptr[1]))))
|
||||
ptr++;
|
||||
|
||||
if (*ptr == '\0') {
|
||||
@@ -676,12 +682,12 @@ void begin_new_syntax(char *ptr)
|
||||
live_syntax->magics = NULL;
|
||||
live_syntax->linter = NULL;
|
||||
live_syntax->formatter = NULL;
|
||||
live_syntax->tab = NULL;
|
||||
live_syntax->tabstring = NULL;
|
||||
#ifdef ENABLE_COMMENT
|
||||
live_syntax->comment = copy_of(GENERAL_COMMENT_CHARACTER);
|
||||
#endif
|
||||
live_syntax->color = NULL;
|
||||
live_syntax->nmultis = 0;
|
||||
live_syntax->multiscore = 0;
|
||||
|
||||
/* Hook the new syntax in at the top of the list. */
|
||||
live_syntax->next = syntaxes;
|
||||
@@ -691,13 +697,13 @@ void begin_new_syntax(char *ptr)
|
||||
seen_color_command = FALSE;
|
||||
|
||||
/* The default syntax should have no associated extensions. */
|
||||
if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') {
|
||||
if (*ptr && strcmp(live_syntax->name, "default") == 0) {
|
||||
jot_error(N_("The \"default\" syntax does not accept extensions"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there seem to be extension regexes, pick them up. */
|
||||
if (*ptr != '\0')
|
||||
if (*ptr)
|
||||
grab_and_store("extension", ptr, &live_syntax->extensions);
|
||||
}
|
||||
#endif /* ENABLE_COLOR */
|
||||
@@ -734,9 +740,11 @@ bool is_universal(void (*func)(void))
|
||||
/* Bind or unbind a key combo, to or from a function. */
|
||||
void parse_binding(char *ptr, bool dobind)
|
||||
{
|
||||
char *keyptr = NULL, *keycopy = NULL, *funcptr = NULL, *menuptr = NULL;
|
||||
int keycode, menu, mask = 0;
|
||||
char *keycopy, *keyptr, *menuptr;
|
||||
keystruct *newsc = NULL;
|
||||
char *funcptr = NULL;
|
||||
int keycode, menu;
|
||||
int mask = 0;
|
||||
|
||||
check_for_nonempty_syntax();
|
||||
|
||||
@@ -750,12 +758,13 @@ void parse_binding(char *ptr, bool dobind)
|
||||
keycopy = copy_of(keyptr);
|
||||
|
||||
/* Uppercase either the second or the first character of the key name. */
|
||||
if (keycopy[0] == '^')
|
||||
keycopy[1] = toupper((unsigned char)keycopy[1]);
|
||||
else
|
||||
keycopy[0] = toupper((unsigned char)keycopy[0]);
|
||||
if (keycopy[0] == '^') {
|
||||
if ('a' <= keycopy[1] && keycopy[1] <= 'z')
|
||||
keycopy[1] &= 0x5F;
|
||||
} else if ('a' <= keycopy[0] && keycopy[0] <= 'z')
|
||||
keycopy[0] &= 0x5F;
|
||||
|
||||
/* Verify that the key name is not too short, to allow the next call. */
|
||||
/* Verify that the key name is not too short. */
|
||||
if (keycopy[1] == '\0' || (keycopy[0] == 'M' && keycopy[2] == '\0')) {
|
||||
jot_error(N_("Key name %s is invalid"), keycopy);
|
||||
goto free_things;
|
||||
@@ -780,12 +789,17 @@ void parse_binding(char *ptr, bool dobind)
|
||||
}
|
||||
|
||||
menuptr = ptr;
|
||||
ptr = parse_next_word(ptr);
|
||||
parse_next_word(ptr);
|
||||
|
||||
if (menuptr[0] == '\0') {
|
||||
/* TRANSLATORS: Do not translate the word "all". */
|
||||
jot_error(N_("Must specify a menu (or \"all\") "
|
||||
"in which to bind/unbind the key"));
|
||||
jot_error(N_("Must specify a menu (or \"all\") in which to bind/unbind the key"));
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
menu = name_to_menu(menuptr);
|
||||
if (menu == 0) {
|
||||
jot_error(N_("Unknown menu: %s"), menuptr);
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
@@ -803,17 +817,11 @@ void parse_binding(char *ptr, bool dobind)
|
||||
newsc = strtosc(funcptr);
|
||||
|
||||
if (newsc == NULL) {
|
||||
jot_error(N_("Cannot map name \"%s\" to a function"), funcptr);
|
||||
jot_error(N_("Unknown function: %s"), funcptr);
|
||||
goto free_things;
|
||||
}
|
||||
}
|
||||
|
||||
menu = name_to_menu(menuptr);
|
||||
if (menu < 1) {
|
||||
jot_error(N_("Cannot map name \"%s\" to a menu"), menuptr);
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
/* Wipe the given shortcut from the given menu. */
|
||||
for (keystruct *s = sclist; s != NULL; s = s->next)
|
||||
if ((s->menus & menu) && s->keycode == keycode)
|
||||
@@ -848,8 +856,7 @@ void parse_binding(char *ptr, bool dobind)
|
||||
|
||||
if (!menu) {
|
||||
if (!ISSET(RESTRICTED) && !ISSET(VIEW_MODE))
|
||||
jot_error(N_("Function '%s' does not exist in menu '%s'"),
|
||||
funcptr, menuptr);
|
||||
jot_error(N_("Function '%s' does not exist in menu '%s'"), funcptr, menuptr);
|
||||
goto free_things;
|
||||
}
|
||||
|
||||
@@ -886,14 +893,14 @@ bool is_good_file(char *file)
|
||||
struct stat rcinfo;
|
||||
|
||||
/* First check that the file exists and is readable. */
|
||||
if (access(file, R_OK) != 0)
|
||||
if (access(file, R_OK) < 0)
|
||||
return FALSE;
|
||||
|
||||
/* If the thing exists, it may be neither a directory nor a device. */
|
||||
if (stat(file, &rcinfo) != -1 && (S_ISDIR(rcinfo.st_mode) ||
|
||||
if (stat(file, &rcinfo) == 0 && (S_ISDIR(rcinfo.st_mode) ||
|
||||
S_ISCHR(rcinfo.st_mode) || S_ISBLK(rcinfo.st_mode))) {
|
||||
jot_error(S_ISDIR(rcinfo.st_mode) ? N_("\"%s\" is a directory") :
|
||||
N_("\"%s\" is a device file"), file);
|
||||
jot_error(S_ISDIR(rcinfo.st_mode) ? N_("'%s' is a directory") :
|
||||
N_("'%s' is a device file"), file);
|
||||
return FALSE;
|
||||
} else
|
||||
return TRUE;
|
||||
@@ -901,7 +908,7 @@ bool is_good_file(char *file)
|
||||
|
||||
#ifdef ENABLE_COLOR
|
||||
/* Partially parse the syntaxes in the given file, or (when syntax
|
||||
* is not NULL) fully parse one specific syntax from the file . */
|
||||
* is not NULL) fully parse one specific syntax from the file. */
|
||||
void parse_one_include(char *file, syntaxtype *syntax)
|
||||
{
|
||||
char *was_nanorc = nanorc;
|
||||
@@ -910,7 +917,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
|
||||
FILE *rcstream;
|
||||
|
||||
/* Don't open directories, character files, or block files. */
|
||||
if (!is_good_file(file))
|
||||
if (access(file, R_OK) == 0 && !is_good_file(file))
|
||||
return;
|
||||
|
||||
rcstream = fopen(file, "rb");
|
||||
@@ -942,7 +949,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
|
||||
extra = syntax->augmentations;
|
||||
|
||||
/* Apply any stored extendsyntax commands. */
|
||||
while (extra != NULL) {
|
||||
while (extra) {
|
||||
char *keyword = extra->data;
|
||||
char *therest = parse_next_word(extra->data);
|
||||
|
||||
@@ -955,6 +962,7 @@ void parse_one_include(char *file, syntaxtype *syntax)
|
||||
extra = extra->next;
|
||||
}
|
||||
|
||||
/* Indicate that this syntax has been loaded. */
|
||||
free(syntax->filename);
|
||||
syntax->filename = NULL;
|
||||
|
||||
@@ -974,11 +982,16 @@ void parse_includes(char *ptr)
|
||||
pattern = ptr;
|
||||
if (*pattern == '"')
|
||||
pattern++;
|
||||
ptr = parse_argument(ptr);
|
||||
parse_argument(ptr);
|
||||
|
||||
if (strlen(pattern) > PATH_MAX) {
|
||||
jot_error(N_("Path is too long"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Expand a tilde first, then try to match the globbing pattern. */
|
||||
expanded = real_dir_from_tilde(pattern);
|
||||
result = glob(expanded, GLOB_ERR, NULL, &files);
|
||||
expanded = expand_leading_tilde(pattern);
|
||||
result = glob(expanded, GLOB_ERR|GLOB_NOCHECK, NULL, &files);
|
||||
|
||||
/* If there are matches, process each of them. Otherwise, only
|
||||
* report an error if it's something other than zero matches. */
|
||||
@@ -993,16 +1006,22 @@ void parse_includes(char *ptr)
|
||||
}
|
||||
|
||||
/* Return the index of the color that is closest to the given RGB levels,
|
||||
* assuming that the terminal uses the 6x6x6 color cube of xterm-256color. */
|
||||
* assuming that the terminal uses the 6x6x6 color cube of xterm-256color.
|
||||
* When red == green == blue, return an index in the xterm gray scale. */
|
||||
short closest_index_color(short red, short green, short blue)
|
||||
{
|
||||
/* Translation table, from 16 intended levels to 6 available levels. */
|
||||
/* Translation table, from 16 intended color levels to 6 available levels. */
|
||||
static const short level[] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
|
||||
|
||||
if (COLORS == 256)
|
||||
return (36 * level[red] + 6 * level[green] + level[blue] + 16);
|
||||
else
|
||||
/* Translation table, from 14 intended gray levels to 24 available levels. */
|
||||
static const short gray[] = { 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 15, 18, 21, 23 };
|
||||
|
||||
if (COLORS != 256)
|
||||
return THE_DEFAULT;
|
||||
else if (red == green && green == blue && 0 < red && red < 0xF)
|
||||
return 232 + gray[red - 1];
|
||||
else
|
||||
return (36 * level[red] + 6 * level[green] + level[blue] + 16);
|
||||
}
|
||||
|
||||
#define COLORCOUNT 34
|
||||
@@ -1032,12 +1051,12 @@ short indices[COLORCOUNT] = { COLOR_RED, COLOR_GREEN, COLOR_BLUE,
|
||||
* vivid to TRUE for a lighter color, and thick for a heavier typeface. */
|
||||
short color_to_short(const char *colorname, bool *vivid, bool *thick)
|
||||
{
|
||||
if (strncmp(colorname, "bright", 6) == 0 && colorname[6] != '\0') {
|
||||
/* Prefix "bright" is deprecated; remove in 2024. */
|
||||
if (strncmp(colorname, "bright", 6) == 0 && colorname[6]) {
|
||||
/* Prefix "bright" is deprecated; remove in 2027. */
|
||||
*vivid = TRUE;
|
||||
*thick = TRUE;
|
||||
colorname += 6;
|
||||
} else if (strncmp(colorname, "light", 5) == 0 && colorname[5] != '\0') {
|
||||
} else if (strncmp(colorname, "light", 5) == 0 && colorname[5]) {
|
||||
*vivid = TRUE;
|
||||
*thick = FALSE;
|
||||
colorname += 5;
|
||||
@@ -1075,40 +1094,40 @@ short color_to_short(const char *colorname, bool *vivid, bool *thick)
|
||||
|
||||
/* Parse the color name (or pair of color names) in the given string.
|
||||
* Return FALSE when any color name is invalid; otherwise return TRUE. */
|
||||
bool parse_combination(char *combostr, short *fg, short *bg, int *attributes)
|
||||
bool parse_combination(char *combotext, short *fg, short *bg, int *attributes)
|
||||
{
|
||||
bool vivid, thick;
|
||||
char *comma;
|
||||
|
||||
*attributes = A_NORMAL;
|
||||
|
||||
if (strncmp(combostr, "bold", 4) == 0) {
|
||||
if (strncmp(combotext, "bold", 4) == 0) {
|
||||
*attributes |= A_BOLD;
|
||||
if (combostr[4] != ',') {
|
||||
if (combotext[4] != ',') {
|
||||
jot_error(N_("An attribute requires a subsequent comma"));
|
||||
return FALSE;
|
||||
}
|
||||
combostr += 5;
|
||||
combotext += 5;
|
||||
}
|
||||
|
||||
if (strncmp(combostr, "italic", 6) == 0) {
|
||||
if (strncmp(combotext, "italic", 6) == 0) {
|
||||
#ifdef A_ITALIC
|
||||
*attributes |= A_ITALIC;
|
||||
#endif
|
||||
if (combostr[6] != ',') {
|
||||
if (combotext[6] != ',') {
|
||||
jot_error(N_("An attribute requires a subsequent comma"));
|
||||
return FALSE;
|
||||
}
|
||||
combostr += 7;
|
||||
combotext += 7;
|
||||
}
|
||||
|
||||
comma = strchr(combostr, ',');
|
||||
comma = strchr(combotext, ',');
|
||||
|
||||
if (comma)
|
||||
*comma = '\0';
|
||||
|
||||
if (!comma || comma > combostr) {
|
||||
*fg = color_to_short(combostr, &vivid, &thick);
|
||||
if (!comma || comma > combotext) {
|
||||
*fg = color_to_short(combotext, &vivid, &thick);
|
||||
if (*fg == BAD_COLOR)
|
||||
return FALSE;
|
||||
if (vivid && !thick && COLORS > 8)
|
||||
@@ -1155,7 +1174,7 @@ void parse_rule(char *ptr, int rex_flags)
|
||||
return;
|
||||
}
|
||||
|
||||
while (*ptr != '\0') {
|
||||
while (*ptr) {
|
||||
regex_t *start_rgx = NULL, *end_rgx = NULL;
|
||||
/* Intermediate storage for compiled regular expressions. */
|
||||
colortype *newcolor = NULL;
|
||||
@@ -1214,22 +1233,22 @@ void parse_rule(char *ptr, int rex_flags)
|
||||
|
||||
/* For a multiline rule, give it a number and increase the count. */
|
||||
if (expectend) {
|
||||
newcolor->id = live_syntax->nmultis;
|
||||
live_syntax->nmultis++;
|
||||
newcolor->id = live_syntax->multiscore;
|
||||
live_syntax->multiscore++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the argument of an interface color option. */
|
||||
colortype *parse_interface_color(char *combostr)
|
||||
/* Set the colors for the given interface element to the given combination. */
|
||||
void set_interface_color(int element, char *combotext)
|
||||
{
|
||||
colortype *trio = nmalloc(sizeof(colortype));
|
||||
|
||||
if (!parse_combination(combostr, &trio->fg, &trio->bg, &trio->attributes)) {
|
||||
free(trio);
|
||||
return NULL;
|
||||
if (parse_combination(combotext, &trio->fg, &trio->bg, &trio->attributes)) {
|
||||
free(color_combo[element]);
|
||||
color_combo[element] = trio;
|
||||
} else
|
||||
return trio;
|
||||
free(trio);
|
||||
}
|
||||
|
||||
/* Read regex strings enclosed in double quotes from the line pointed at
|
||||
@@ -1245,7 +1264,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
|
||||
}
|
||||
|
||||
/* The default syntax doesn't take any file matching stuff. */
|
||||
if (strcmp(live_syntax->name, "default") == 0 && *ptr != '\0') {
|
||||
if (*ptr && strcmp(live_syntax->name, "default") == 0) {
|
||||
jot_error(N_("The \"default\" syntax does not accept '%s' regexes"), kind);
|
||||
return;
|
||||
}
|
||||
@@ -1258,11 +1277,11 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
|
||||
lastthing = *storage;
|
||||
|
||||
/* If there was an earlier command, go to the last of those regexes. */
|
||||
while (lastthing != NULL && lastthing->next != NULL)
|
||||
while (lastthing && lastthing->next)
|
||||
lastthing = lastthing->next;
|
||||
|
||||
/* Now gather any valid regexes and add them to the linked list. */
|
||||
while (*ptr != '\0') {
|
||||
while (*ptr) {
|
||||
regex_t *packed_rgx = NULL;
|
||||
|
||||
regexstring = ++ptr;
|
||||
@@ -1289,7 +1308,7 @@ void grab_and_store(const char *kind, char *ptr, regexlisttype **storage)
|
||||
}
|
||||
}
|
||||
|
||||
/* Gather and store the string after a comment/linter command. */
|
||||
/* Gather and store the string after a comment/linter/formatter/tabgives command. */
|
||||
void pick_up_name(const char *kind, char *ptr, char **storage)
|
||||
{
|
||||
if (*ptr == '\0') {
|
||||
@@ -1327,20 +1346,22 @@ bool parse_syntax_commands(char *keyword, char *ptr)
|
||||
pick_up_name("comment", ptr, &live_syntax->comment);
|
||||
#endif
|
||||
} else if (strcmp(keyword, "tabgives") == 0) {
|
||||
pick_up_name("tabgives", ptr, &live_syntax->tab);
|
||||
} else if (strcmp(keyword, "linter") == 0)
|
||||
pick_up_name("tabgives", ptr, &live_syntax->tabstring);
|
||||
} else if (strcmp(keyword, "linter") == 0) {
|
||||
pick_up_name("linter", ptr, &live_syntax->linter);
|
||||
else if (strcmp(keyword, "formatter") == 0)
|
||||
strip_leading_blanks_from(live_syntax->linter);
|
||||
} else if (strcmp(keyword, "formatter") == 0) {
|
||||
pick_up_name("formatter", ptr, &live_syntax->formatter);
|
||||
else
|
||||
strip_leading_blanks_from(live_syntax->formatter);
|
||||
} else
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* ENABLE_COLOR */
|
||||
|
||||
/* Verify that the user has not unmapped every shortcut for a
|
||||
* function that we consider 'vital' (such as "Exit"). */
|
||||
/* Verify that the user has not unmapped every shortcut for
|
||||
* a function that we consider 'vital' (such as "Exit"). */
|
||||
static void check_vitals_mapped(void)
|
||||
{
|
||||
#define VITALS 4
|
||||
@@ -1349,10 +1370,10 @@ static void check_vitals_mapped(void)
|
||||
|
||||
for (int v = 0; v < VITALS; v++) {
|
||||
for (funcstruct *f = allfuncs; f != NULL; f = f->next) {
|
||||
if (f->func == vitals[v] && f->menus & inmenus[v]) {
|
||||
if (f->func == vitals[v] && (f->menus & inmenus[v])) {
|
||||
if (first_sc_for(inmenus[v], f->func) == NULL) {
|
||||
jot_error(N_("No key is bound to function '%s' in menu '%s'. "
|
||||
" Exiting.\n"), f->desc, menu_to_name(inmenus[v]));
|
||||
" Exiting.\n"), f->tag, menu_to_name(inmenus[v]));
|
||||
die(_("If needed, use nano with the -I option "
|
||||
"to adjust your nanorc settings.\n"));
|
||||
} else
|
||||
@@ -1364,7 +1385,7 @@ static void check_vitals_mapped(void)
|
||||
|
||||
/* Parse the rcfile, once it has been opened successfully at rcstream,
|
||||
* and close it afterwards. If just_syntax is TRUE, allow the file to
|
||||
* to contain only color syntax commands. */
|
||||
* contain only color syntax commands. */
|
||||
void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
@@ -1443,9 +1464,9 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
newitem->data = argument;
|
||||
newitem->next = NULL;
|
||||
|
||||
if (sntx->augmentations != NULL) {
|
||||
if (sntx->augmentations) {
|
||||
extra = sntx->augmentations;
|
||||
while (extra->next != NULL)
|
||||
while (extra->next)
|
||||
extra = extra->next;
|
||||
extra->next = newitem;
|
||||
} else
|
||||
@@ -1477,8 +1498,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
strcmp(keyword, "include") == 0 ||
|
||||
strcmp(keyword, "extendsyntax") == 0)) {
|
||||
if (intros_only)
|
||||
jot_error(N_("Command \"%s\" not allowed in included file"),
|
||||
keyword);
|
||||
jot_error(N_("Command \"%s\" not allowed in included file"), keyword);
|
||||
else
|
||||
break;
|
||||
} else if (intros_only && (strcmp(keyword, "color") == 0 ||
|
||||
@@ -1488,8 +1508,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
strcmp(keyword, "linter") == 0 ||
|
||||
strcmp(keyword, "formatter") == 0)) {
|
||||
if (!opensyntax)
|
||||
jot_error(N_("A '%s' command requires a preceding "
|
||||
"'syntax' command"), keyword);
|
||||
jot_error(N_("A '%s' command requires a preceding 'syntax' command"), keyword);
|
||||
if (strstr("icolor", keyword))
|
||||
seen_color_command = TRUE;
|
||||
continue;
|
||||
@@ -1534,7 +1553,7 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
}
|
||||
|
||||
if (rcopts[i].name == NULL) {
|
||||
jot_error(N_("Unknown option \"%s\""), option);
|
||||
jot_error(N_("Unknown option: %s"), option);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1561,40 +1580,42 @@ void parse_rcfile(FILE *rcstream, bool just_syntax, bool intros_only)
|
||||
argument = ptr;
|
||||
if (*argument == '"')
|
||||
argument++;
|
||||
ptr = parse_argument(ptr);
|
||||
parse_argument(ptr);
|
||||
|
||||
#ifdef ENABLE_UTF8
|
||||
/* When in a UTF-8 locale, ignore arguments with invalid sequences. */
|
||||
if (using_utf8() && mbstowcs(NULL, argument, 0) == (size_t)-1) {
|
||||
if (using_utf8 && mbstowcs(NULL, argument, 0) == (size_t)-1) {
|
||||
jot_error(N_("Argument is not a valid multibyte string"));
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_COLOR
|
||||
if (strcmp(option, "titlecolor") == 0)
|
||||
color_combo[TITLE_BAR] = parse_interface_color(argument);
|
||||
set_interface_color(TITLE_BAR, argument);
|
||||
else if (strcmp(option, "numbercolor") == 0)
|
||||
color_combo[LINE_NUMBER] = parse_interface_color(argument);
|
||||
set_interface_color(LINE_NUMBER, argument);
|
||||
else if (strcmp(option, "stripecolor") == 0)
|
||||
color_combo[GUIDE_STRIPE] = parse_interface_color(argument);
|
||||
set_interface_color(GUIDE_STRIPE, argument);
|
||||
else if (strcmp(option, "scrollercolor") == 0)
|
||||
color_combo[SCROLL_BAR] = parse_interface_color(argument);
|
||||
set_interface_color(SCROLL_BAR, argument);
|
||||
else if (strcmp(option, "selectedcolor") == 0)
|
||||
color_combo[SELECTED_TEXT] = parse_interface_color(argument);
|
||||
set_interface_color(SELECTED_TEXT, argument);
|
||||
else if (strcmp(option, "spotlightcolor") == 0)
|
||||
color_combo[SPOTLIGHTED] = parse_interface_color(argument);
|
||||
set_interface_color(SPOTLIGHTED, argument);
|
||||
else if (strcmp(option, "minicolor") == 0)
|
||||
color_combo[MINI_INFOBAR] = parse_interface_color(argument);
|
||||
set_interface_color(MINI_INFOBAR, argument);
|
||||
else if (strcmp(option, "promptcolor") == 0)
|
||||
color_combo[PROMPT_BAR] = parse_interface_color(argument);
|
||||
set_interface_color(PROMPT_BAR, argument);
|
||||
else if (strcmp(option, "statuscolor") == 0)
|
||||
color_combo[STATUS_BAR] = parse_interface_color(argument);
|
||||
set_interface_color(STATUS_BAR, argument);
|
||||
else if (strcmp(option, "errorcolor") == 0)
|
||||
color_combo[ERROR_MESSAGE] = parse_interface_color(argument);
|
||||
set_interface_color(ERROR_MESSAGE, argument);
|
||||
else if (strcmp(option, "keycolor") == 0)
|
||||
color_combo[KEY_COMBO] = parse_interface_color(argument);
|
||||
set_interface_color(KEY_COMBO, argument);
|
||||
else if (strcmp(option, "functioncolor") == 0)
|
||||
color_combo[FUNCTION_TAG] = parse_interface_color(argument);
|
||||
set_interface_color(FUNCTION_TAG, argument);
|
||||
else if (strcmp(option, "foldedcolor") == 0)
|
||||
set_interface_color(FOLDED_LINE, argument);
|
||||
else
|
||||
#endif
|
||||
#ifdef ENABLE_OPERATINGDIR
|
||||
@@ -1686,12 +1707,13 @@ void parse_one_nanorc(void)
|
||||
|
||||
/* If opening the file succeeded, parse it. Otherwise, only
|
||||
* complain if the file actually exists. */
|
||||
if (rcstream != NULL)
|
||||
if (rcstream)
|
||||
parse_rcfile(rcstream, FALSE, TRUE);
|
||||
else if (errno != ENOENT)
|
||||
jot_error(N_("Error reading %s: %s"), nanorc, strerror(errno));
|
||||
}
|
||||
|
||||
/* Return TRUE when path-plus-name denotes a readable, normal file. */
|
||||
bool have_nanorc(const char *path, const char *name)
|
||||
{
|
||||
if (path == NULL)
|
||||
@@ -1709,18 +1731,18 @@ void do_rcfiles(void)
|
||||
{
|
||||
if (custom_nanorc) {
|
||||
nanorc = get_full_path(custom_nanorc);
|
||||
if (access(nanorc, F_OK) != 0)
|
||||
if (nanorc == NULL || access(nanorc, F_OK) < 0)
|
||||
die(_("Specified rcfile does not exist\n"));
|
||||
} else
|
||||
nanorc = mallocstrcpy(nanorc, SYSCONFDIR "/nanorc");
|
||||
if (is_good_file(nanorc))
|
||||
parse_one_nanorc();
|
||||
} else {
|
||||
const char *xdgconfdir;
|
||||
|
||||
if (is_good_file(nanorc))
|
||||
parse_one_nanorc();
|
||||
|
||||
if (custom_nanorc == NULL) {
|
||||
const char *xdgconfdir = getenv("XDG_CONFIG_HOME");
|
||||
if (have_nanorc(SYSCONFDIR, "/nanorc"))
|
||||
parse_one_nanorc();
|
||||
|
||||
get_homedir();
|
||||
xdgconfdir = getenv("XDG_CONFIG_HOME");
|
||||
|
||||
/* Now try to find a nanorc file in the user's home directory or in the
|
||||
* XDG configuration directories, and process the first one found. */
|
||||
|
||||
622
src/search.c
622
src/search.c
File diff suppressed because it is too large
Load Diff
592
src/text.c
592
src/text.c
File diff suppressed because it is too large
Load Diff
160
src/utils.c
160
src/utils.c
@@ -1,8 +1,8 @@
|
||||
/**************************************************************************
|
||||
* utils.c -- This file is part of GNU nano. *
|
||||
* *
|
||||
* Copyright (C) 1999-2011, 2013-2021 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019 Benno Schulenberg *
|
||||
* Copyright (C) 1999-2011, 2013-2026 Free Software Foundation, Inc. *
|
||||
* Copyright (C) 2016, 2017, 2019, 2020, 2026 Benno Schulenberg *
|
||||
* *
|
||||
* GNU nano is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published *
|
||||
@@ -15,7 +15,7 @@
|
||||
* See the GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see http://www.gnu.org/licenses/. *
|
||||
* along with this program. If not, see https://gnu.org/licenses/. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
@@ -28,27 +28,25 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Return the user's home directory. We use $HOME, and if that fails,
|
||||
* we fall back on the home directory of the effective user ID. */
|
||||
/* Set global variable `homedir` to the user's home directory. First try
|
||||
* $HOME, otherwise consult the password database for the current UID. */
|
||||
void get_homedir(void)
|
||||
{
|
||||
if (homedir == NULL) {
|
||||
const char *homenv = getenv("HOME");
|
||||
|
||||
#ifdef HAVE_PWD_H
|
||||
/* When HOME isn't set, or when we're root, get the home directory
|
||||
* from the password file instead. */
|
||||
/* When $HOME is unset, or when we're root, try the database. */
|
||||
if (homenv == NULL || geteuid() == ROOT_UID) {
|
||||
const struct passwd *userage = getpwuid(geteuid());
|
||||
|
||||
if (userage != NULL)
|
||||
if (userage)
|
||||
homenv = userage->pw_dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Only set homedir if some home directory could be determined,
|
||||
* otherwise keep homedir NULL. */
|
||||
if (homenv != NULL && *homenv != '\0')
|
||||
/* Only set `homedir` if a home directory could be determined. */
|
||||
if (homenv && *homenv)
|
||||
homedir = copy_of(homenv);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +116,7 @@ bool parse_num(const char *string, ssize_t *result)
|
||||
|
||||
value = (ssize_t)strtol(string, &excess, 10);
|
||||
|
||||
if (errno == ERANGE || *string == '\0' || *excess != '\0')
|
||||
if (errno == ERANGE || *string == '\0' || *excess)
|
||||
return FALSE;
|
||||
|
||||
*result = value;
|
||||
@@ -126,29 +124,30 @@ bool parse_num(const char *string, ssize_t *result)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Read two numbers, separated by a comma, from str, and store them in
|
||||
* *line and *column. Return FALSE on error, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *str, ssize_t *line, ssize_t *column)
|
||||
/* Read one number (or two numbers separated by comma, period, or colon)
|
||||
* from the given string and store the number(s) in *line (and *column).
|
||||
* Return FALSE on a failed parsing, and TRUE otherwise. */
|
||||
bool parse_line_column(const char *string, ssize_t *line, ssize_t *column)
|
||||
{
|
||||
bool retval;
|
||||
char *firstpart;
|
||||
const char *comma;
|
||||
char *firstpart;
|
||||
bool retval;
|
||||
|
||||
while (*str == ' ')
|
||||
str++;
|
||||
while (*string == ' ')
|
||||
string++;
|
||||
|
||||
comma = strpbrk(str, "m,. /;");
|
||||
comma = strpbrk(string, ",.:");
|
||||
|
||||
if (comma == NULL)
|
||||
return parse_num(str, line);
|
||||
return parse_num(string, line);
|
||||
|
||||
retval = parse_num(comma + 1, column);
|
||||
|
||||
if (comma == str)
|
||||
if (comma == string)
|
||||
return retval;
|
||||
|
||||
firstpart = copy_of(str);
|
||||
firstpart[comma - str] = '\0';
|
||||
firstpart = copy_of(string);
|
||||
firstpart[comma - string] = '\0';
|
||||
|
||||
retval = parse_num(firstpart, line) && retval;
|
||||
|
||||
@@ -168,14 +167,19 @@ void recode_NUL_to_LF(char *string, size_t length)
|
||||
}
|
||||
}
|
||||
|
||||
/* In the given string, recode each embedded newline as a NUL. */
|
||||
void recode_LF_to_NUL(char *string)
|
||||
/* In the given string, recode each embedded newline as a NUL,
|
||||
* and return the number of bytes in the string. */
|
||||
size_t recode_LF_to_NUL(char *string)
|
||||
{
|
||||
while (*string != '\0') {
|
||||
char *beginning = string;
|
||||
|
||||
while (*string) {
|
||||
if (*string == '\n')
|
||||
*string = '\0';
|
||||
string++;
|
||||
}
|
||||
|
||||
return (string - beginning);
|
||||
}
|
||||
|
||||
#if !defined(ENABLE_TINY) || defined(ENABLE_TABCOMP) || defined(ENABLE_BROWSER)
|
||||
@@ -193,16 +197,13 @@ void free_chararray(char **array, size_t len)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SPELLER
|
||||
/* Is the word starting at the given position in 'text' and of the given
|
||||
/* Is the word starting at the given position in `text` and of the given
|
||||
* length a separate word? That is: is it not part of a longer word? */
|
||||
bool is_separate_word(size_t position, size_t length, const char *text)
|
||||
{
|
||||
const char *before = text + step_left(text, position);
|
||||
const char *after = text + position + length;
|
||||
|
||||
/* If the word starts at the beginning of the line OR the character before
|
||||
* the word isn't a letter, and if the word ends at the end of the line OR
|
||||
* the character after the word isn't a letter, we have a whole word. */
|
||||
return ((position == 0 || !is_alpha_char(before)) &&
|
||||
(*after == '\0' || !is_alpha_char(after)));
|
||||
}
|
||||
@@ -213,8 +214,7 @@ bool is_separate_word(size_t position, size_t length, const char *text)
|
||||
* than the given start; otherwise, we find the first match starting no earlier
|
||||
* than start. If we are doing a regexp search, and we find a match, we fill
|
||||
* in the global variable regmatches with at most 9 subexpression matches. */
|
||||
const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
const char *start)
|
||||
const char *strstrwrapper(const char *haystack, const char *needle, const char *start)
|
||||
{
|
||||
if (ISSET(USE_REGEXP)) {
|
||||
if (ISSET(BACKWARDS_SEARCH)) {
|
||||
@@ -244,16 +244,14 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
next_rung = step_right(haystack, last_find);
|
||||
regmatches[0].rm_so = next_rung;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
if (regexec(&search_regexp, haystack, 1, regmatches, REG_STARTEND) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the last match again, to get possible submatches. */
|
||||
regmatches[0].rm_so = floor;
|
||||
regmatches[0].rm_eo = far_end;
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches, REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
|
||||
return haystack + regmatches[0].rm_so;
|
||||
@@ -262,8 +260,7 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
/* Do a forward regex search from the starting point. */
|
||||
regmatches[0].rm_so = start - haystack;
|
||||
regmatches[0].rm_eo = strlen(haystack);
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches,
|
||||
REG_STARTEND) != 0)
|
||||
if (regexec(&search_regexp, haystack, 10, regmatches, REG_STARTEND) != 0)
|
||||
return NULL;
|
||||
else
|
||||
return haystack + regmatches[0].rm_so;
|
||||
@@ -282,34 +279,26 @@ const char *strstrwrapper(const char *haystack, const char *needle,
|
||||
return mbstrcasestr(start, needle);
|
||||
}
|
||||
|
||||
/* This is a wrapper for the malloc() function that properly handles
|
||||
* things when we run out of memory. */
|
||||
/* Allocate the given amount of memory and return a pointer to it. */
|
||||
void *nmalloc(size_t howmuch)
|
||||
{
|
||||
void *r = malloc(howmuch);
|
||||
void *section = malloc(howmuch);
|
||||
|
||||
if (howmuch == 0)
|
||||
die("Allocating zero bytes. Please report a bug.\n");
|
||||
|
||||
if (r == NULL)
|
||||
if (section == NULL)
|
||||
die(_("Nano is out of memory!\n"));
|
||||
|
||||
return r;
|
||||
return section;
|
||||
}
|
||||
|
||||
/* This is a wrapper for the realloc() function that properly handles
|
||||
* things when we run out of memory. */
|
||||
void *nrealloc(void *ptr, size_t howmuch)
|
||||
/* Reallocate the given section of memory to have the given size. */
|
||||
void *nrealloc(void *section, size_t howmuch)
|
||||
{
|
||||
void *r = realloc(ptr, howmuch);
|
||||
section = realloc(section, howmuch);
|
||||
|
||||
if (howmuch == 0)
|
||||
die("Allocating zero bytes. Please report a bug.\n");
|
||||
|
||||
if (r == NULL)
|
||||
if (section == NULL)
|
||||
die(_("Nano is out of memory!\n"));
|
||||
|
||||
return r;
|
||||
return section;
|
||||
}
|
||||
|
||||
/* Return an appropriately reallocated dest string holding a copy of src.
|
||||
@@ -354,6 +343,22 @@ char *free_and_assign(char *dest, char *src)
|
||||
* displayed in the edit window when the cursor is at the given column. */
|
||||
size_t get_page_start(size_t column)
|
||||
{
|
||||
#ifndef NANO_TINY
|
||||
if (united_sidescroll) {
|
||||
if (column < CUSHION)
|
||||
return 0;
|
||||
else if (column < openfile->brink + CUSHION) {
|
||||
if (ISSET(JUMPY_SCROLLING))
|
||||
return (column > editwincols / 2) ? column - editwincols / 2 : 0;
|
||||
else
|
||||
return column - CUSHION;
|
||||
} else if (column > openfile->brink + editwincols - CUSHION - 1)
|
||||
return column - editwincols + (ISSET(JUMPY_SCROLLING) ? editwincols / 2 : CUSHION) + 1;
|
||||
else
|
||||
return openfile->brink;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (column == 0 || column + 2 < editwincols || ISSET(SOFTWRAP))
|
||||
return 0;
|
||||
else if (editwincols > 8)
|
||||
@@ -362,15 +367,8 @@ size_t get_page_start(size_t column)
|
||||
return column - (editwincols - 2);
|
||||
}
|
||||
|
||||
/* Return the placewewant associated with current_x, i.e. the zero-based
|
||||
* column position of the cursor. */
|
||||
size_t xplustabs(void)
|
||||
{
|
||||
return wideness(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Return the index in text of the character that (when displayed) will
|
||||
* not overshoot the given column. */
|
||||
/* Return the index in the given text of the character that (when displayed)
|
||||
* will not overshoot the given column. */
|
||||
size_t actual_x(const char *text, size_t column)
|
||||
{
|
||||
const char *start = text;
|
||||
@@ -378,7 +376,7 @@ size_t actual_x(const char *text, size_t column)
|
||||
size_t width = 0;
|
||||
/* The current accumulated span, in columns. */
|
||||
|
||||
while (*text != '\0') {
|
||||
while (*text) {
|
||||
int charlen = advance_over(text, &width);
|
||||
|
||||
if (width > column)
|
||||
@@ -390,22 +388,21 @@ size_t actual_x(const char *text, size_t column)
|
||||
return (text - start);
|
||||
}
|
||||
|
||||
/* A strnlen() with tabs and multicolumn characters factored in:
|
||||
* how many columns wide are the first maxlen bytes of text? */
|
||||
size_t wideness(const char *text, size_t maxlen)
|
||||
/* Return the number of columns that the first count bytes of text occupy. */
|
||||
size_t wideness(const char *text, size_t count)
|
||||
{
|
||||
size_t width = 0;
|
||||
|
||||
if (maxlen == 0)
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
while (*text != '\0') {
|
||||
while (*text) {
|
||||
size_t charlen = advance_over(text, &width);
|
||||
|
||||
if (maxlen <= charlen)
|
||||
if (count <= charlen)
|
||||
break;
|
||||
|
||||
maxlen -= charlen;
|
||||
count -= charlen;
|
||||
text += charlen;
|
||||
}
|
||||
|
||||
@@ -417,12 +414,18 @@ size_t breadth(const char *text)
|
||||
{
|
||||
size_t span = 0;
|
||||
|
||||
while (*text != '\0')
|
||||
while (*text)
|
||||
text += advance_over(text, &span);
|
||||
|
||||
return span;
|
||||
}
|
||||
|
||||
/* Return the (zero-based) column position of the cursor. */
|
||||
size_t xplustabs(void)
|
||||
{
|
||||
return wideness(openfile->current->data, openfile->current_x);
|
||||
}
|
||||
|
||||
/* Append a new magic line to the end of the buffer. */
|
||||
void new_magicline(void)
|
||||
{
|
||||
@@ -437,8 +440,9 @@ void new_magicline(void)
|
||||
* it isn't the only line in the file. */
|
||||
void remove_magicline(void)
|
||||
{
|
||||
if (openfile->filebot->data[0] == '\0' &&
|
||||
openfile->filebot != openfile->filetop) {
|
||||
if (openfile->filebot->data[0] == '\0' && openfile->filebot != openfile->filetop) {
|
||||
if (openfile->current == openfile->filebot)
|
||||
openfile->current = openfile->current->prev;
|
||||
openfile->filebot = openfile->filebot->prev;
|
||||
delete_node(openfile->filebot->next);
|
||||
openfile->filebot->next = NULL;
|
||||
@@ -492,7 +496,9 @@ void get_range(linestruct **top, linestruct **bot)
|
||||
also_the_last = TRUE;
|
||||
}
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
#if !defined(NANO_TINY) || defined(ENABLE_SPELLER) || defined (ENABLE_LINTER) || defined (ENABLE_FORMATTER)
|
||||
/* Return a pointer to the line that has the given line number. */
|
||||
linestruct *line_from_number(ssize_t number)
|
||||
{
|
||||
@@ -507,7 +513,7 @@ linestruct *line_from_number(ssize_t number)
|
||||
|
||||
return line;
|
||||
}
|
||||
#endif /* !NANO_TINY */
|
||||
#endif
|
||||
|
||||
/* Count the number of characters from begin to end, and return it. */
|
||||
size_t number_of_characters_in(const linestruct *begin, const linestruct *end)
|
||||
|
||||
1701
src/winio.c
1701
src/winio.c
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@ pkgdata_DATA = asm.nanorc \
|
||||
c.nanorc \
|
||||
css.nanorc \
|
||||
default.nanorc \
|
||||
elisp.nanorc \
|
||||
email.nanorc \
|
||||
go.nanorc \
|
||||
groff.nanorc \
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
## Syntax highlighting for assembler.
|
||||
|
||||
## Original author: Mike Frysinger
|
||||
## License: GPL version 3 or newer
|
||||
|
||||
syntax asm "\.(S|s|asm)$"
|
||||
magic "assembler source"
|
||||
comment "//"
|
||||
|
||||
color red "\<[A-Z_]{2,}\>"
|
||||
color brightgreen "\.(data|subsection|text)"
|
||||
color green "\.(align|file|globl|global|hidden|section|size|type|weak)"
|
||||
color brightyellow "\.(ascii|asciz|byte|double|float|hword|int|long|short|single|struct|word)"
|
||||
color brightred "^[[:blank:]]*[.0-9A-Za-z_]*:"
|
||||
color brightcyan "^[[:blank:]]*#[[:blank:]]*(define|undef|include|ifn?def|endif|elif|else|if|warning|error)"
|
||||
color red "\<[[:alpha:]_]{2,}\>"
|
||||
color brightgreen "\.(data|subsection|text)\>"
|
||||
color green "\.(align|file|globl|global|hidden|section|size|type|weak)\>"
|
||||
color brightyellow "\.(ascii|asciz|byte|double|float|hword|int|long|short|single|struct|word)\>"
|
||||
color brightred "^[[:blank:]]*[[:alnum:]_.]*:"
|
||||
color brightcyan "^[[:blank:]]*#[[:blank:]]*(define|undef|include|ifn?def|endif|elif|else|if|warning|error)\>"
|
||||
|
||||
# Strings and names of included files.
|
||||
color brightyellow ""([^"\]|\\.)*"|<[^= ]*>"
|
||||
|
||||
@@ -7,11 +7,11 @@ syntax autoconf "\.(ac|m4)$"
|
||||
comment "#"
|
||||
|
||||
# Keywords:
|
||||
color yellow "\<(if|test|then|elif|else|fi|for|in|do|done)\>"
|
||||
color yellow "\<(if|test|then|elif|else|fi|case|esac|ifelse|for|in|do|done)\>"
|
||||
color yellow "=|!=|&&|\|\|"
|
||||
|
||||
# Macros:
|
||||
color cyan "\<[[:upper:]_[:digit:]]+\>"
|
||||
color cyan "\<[[:upper:][:digit:]_]+\>"
|
||||
|
||||
# Version numbers:
|
||||
color red "\<[-_.0-9]+\>"
|
||||
@@ -29,7 +29,7 @@ color brightred "^[[:blank:]]*\*\*\*.*"
|
||||
color magenta "\[|\]|\(|\)"
|
||||
|
||||
# Comments:
|
||||
color blue "^[[:blank:]]*#.*" "\<dnl.*"
|
||||
color blue "^[[:blank:]]*#.*|\<dnl.*"
|
||||
|
||||
# Trailing whitespace:
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
## Syntax highlighting for AWK scripts.
|
||||
|
||||
## Original author: Donnie Berkholz
|
||||
|
||||
syntax awk "\.awk$"
|
||||
header "^#!.*awk"
|
||||
magic "awk script"
|
||||
comment "#"
|
||||
|
||||
# Records.
|
||||
color brightred "\$[0-9A-Za-z_!@#$*?-]+"
|
||||
color brightred "\$[[:alnum:]_!@#$*?-]+"
|
||||
# Awk-set variables.
|
||||
color red "\<(ARGC|ARGIND|ARGV|BINMODE|CONVFMT|ENVIRON|ERRNO|FIELDWIDTHS)\>"
|
||||
color red "\<(FILENAME|FNR|FS|IGNORECASE|LINT|NF|NR|OFMT|OFS|ORS)\>"
|
||||
color red "\<(PROCINFO|RS|RT|RSTART|RLENGTH|SUBSEP|TEXTDOMAIN)\>"
|
||||
# Function declarations and special patterns.
|
||||
color brightgreen "\<(function|extension|BEGIN|END)\>"
|
||||
# Operators.
|
||||
color green "\{|\}|\(|\)|\;|\[|\]|\\|<|>|!|=|&|\+|-|\*|%|/|\?:|\^|\|"
|
||||
# Operators and brackets/braces/slashes/parentheses.
|
||||
color green "[][!%&()*+/:;<=>?\^{|}~-]"
|
||||
# Flow control.
|
||||
color brightyellow "\<(for|if|while|do|else|in|delete|exit)\>"
|
||||
color brightyellow "\<(break|continue|return)\>"
|
||||
@@ -30,6 +32,8 @@ color magenta "\<(bindtextdomain|dcgettext|dcngettext)\>"
|
||||
|
||||
# Strings.
|
||||
color brightyellow ""([^"\]|\\.)*""
|
||||
# Escape sequences.
|
||||
color brick "\\([abfnrtv\/"]|[0-7]{1,3}|x[[:xdigit:]]{1,2}|u[[:xdigit:]]{1,8})"
|
||||
# Comments.
|
||||
color brightblue "(^|[[:blank:]])#.*"
|
||||
|
||||
|
||||
@@ -6,37 +6,41 @@ magic "^(C|C\+\+) (source|program)"
|
||||
comment "//"
|
||||
|
||||
# Constants.
|
||||
color brightred "\<[A-Z_][0-9A-Z_]*\>"
|
||||
color brightred "\<[[:upper:]_][[:upper:][:digit:]_]*\>"
|
||||
# Labels.
|
||||
color brightmagenta "^[[:blank:]]*[A-Z_a-z][0-9A-Z_a-z]*:[[:blank:]]*$"
|
||||
color brightmagenta "^[[:blank:]]*[[:alpha:]_][[:alnum:]_]*:[[:blank:]]*$"
|
||||
color normal ":[[:blank:]]*$"
|
||||
|
||||
# Types and related keywords.
|
||||
color green "\<(auto|bool|char|const|double|enum|extern|float|inline|int|long|restrict|short|signed|sizeof|static|struct|typedef|union|unsigned|void)\>"
|
||||
color green "\<([[:lower:]][[:lower:]_]*|(u_?)?int(8|16|32|64))_t\>"
|
||||
color green "\<(_(Alignas|Alignof|Atomic|Bool|Complex|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>"
|
||||
color green "\<(class|explicit|friend|mutable|namespace|override|private|protected|public|register|template|this|typename|using|virtual|volatile)\>"
|
||||
color green "\<(bool|char|double|enum|float|int|short|(un)?signed|struct|union|void|((u_?)?int(8|16|32|64)|[[:lower:]][[:lower:]_]*)_t)\>"
|
||||
color green "\<(align(as|of)|auto|const(eval|expr|init)?|extern|inline|register|restrict|sizeof|static(_assert)?|thread_local|typedef|typeof(_unqual)?|volatile)\>"
|
||||
color green "\<(_(Align(as|of)|Atomic|BitInt|Bool|Complex|Decimal(32|64|128)|Generic|Imaginary|Noreturn|Static_assert|Thread_local))\>"
|
||||
color green "\<(class|explicit|final|friend|mutable|namespace|override|private|protected|public|template|this|typename|using|virtual)\>"
|
||||
color green "\<(char(8|16|32)_t|wchar_t|(const|dynamic|reinterpret|static)_cast|decltype|export|import|module|noexcept|requires|typeid)\>"
|
||||
|
||||
# Flow control.
|
||||
color brightyellow "\<(if|else|for|while|do|switch|case|default)\>"
|
||||
color brightyellow "\<(try|throw|catch|operator|new|delete)\>"
|
||||
color magenta "\<(break|continue|goto|return)\>"
|
||||
color magenta "\<(break|continue|goto|(co_)?return)\>"
|
||||
|
||||
# Single-quoted stuff (characters, backslash escapes, hex and octal byte codes).
|
||||
color brightmagenta "'([^'\]|\\(["'\abfnrtv]|x[[:xdigit:]]{1,2}|[0-3]?[0-7]{1,2}))'"
|
||||
|
||||
# Hexadecimal, binary, and boolean values.
|
||||
color pink "\<(0[Xx][[:xdigit:]]['[:xdigit:]]*|0[Bb][01]['01]*|true|false|nullptr)\>"
|
||||
|
||||
# GCC builtins.
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)" "__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
color cyan "__attribute__[[:blank:]]*\(\([^)]*\)\)|__(aligned|asm|builtin|hidden|inline|packed|restrict|section|typeof|weak)__"
|
||||
|
||||
# Strings and names of included files.
|
||||
color brightyellow ""([^"]|\\")*"" "#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
||||
color brightyellow ""([^"]|\\")*"|#[[:blank:]]*include[[:blank:]]*<[^>]+>"
|
||||
|
||||
# Preprocessor directives.
|
||||
color brightcyan start="^[[:blank:]]*#[[:blank:]]*(if(n?def)?|elif|warning|error|pragma)\>" end="(\`|[^\])$"
|
||||
color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|endif|include(_next)?|line|undef)\>|$)"
|
||||
color brightcyan start="^[[:blank:]]*#[[:blank:]]*((el)?if(n?def)?|error|pragma|warning)\>" end="(\`|[^\])$"
|
||||
color brightcyan "^[[:blank:]]*#[[:blank:]]*((define|else|embed|endif|include(_next)?|line|undef)\>|$)"
|
||||
|
||||
# Comments.
|
||||
color brightblue "//.*"
|
||||
color brightblue "//[^"]*$|(^|[[:blank:]])//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
|
||||
# Reminders.
|
||||
|
||||
@@ -8,24 +8,24 @@ syntax changelog "Change[Ll]og[^/]*$"
|
||||
# Author lines.
|
||||
color green "^(19|20).*"
|
||||
# Dates.
|
||||
color red "^(19|20)[0-9-]{8}"
|
||||
color red "^(19|20)[[:digit:]-]{8}"
|
||||
# Email addresses.
|
||||
color yellow "<[^>]*@[^>]*>"
|
||||
|
||||
# Command-line options.
|
||||
color cyan "[[:blank:]]-[a-zA-Z\$]|--[8a-z-]+"
|
||||
color cyan "[[:blank:]]-[[:alpha:]$]|--[[:lower:]8-]+"
|
||||
# Bug and patch numbers.
|
||||
color cyan "(BZ|bug|patch)[ ]#[0-9]+|PR [[:alnum:]]+/[0-9]+"
|
||||
color cyan "(BZ|bug|patch) #[[:digit:]]+|PR [[:alnum:]]+/[[:digit:]]+"
|
||||
# Probable constants, for variety.
|
||||
color brightred "\<[A-Z_][0-9A-Z_]+\>"
|
||||
color brightred "\<[[:upper:]_][[:upper:][:digit:]_]+\>"
|
||||
# Key sequences.
|
||||
color brightblue "\^[A-Z^\]|\<M-.|\<F1?[0-9]|(\^|M-)Space"
|
||||
color brightblue "\^[[:upper:]\^_]|\<M-.|\<F1?[[:digit:]]|(\^|M-)Space"
|
||||
|
||||
# Changed files.
|
||||
color magenta start="^( | {8})\* " end="(:( |$)|^$)"
|
||||
|
||||
# Release markers.
|
||||
color brightblue "^(GNU )?nano[- ][0-9]\.[0-9]\.[^ ]+"
|
||||
color brightblue "^(GNU )?nano[- ][[:digit:]]\.[[:digit:]]\.[^ ]+"
|
||||
|
||||
# Trailing whitespace.
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
## Syntax highlighting for CMake files.
|
||||
|
||||
## Original author: Felipe Bugno
|
||||
|
||||
syntax cmake "(CMakeLists\.txt|\.cmake)$"
|
||||
comment "#"
|
||||
|
||||
color green "^[[:blank:]]*[0-9A-Za-z_]+"
|
||||
color green "^[[:blank:]]*[[:alnum:]_]+"
|
||||
icolor brightyellow "^[[:blank:]]*(include|include_directories|include_external_msproject)\>"
|
||||
|
||||
icolor brightgreen "^[[:blank:]]*((else|end)?if|else|(end)?while|(end)?foreach|break)\>"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
## Syntax highlighting for CSS files.
|
||||
|
||||
## Original author: Simon Rupf
|
||||
|
||||
syntax css "\.css$"
|
||||
comment "/*|*/"
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ comment "#"
|
||||
color ,red " + +"
|
||||
|
||||
# Nano's release motto, then name plus version.
|
||||
color italic,lime "\<[Nn]ano [1-6]\.[0-9][-.[:alnum:]]* "[^"]+""
|
||||
color brightred "\<(GNU )?[Nn]ano [1-6]\.[0-9][-.[:alnum:]]*\>"
|
||||
color italic,lime "\<[Nn]ano [1-9]\.[0-9][-.[:alnum:]]* "[^"]+""
|
||||
color brightred "\<(GNU )?[Nn]ano [1-9]\.[0-9][-.[:alnum:]]*\>"
|
||||
|
||||
# Dates
|
||||
color latte "\<[12][0-9]{3}\.(0[1-9]|1[012])\.(0[1-9]|[12][0-9]|3[01])\>"
|
||||
@@ -18,7 +18,7 @@ color latte "\<[12][0-9]{3}\.(0[1-9]|1[012])\.(0[1-9]|[12][0-9]|3[01])\>"
|
||||
color magenta "<[[:alnum:].%_+-]+@[[:alnum:].-]+\.[[:alpha:]]{2,}>"
|
||||
|
||||
# URLs.
|
||||
color lightblue "\<https?://\S+\.\S+[^[:space:],.)]"
|
||||
color lightblue "\<https?://\S+\.\S+[^])>[:space:],.]"
|
||||
|
||||
# Bracketed captions in certain config files.
|
||||
color brightgreen "^\[[^][]+\]$"
|
||||
@@ -26,5 +26,8 @@ color brightgreen "^\[[^][]+\]$"
|
||||
# Comments.
|
||||
color cyan "^[[:blank:]]*#.*"
|
||||
|
||||
# Make hard (non-breaking) spaces noticeable.
|
||||
color ,#444 " "
|
||||
|
||||
# Control codes.
|
||||
color orange "[[:cntrl:]]"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
## Syntax highlighting for Emacs Lisp.
|
||||
|
||||
syntax elisp "\.el$"
|
||||
magic "Lisp/Scheme program"
|
||||
comment ";"
|
||||
|
||||
# Basic functions/macros
|
||||
color brightcyan "\<(if|when|unless|cond|and|or|lambda|let|progn|while|dolist|dotimes)\>"
|
||||
color brightcyan "\<save-((window-)?excursion|restriction)\>"
|
||||
color brightcyan "\<eval-(and|when)-compile\>"
|
||||
# Defining functions
|
||||
color brightcyan "\<def(un|macro|subst|generic|alias)\>"
|
||||
color brightcyan "\<cl-def(un|macro|subst|generic|struct|type)\>"
|
||||
color brightcyan "\<define-(derived|minor|generic)-mode\>"
|
||||
# Defining variables
|
||||
color brightcyan "\<def(class|const|var(-local|alias)?)\>"
|
||||
# Customization functions
|
||||
color brightcyan "\<def(custom|face|group|theme)\>"
|
||||
# Setting values
|
||||
color brightcyan "\<(setq(-default|-local)?|setf|push|pop|declare(-function)?)\>"
|
||||
# Feature functions
|
||||
color brightcyan "\<(require|provide)\>"
|
||||
# Quoted symbols
|
||||
color brightyellow "#?'\<(\w|-)+\>"
|
||||
# Booleans
|
||||
color brightred "\<(t|nil)\>"
|
||||
# Keywords
|
||||
color blue ":(\w|[?-])+"
|
||||
# Strings
|
||||
color yellow start="^[[:blank:]]+"" end="[^\]""
|
||||
color yellow ""([^"\]|\\.)*""
|
||||
# Comments
|
||||
color cyan "(^|[[:blank:]]);.*"
|
||||
@@ -1,5 +1,7 @@
|
||||
## Syntax highlighting for Fortran 90/95.
|
||||
|
||||
## Original author: Pascal Gentil
|
||||
|
||||
syntax fortran "\.(f|for|f90|f95)$"
|
||||
comment "!"
|
||||
|
||||
@@ -10,7 +12,7 @@ icolor green "\<(append|asis|assign|assignment|associated|character|common)\>"
|
||||
icolor green "\<(complex|data|default|delim|dimension|double precision)\>"
|
||||
icolor green "\<(elemental|epsilon|external|file|fmt|form|format|huge)\>"
|
||||
icolor green "\<(implicit|include|index|inquire|integer|intent|interface)\>"
|
||||
icolor green "\<(intrinsic|iostat|kind|logical|module|none|null|only)>"
|
||||
icolor green "\<(intrinsic|iostat|kind|logical|module|none|null|only)\>"
|
||||
icolor green "\<(operator|optional|pack|parameter|pointer|position|private)\>"
|
||||
icolor green "\<(program|public|real|recl|recursive|selected_int_kind)\>"
|
||||
icolor green "\<(selected_real_kind|subroutine|status)\>"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
## Syntax highlighting for POV-Ray files.
|
||||
|
||||
## Original author: Donnie Berkholz
|
||||
|
||||
syntax pov "\.(pov|POV|povray|POVRAY)$"
|
||||
comment "//"
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
## Syntax highlighting for RPM spec files.
|
||||
|
||||
## Original author: Asterios Dramis
|
||||
|
||||
syntax spec "\.spec(\.[^/]+)?$"
|
||||
comment "#"
|
||||
|
||||
@@ -12,7 +14,9 @@ color brightblue "\<(AutoReq|AutoProv|AutoReqProv)[[:space:]]*:"
|
||||
color brightblue "\<(License|Copyright|Distribution|Vendor|Packager)[[:space:]]*:"
|
||||
color brightblue "\<((Source|Patch)[0-9]*|Nosource|Nopatch)[[:space:]]*:"
|
||||
# Architectures.
|
||||
color brightred "\<(i386|i486|i586|i686|athlon|ia64|alpha|alphaev5|alphaev56|alphapca56|alphaev6|alphaev67|sparc|sparcv9|sparc64armv3l|armv4b|armv4lm|ips|mipsel|ppc|ppciseries|ppcpseries|ppc64|m68k|m68kmint|Sgi|rs6000|i370|s390x?|noarch)\>"
|
||||
color brightred "\<((a|loong)arch64|alpha(ev(56?|67?)|pca56)?|amd64|armv(3l|4b|4l|5t(ej?)?l|6h?l|7(hn?)?l|8h?l)|athlon|em64t|geode|i370|i(3|4|5|6)86|ia32e|ia64|m68k(mint)?|mips(64)?(el|r6|r6el)?)\>"
|
||||
color brightred "\<(pentium(3|4)|ppc(32dy4|8260|8560)?|ppc64(le|p7)?|ppc(64)?(i|p)series|riscv64|rs6000|s390x?|sgi|sh(3|4|4a)?|sparc(64v?|v8|v9v?)?|x86_64(_v2|_v3|_v4)?|xtensa)\>"
|
||||
|
||||
# Architecture and OS conditionals.
|
||||
color brightred "%(ifarch|elifarch|ifnarch|ifos|elifos|ifnos)\>"
|
||||
# %* strings.
|
||||
|
||||
@@ -42,7 +42,7 @@ color brightblue "//.*"
|
||||
color brightblue start="/\*" end="\*/"
|
||||
|
||||
# Special comments.
|
||||
color brightcyan "//[[:blank:]]*\+build[[:blank:]]+(([a-zA-Z_0-9]+[[:blank:]]*)+,[[:blank:]]*)*[a-zA-Z_0-9]+"
|
||||
color brightcyan "//[[:blank:]]*\+build[[:blank:]]+(([[:alnum:]_]+[[:blank:]]*)+,[[:blank:]]*)*[[:alnum:]_]+"
|
||||
|
||||
# Trailing whitespace.
|
||||
color ,green "[[:space:]]+$"
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
## Syntax highlighting for groff.
|
||||
|
||||
syntax groff "\.(m[ems]|rof|tmac)$|/tmac\.[^/]+$"
|
||||
## Original author: Robert D. Goulding
|
||||
|
||||
syntax groff "\.(me|mm|mom|ms|roff|tmac)$|/tmac\.[^/]+$"
|
||||
comment ".\""
|
||||
|
||||
# The argument of .ds or .nr
|
||||
# The setting of a string or register
|
||||
color cyan "^\.(ds|nr) [^[:space:]]*"
|
||||
# Single-character escapes
|
||||
color brightmagenta "\\."
|
||||
# The argument of \f or \s in the same color
|
||||
color brightmagenta "\\f(.|\(..)" "\\s(\+|\-)?[0-9]"
|
||||
# Newlines
|
||||
color brightmagenta "\\f(.|\(..)|\\s(\+|\-)?[0-9]"
|
||||
# References to registers
|
||||
color cyan "\\(\\)?n(.|\(..)"
|
||||
color cyan start="\\(\\)?n\[" end="]"
|
||||
# Requests
|
||||
color brightgreen "^\.[[:blank:]]*[^[:space:]]*"
|
||||
# Comments
|
||||
color yellow "^\.\\".*"
|
||||
# Strings
|
||||
color yellow "(^\\#|(^\.)?\\").*"
|
||||
# References to strings
|
||||
color green "\\(\\)?\*(.|\(..)"
|
||||
color green start="\\(\\)?\*\[" end="]"
|
||||
# Characters
|
||||
# Special characters
|
||||
color brightred "\\\(.."
|
||||
color brightred start="\\\[" end="]"
|
||||
# Macro arguments
|
||||
color brightcyan "\\\\\$[1-9]"
|
||||
color brightcyan "\\\\\$[0-9]"
|
||||
|
||||
@@ -1,23 +1,30 @@
|
||||
## Syntax highlighting for Guile Scheme.
|
||||
|
||||
syntax guile "\.scm$"
|
||||
## Original authors: Mark Oteiza and Benno Schulenberg
|
||||
## License: GPL version 3 or newer
|
||||
|
||||
syntax guile "\.(scm|sld|sls|ss)$"
|
||||
header "^#!.*guile"
|
||||
comment ";"
|
||||
|
||||
# Basic scheme functions
|
||||
color green "\<(do|if|lambda|let(rec)?|map|unless|when)\>"
|
||||
# Basic syntax
|
||||
color lightgreen "\<((and|begin|case|cond|do|else|if|lambda|let(rec)?|or|quote|unless|when)\>|let\*|set!)"
|
||||
# Basic procedures
|
||||
color lightcyan "\<((append|apply|c[ad]{1,4}r|cons|display|for-each|list|map|newline)\>|reverse(\>|!)|set-c[ad]r!)"
|
||||
color lightcyan "\<(boolean|char(-ci)?[<>]?=?|complex|eqv?|even|integer|list|nan|negative|null|number|odd|pair|positive|rational|real|string|symbol|vector|zero)\?"
|
||||
color lightcyan "\<(abs|a?(cos|sin|tan)|ceiling|exp|floor|max|min|modulo|not|random|round|quotient|sqrt|square|truncate)\>"
|
||||
# Defining things
|
||||
color brightcyan "\<define(-macro|-module|-public|-syntax)?\>"
|
||||
color brightgreen "\<define(-macro|-module|-public|-syntax)?\>"
|
||||
# Quoted symbols
|
||||
color brightyellow "'\<(\w|-)+\>"
|
||||
# Chars
|
||||
color lightyellow "'(\w|[!$%&*+/:<=>?@^_~])(\w|[!$%&*+/:<=>?@^_~.0-9-])*"
|
||||
# Characters
|
||||
color brightmagenta "#\\(.|\w+)"
|
||||
# Booleans
|
||||
color brightred "(#t|#f)\>"
|
||||
color brightred "#(t|true|f|false)\>"
|
||||
# Keywords
|
||||
color blue "#?:(\w|[?-])+"
|
||||
color lagoon "#?:(\w|[?-])+"
|
||||
# Strings
|
||||
color yellow start="^[[:blank:]]+"" end="[^\]""
|
||||
color yellow start="^[[:blank:]]*"([^"\]|\\.)*$" end="(^|[^\]|[^\]\\\\)""
|
||||
color yellow ""([^"\]|\\.)*""
|
||||
# Comments
|
||||
color cyan "(^|[[:blank:]]);.*"
|
||||
color italic,#aaa "(^|[[:blank:]]);.*"
|
||||
|
||||
@@ -8,8 +8,8 @@ formatter tidy -m -q
|
||||
|
||||
# Tags:
|
||||
color cyan "<[[:alpha:]/!?][^>]*>"
|
||||
# Bold, italic, and underlined:
|
||||
color brightmagenta "</?[biu]>"
|
||||
# Bold, italic, underlined, emphasis, and importance:
|
||||
color brightmagenta "</?(b|i|u|em|strong)>"
|
||||
|
||||
# Named character references:
|
||||
color red "&[^;[:space:]]*;"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user