├── .gitignore
├── LICENSE
├── README.org
├── README_CN.org
├── screenshot.png
├── sniem-cheatsheet.el
├── sniem-common.el
├── sniem-linked-file.el
├── sniem-macro.el
├── sniem-mark-jump.el
├── sniem-object-catch.el
├── sniem-operation.el
├── sniem-var.el
└── sniem.el
/.gitignore:
--------------------------------------------------------------------------------
1 | todo.org
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | sniem Copyright (C) 2021 SpringHan
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/README.org:
--------------------------------------------------------------------------------
1 | * Sniem
2 | [[file:README_CN.org][中文文档]]
3 | ** Screenshot
4 | [[file:screenshot.png]]
5 | ** Dependences
6 | - ~s~
7 | - ~dash~
8 | ** Installation
9 | #+begin_src emacs-lisp
10 | (use-package
11 | sniem
12 | :init (global-sniem-mode t)
13 | :config
14 | (sniem-set-keyboard-layout 'qwerty))
15 | #+end_src
16 | ** What is sniem
17 | Sniem means Hands-eased United Editing Method,it's a new editing method for Emacs.
18 | ** Features
19 | - ~last-point~
20 |
21 | ~last-point~ is a thing that through all motions and most of operations. Like its name, when execute any motions, the last position will be set to ~last-point~.
22 |
23 | - ~leader-key~
24 |
25 | Sniem has leader key,the key of leader map can be set by ~(sniem-leader-set-key)~. And you can use ~(sniem-set-leader-key)~ to set the key of leader.
26 | #+begin_src emacs-lisp
27 | (sniem-leader-set-key
28 | "d" 'sniem-digit-argument-or-fn
29 | "D" 'dired)
30 | (sniem-set-leader-key ",")
31 | #+end_src
32 |
33 | - Modes
34 |
35 | Sniem has 5 modes.
36 | - ~NORMAL~: This mode is the default mode for the editing buffers.
37 |
38 | You can use ~(sniem-normal-set-key)~ to set keys for normal mode. Its usage is same as ~(sniem-leader-set-key)~.
39 |
40 | - ~INSERT~: This mode will be used when you executed ~sniem-insert~ in ~NORMAL~ mode. It's used to edit. In this mode, there's only one binding for ~sniem~, that is ~~ which will make you exit ~INSERT~ mode back to ~NORMAL~ mode.
41 |
42 | - ~MOTION~: This mode is used in special modes, there's only has one binding for ~sniem~, that is ~~ which can let you use leader keys.
43 |
44 | - ~EXPAND~: This mode is used to expand region more comfortablely.
45 |
46 | You can use ~(sniem-expand-set-key)~ to set keys for normal mode. Its usage is same as ~(sniem-leader-set-key)~.
47 |
48 | | Key | Function |
49 | | ~RET~ | Call the object-catch function |
50 | | ~TAB~ | sniem-shift |
51 | | ~r~ | Repeat the object-catch |
52 | | ~p~ | Catch the parent pair of the content selected |
53 | | ~b~ | Catch pair by its prefix char |
54 | | ~B~ | Catch the parent pair of the content selected by its prefix char |
55 | | ~o~ | Catch ~()~ pair |
56 | | ~O~ | Catch parent ~()~ pair for the content selected |
57 | | ~s~ | Catch ~[]~ pair |
58 | | ~S~ | Catch parent ~[]~ pair for the content selected |
59 | | ~c~ | Catch ~{}~ pair |
60 | | ~C~ | Catch parent ~{}~ pair for the content selected |
61 | | ~q~ | Catch ~''~ pair |
62 | | ~Q~ | Catch parent ~''~ pair for the content selected |
63 | | ~d~ | Catch ~""~ pair |
64 | | ~D~ | Catch parent ~""~ pair for the content selected |
65 | | ~a~ | Catch ~<>~ pair |
66 | | ~A~ | Catch parent ~<>~ pair for the content selected |
67 | | ~/~ | Reverse the direction of catch |
68 | | Other alpha keys | Quit expand mode and goto NORMAL mode |
69 |
70 | - ~MINIBUFFER-KEYPAD~: This mode allows you to use keypad in any minibuffers.
71 |
72 | When you're in a minibuffer, you can input as usual. But when you input space in twice time, the keypad mode will be opened. And you can input space twice to exit keypad mode.
73 |
74 | - Keyboard layout
75 |
76 | Sniem provides supports for the mainly 4 layouts,you can use ~(sniem-set-keyboard-layout)~ to set.
77 | #+begin_src emacs-lisp
78 | (sniem-set-keyboard-layout 'qwerty)
79 | (sniem-set-keyboard-layout 'colemak)
80 | (sniem-set-keyboard-layout 'dvorak)
81 | (sniem-set-keyboard-layout 'dvp) ;For Dvorak Programmer
82 | #+end_src
83 | After you set the keyboard layout, Sniem will set the default keys in ~NORMAL~ mode accroding to your layout, then create the cheatsheet.
84 |
85 | - Keypad
86 |
87 | Sniem provides the Keypad function, After you execute the Keypad, When you press: , is ~C-~ , . is ~M-~ , / is ~C-M-~ . After you press ~~, it will reture the next key itself which you press.
88 |
89 | - middle-keyboard-digit-argument-or-function
90 |
91 | This function is defaultly bound on ~~. After you execute it, the middle keys of the keyboard can be instead of numbers and ~-~, the record will be over after you pressed ~~. You can also use the keys in the table to do the special operations:
92 | | Key | Function |
93 | | , | Repeat object-catch |
94 | | . | Mark the content at point or a region |
95 | | k | Unmark the content and select it |
96 | | K | Pop the newest marked-content |
97 | | SPC | Execute function in motion-hint |
98 | | / | Reverse the direction of object-catch |
99 | | p | Add, change or delete the pair of region |
100 | | < | Jump to prev comment mark |
101 | | > | Jump to next comment mark |
102 | | m | Insert new comment mark |
103 | | c | Clear the special clipboard |
104 | | x | Pop the newest content in special clipboard |
105 | | P | Paste from special clipboard |
106 | | y | Yank for special clipboard |
107 | | Y | Yank in region for special clipboard |
108 |
109 | - ~(sniem-shift)~
110 |
111 | This function normally be binded to ~TAB~ in some mode's keymaps. (Expect the insert mode keymap)
112 | And there's a motion list (called ~shift-motion-list~ at below) which be linked to this function, it's: ~sniem-forward-char~, ~sniem-backward-char~, ~sniem-next-line~, ~sniem-prev-line~, ~sniem-next-word~, ~sniem-prev-word~, ~sniem-scroll-up-command~.
113 | Then, there're three conditions you execute this function.
114 |
115 | 1. Press ~TAB~ (The key which binds ~sniem-shift~ ) once
116 |
117 | When you just press once, this function is a replacement of shift.
118 | e.g.: You can execute the command of ~K~ by execute ~sniem-shift~ & ~k~ .
119 | Defaultly, it can be ~TAB k~ .
120 |
121 | But when you pressed a capital letter key after executing the function, in addition, the command of its lower case letter is a motion in ~shift-motion-list~ , the motion will be added or deleted from the motion-shift-locked key list.
122 |
123 | 2. Press twice
124 |
125 | When you execute it twice, it'll enter the motion-shift-locked mode. In this case, when you press the key of motions included in ~shift-motion-list~ , it will execute the motion of its capital letter key.
126 | And normally, only the first four motions of ~shift-motion-list~ are the in the motion-shift-locked mode key list. If you want to add or delete a motion from this mode, you just need to press its capital letter key.
127 | You can exit motion-shift-locked mode by press it twice.
128 |
129 | 3. Press three times
130 |
131 | In this case, it will enter the Caps_Lock mode only in sniem insert mode. The effect is just like ~caps-lock~ (another package). You can press 3 times to exit this mode.
132 | ** Some special operations
133 | - Motions
134 |
135 | - ~(sniem-goto-prev)~ & ~(sniem-goto-next)~
136 |
137 | Use ~middle-keyboard~ to get the lines to forward or backward, then execute it.
138 |
139 | - ~(sniem-next-word)~ & ~(sniem-prev-word)~
140 |
141 | Normally, goto the next or previous word. If there is a content selected, goto the next or previous content same as it.
142 |
143 | - ~(sniem-goto-last-point)~
144 |
145 | Normally, goto the ~last-point~. If the ~sniem-mark-content~ is exists, goto the ~mark-content~.
146 |
147 | - ~(sniem-beginning-of-line)~
148 |
149 | Normally, goto the beginning of current line. If the cursor is at beginning now, execute indentation function.
150 |
151 | - Editing operations
152 |
153 | - operation-about-last-point
154 |
155 | Most of the editing operations is related to ~last-point~ (Without ~(sniem-paste)~).
156 | - You can press ~p~ after the operations to execute it with ~last-point~.
157 | - ~(sniem-lock-unlock-last-point)~
158 | Lock or unlock the ~last-point~. When it is locked, it will display in the buffer.
159 |
160 | - operation-in-region
161 |
162 | All of the operations which are end with ~-in-region~ will edit the area from the forward point of the start of region to the backward point of the end of the region.
163 |
164 | - ~object-catch~
165 |
166 | Sniem provides functions to get the object smartly: ~object-catch~.
167 | - ~~
168 |
169 | Get the closest pair to cursor.
170 |
171 | - ~~
172 |
173 | Get the parent pair of the selected pair.
174 |
175 | - ~~
176 |
177 | Input the char of the pair, then get the closest to cursor.
178 |
179 | - ~~
180 |
181 | Input the char of the pair, then get the parent of the selected pair.
182 |
183 | - ~(~ & ~[~ & ~{~
184 |
185 | Quickly get the pair.
186 |
187 | - ~(sniem-paste)~
188 |
189 | Defaultly, press ~p~ to enter the interface of the ~sniem-paste~. Then you can use ~n~ & ~p~ to flip. You can paste the first content when you press ~p~ in the first page.
190 | ~[1-9]~ to select the content.
191 |
192 | - ~(sniem-macro)~
193 |
194 | Sniem provides some great kmacro functions.
195 | - Basic
196 |
197 | ~q~ for record, ~e~ for execution, ~n~ to name the last kmacro, ~l~ for lock or unlock the macro, ~.~ for forcibly lock macro, ~c~ for call macro.
198 |
199 | - Advance
200 |
201 | - When you record after selecting some lines, the kmacro will be executed to all the lines you selected after recording.
202 | - If you record after selecting content in the same line, the content will be recorded. Then you can execute ~(sniem-next-word)~ or ~(sniem-prev-word)~ to goto the next or previous content same as it. Execute ~(keyboard-quit)~ can cancel the content record.
203 |
204 | - ~(sniem-search)~
205 |
206 | Normally, searching the original content you input.
207 | When you give it prefix argument, the content will be packed with regexp for finding symbol automatically.
208 |
209 | - ~(sniem-mark) Expand~
210 |
211 | When you use this function to mark symbol, if there're some ~expand~ attachment of current mode in ~sniem-mark-attachments~ (*custom* part will introduce it) around current selection, you can execute mark function again to expand selection.
212 |
213 | For example, when you writing Python, you can execute mark function (mark symbol) twice to select ~self.test~ .
214 |
215 | - sniem-mark-jump
216 |
217 | sniem-mark-jump provides two motions. They are ~(sniem-mark-jump-next)~ & ~(sniem-mark-jump-prev)~.
218 | Normally, execute them can goto the next or previous comment mark. But if you use them with ~digit-argument~, they'll find the next or previous comment mark with type which is the number you input of the mark type alist.
219 | ** Custom
220 | - ~sniem-center-message~ & ~sniem-mark-message~ , etc.
221 |
222 | Theses variables are the help message for their operations. If you don't want them, you can execute this function:
223 | #+begin_src emacs-lisp
224 | (setq sniem-center-message nil
225 | sniem-mark-message nil
226 | sniem-delete-message nil
227 | sniem-change-message nil
228 | sniem-yank-message nil
229 | sniem-macro-message nil
230 | sniem-pair-message nil)
231 | #+end_src
232 |
233 | - ~sniem-xxx-mode-cursor~
234 |
235 | The ~xxx~ can be: ~normal~, ~insert~, ~motion~.
236 |
237 | - ~sniem-motion-hint-sit-time~
238 |
239 | This is the sit time for motion hint. Default is ~1~.
240 |
241 | - State Hint
242 |
243 | If you use [[https://github.com/manateelazycat/awesome-tray][awesome-tray]], sniem will automaticly set ~(sniem-state)~ to the alist, so you can use it.
244 | Otherwise, you can set the state hint accroding to your modeline.
245 |
246 | If you use the default modeline, you can try this:
247 | #+begin_src emacs-lisp
248 | (setq-default mode-line-format (append '((:eval (sniem-state))) mode-line-format))
249 | (force-mode-line-update)
250 | #+end_src
251 |
252 | - sniem-mark-jump
253 |
254 | - ~sniem-mark-jump-author-name~
255 |
256 | This is the author name for the comment mark.
257 |
258 | - ~sniem-mark-jump-author-name-enable~
259 |
260 | This variable is the status of the author name's enablement.
261 |
262 | - ~sniem-mark-attachments~
263 |
264 | When marking symbol, sniem will try getting attachment from this variable. If the pair under cursor is in this variable, it will be regarded as a part of symbol.
265 | To set this variable, you can use function ~(sniem-mark-set-attachment)~ .
266 | e.g.:
267 | #+begin_src emacs-lisp
268 | (sniem-mark-set-attachment 'global "_")
269 | (sniem-mark-set-attachment 'emacs-lisp-mode "<" ">")
270 | (sniem-mark-set-attachment
271 | 'c-mode
272 | :expand '("::")
273 | ;; Normally, if the expand attachment is one char, it will only work for once.
274 | ;; But if you set it to more chars, the attachment will work like a normal attachment.
275 | )
276 | (sniem-mark-set-attachment
277 | 'python-mode
278 | :expand '(".") ;For expand
279 | )
280 | #+end_src
281 |
282 | - ~sniem-object-catch-global-symbol-alist~
283 |
284 | This variable is the list of pairs which can be catched. And this variable can also provide pair info to ~(sniem-mark)~ & ~(sniem-pair)~ .
285 | This variable includes some global pairs and some pairs for specific modes.
286 |
287 | You can set this by ~(add-to-list)~ to add global pairs or ~(sniem-object-catch-mode-defalist)~ to set for certain mode.
288 | e.g.:
289 | #+begin_src emacs-lisp
290 | (add-to-list 'sniem-object-catch-global-symbol-alist '("^" . "^"))
291 |
292 | (sniem-object-catch-mode-defalist emacs-lisp-mode
293 | ("`" . "'")
294 | ("'" . "")) ;Set the back-pair to empty string, means to remove it from pair-list
295 | #+end_src
296 |
--------------------------------------------------------------------------------
/README_CN.org:
--------------------------------------------------------------------------------
1 | * Sniem
2 | [[file:README.org][English Doc]]
3 | ** 截图
4 | [[file:screenshot.png]]
5 | ** 依赖
6 | - ~s~
7 | - ~dash~
8 | ** 安装
9 | #+begin_src emacs-lisp
10 | (use-package
11 | sniem
12 | :init (global-sniem-mode t)
13 | :config
14 | (sniem-set-keyboard-layout 'qwerty))
15 | #+end_src
16 | ** 什么是 sniem
17 | Sniem 全称 Hands-eased United Editing Method,是一款新的编辑模式
18 | ** 特性
19 | - ~last-point~
20 |
21 | ~last-point~ 是 sniem 中贯穿所有动作和几乎所有操作的概念,如其名,当执行任意动作时,一般情况下执行前的那个位置会被设置为 ~last-point~
22 |
23 | - ~leader-key~
24 |
25 | Sniem 自带 leader key,leader map 的按键可通过 ~(sniem-leader-set-key)~ 来设置。也可通过 ~(sniem-set-leader-key)~ 来设置 leader 的按键。
26 | #+begin_src emacs-lisp
27 | (sniem-leader-set-key
28 | "d" 'sniem-digit-argument-or-fn
29 | "D" 'dired)
30 | (sniem-set-leader-key ",")
31 | #+end_src
32 |
33 | - Modes
34 |
35 | Sniem 有以下几个模式
36 | - ~NORMAL~
37 |
38 | 一般情况下的模式,此模式下绑定了许多按键,可通过 ~(sniem-cheatsheet)~ 或者 ~?~ 键来查看绑定的按键。可通过 ~(sniem-normal-set-key)~ 来绑定按键,用法与 ~(sniem-leader-set-key)~ 相同。
39 |
40 | - ~INSERT~
41 |
42 | 此模式下 ~~ (可通过 ~(sniem-set-quit-insert-key)~ 设置) 按键会被绑定为 ~(sniem-quit-insert)~ 以退出此模式 ,其它按键都是 ~global-map~ 里的按键
43 |
44 | - ~MOTION~
45 |
46 | 与 ~INSERT~ 模式相同,除了 ~~ 键被绑定为 leader,其它按键都是原本的按键。(原来的空格键被绑定为了 ~ ~)
47 |
48 | - ~EXPAND~
49 |
50 | 这个模式使扩展选中区域更舒适。
51 |
52 | 可通过 ~(sniem-expand-set-key)~ 来绑定按键,用法与 ~(sniem-leader-set-key)~ 相同。
53 |
54 | | Key | Function |
55 | | ~RET~ | 调用 object-catch |
56 | | ~TAB~ | sniem-shift |
57 | | ~r~ | 重复上一次的 object-catch |
58 | | ~p~ | 抓取当前选中内容的父级 pair |
59 | | ~b~ | 获取 pair 通过其前缀字符 |
60 | | ~B~ | 获取当前选中内容的父级 pair 通过其前缀字符 |
61 | | ~o~ | 获取 ~()~ pair |
62 | | ~O~ | 获取当前选中内容的父级 ~()~ pair |
63 | | ~s~ | 获取 ~[]~ pair |
64 | | ~S~ | 获取当前选中内容的父级 ~[]~ pair |
65 | | ~c~ | 获取 ~{}~ pair |
66 | | ~C~ | 获取当前选中内容的父级 ~{}~ pair |
67 | | ~q~ | 获取 ~''~ pair |
68 | | ~Q~ | 获取当前选中内容的父级 ~''~ pair |
69 | | ~d~ | 获取 ~""~ pair |
70 | | ~D~ | 获取当前选中内容的父级 ~""~ pair |
71 | | ~a~ | 获取 ~<>~ pair |
72 | | ~A~ | 获取当前选中内容的父级 ~<>~ pair |
73 | | ~/~ | 反转抓取的方向 |
74 | | 其它字母、负号按键 | 切换到 NORMAL 模式 |
75 |
76 | - ~MINIBUFFER-KEYPAD~
77 |
78 | 此模式下允许用户在 minibuffer 中使用 keypad 。
79 | 当你打开 minibuffer 之后,你可以正常输入。但当你按下两次空格之后,就会进入 keypad 模式;再次按两次空格就会退出 keypad 模式。
80 |
81 | - Keyboard layout
82 |
83 | Sniem 针对目前主流的四种键盘布局提供了支持,可通过 ~(sniem-set-keyboard-layout)~ 来设置
84 | #+begin_src emacs-lisp
85 | (sniem-set-keyboard-layout 'qwerty)
86 | (sniem-set-keyboard-layout 'colemak)
87 | (sniem-set-keyboard-layout 'dvorak)
88 | (sniem-set-keyboard-layout 'dvp) ;For Dvorak Programmer
89 | #+end_src
90 | 在设置了键盘布局之后,Sniem 会根据键盘布局来设置 ~NORMAL~ 模式下的默认按键,并生成当前布局的 cheatsheet
91 |
92 | - Keypad
93 |
94 | Sniem 提供 Keypad 支持,进入 Keypad 之后: , 为 ~C-~ , . 为 ~M-~ , / 为 ~C-M-~ ;按下空格再按上面这几个键,则是它们本身。
95 |
96 | - middle-keyboard-digit-argument-or-function
97 |
98 | 此功能默认绑定在 ~~ 键上。执行后,可通过键盘中间的键来分别代替数字键和减号,回车即录入完毕;也可按下以下键来进行特殊操作:
99 | | Key | function |
100 | | , | 重复 object-catch |
101 | | . | 标记当前光标下内容或区域 |
102 | | k | 解除当前光标下内容的标记并选中 |
103 | | K | 解除最新标记内容 |
104 | | SPC | 执行 motion-hint |
105 | | / | 反转 object-catch 方向 |
106 | | p | 添加,更改或删除当前选中内容的 pair |
107 | | < | 跳转到下一个 comment mark |
108 | | > | 跳转到上一个 comment mark |
109 | | m | 插入新的 comment mark |
110 | | c | 清空特殊剪贴板 |
111 | | x | 删除特殊剪贴板最新的内容 |
112 | | P | 从特殊剪贴板粘贴 |
113 | | y | 复制内容至特殊剪贴板 |
114 | | Y | 以 in-region 方式复制内容至剪贴板 |
115 |
116 | - ~(sniem-shift)~
117 |
118 | 这个函数默认在各个模式中被绑定于 ~TAB~ 。(除了 insert mode keymap)
119 | 它提供了一个行为列表(下面称为 ~shift-motion-list~ ),它包括: ~sniem-forward-char~, ~sniem-backward-char~, ~sniem-next-line~, ~sniem-prev-line~, ~sniem-next-word~, ~sniem-prev-word~, ~sniem-scroll-up-command~.
120 | 你执行它的时候有三种情况。
121 |
122 | 1. 按 ~TAB~ (绑定了该函数的键) 一次
123 |
124 | 当你只按下一次,这个函数就为 shift 键的代替。
125 | 例如:你可以使用 ~TAB k~ 执行 ~K~ 键的命令。
126 | 但如果你按下后又按下了一个大写字母的键,且该字母的小写字母所绑定的命令属于 ~shift-motion-list~ ,这个行为会被加入或删除于 motion-shift-locked 按键列表。
127 |
128 | 2. 按两次
129 |
130 | 当你按下两次,就会进入 motion-shift-locked mode。这样,当你按下属于 ~shift-motion-list~ 的键时,将会执行其大写键所绑定的行为。
131 | 一般的,只有 ~shift-motion-list~ 前四个会被自动加入 motion-shift-locked 按键列表中。如果你想把 motion 加入或从中删除,按其大写键即可。
132 | 你可以通过再次按两下 ~TAB~ 退出 motion-shift-locked mode。
133 |
134 | 3. 按三下
135 |
136 | 这样会在 ~sniem-insert-mode~ 进入大写锁定模式。效果与 ~caps-lock~ 这个包相同。再按三下退出该模式。
137 | ** 一些特殊操作
138 |
139 | - 移动
140 |
141 | - ~(sniem-goto-prev)~ & ~(sniem-goto-next)~
142 | 使用 ~middle-keyboard~ 来获取前进或后退的行数,并执行
143 |
144 | - ~(sniem-next-word)~ & ~(sniem-prev-word)~
145 | 一般情况下,跳转到下一个词或者上一个词。如果有内容被选中,则跳转到下一个或上一个与选中内容相同的位置
146 |
147 | - ~(sniem-goto-last-point)~
148 | 一般情况下,跳转到 ~last-point~ 的位置。如果有内容被记录,则跳转到其第一个字符。
149 |
150 | - ~(sniem-beginning-of-line)~
151 |
152 | 一般情况下,跳转到行首。如果光标已经在行首,则对当前行缩进。
153 |
154 | - 编辑操作
155 |
156 | - operation-about-last-point
157 |
158 | Sniem 中几乎所有编辑操作都与 ~last-point~ 有关 (除了 ~(sniem-paste)~)
159 | - 上述的编辑操作只需按下 ~p~ 即可进行与 ~last-point~ 有关的操作
160 | - ~(sniem-lock-unlock-last-point)~
161 | 将 ~last-point~ 锁定或者解除锁定,此时任何移动都不会改变其值。如果被锁定了,会在当前 buffer 显示出来。
162 |
163 | - operation-in-region
164 |
165 | 所有以 ~-in-region~ 为结尾的操作,都是在 region 中对其开头的后一个位置到结尾的前一个位置进行编辑
166 |
167 | - ~object-catch~
168 |
169 | Sniem 提供了一个智能获取 object 的功能, ~object-catch~ 。此源于本人用 ~evil~ 的时候写的一个插件: ~evil-wildfire~ 。
170 | - ~~
171 |
172 | 按下此键即可选取离光标最近的 pair
173 |
174 | - ~~
175 |
176 | 按下此键会选取当前选中的 pair 的父级 pair
177 |
178 | - ~~
179 |
180 | 按下此键后,输入所需 pair ,然后即可选取离光标最近的 pair
181 |
182 | - ~~
183 |
184 | 按下此键后,输入所需 pair ,然后会选取当前所选的父级 pair
185 |
186 | - ~(~ & ~[~ & ~{~
187 |
188 | 可用于快速选取指定 pair
189 |
190 | - ~(sniem-paste)~
191 |
192 | Sniem 的粘贴有些许不同,默认按下 ~p~ 键后进入粘贴面板,随后可用 ~n~ & ~p~ 进行翻页,如果在第一页按下 ~p~ ,则粘贴第一个结果。
193 | 可用数字键对内容进行选择
194 |
195 | - ~(sniem-macro)~
196 |
197 | Sniem 为键盘宏提供了一些不错的功能。
198 | - 基本功能
199 |
200 | ~q~ 录制, ~e~ 执行, ~n~ 为最后一个宏命名, ~l~ 锁定或者解除锁定宏, ~.~ 强制锁定宏, ~c~ 调用宏。
201 |
202 | - 进阶功能
203 |
204 | - 在选中多行的情况下录制,在录制完之后会对所选的每一行执行一遍
205 | - 在选中同行的内容后录制,在录制完之后会记录下内容,此时执行 ~(sniem-next-word)~ 或者 ~(sniem-prev-word)~ 即跳转到此内容,按下 ~C-g~ 可取消内容锁定
206 |
207 | - ~(sniem-search)~
208 |
209 | 一般情况下,搜索你输入的原生内容。
210 | 当你给其 prefix argument 时,它将给你自动添加匹配 symbol 的正则表达式。
211 |
212 | - ~(sniem-mark) Expand~
213 |
214 | 当你使用该函数来选择 symbol 时,如果当前选择周围有属于 ~sniem-mark-attachments~ expand 的字符,你就可以再次执行选择命令来扩展你的选择。
215 |
216 | 例如,当你编辑 Python 文件时,你可以通过连续执行两次选择命令(mark symbol)来选择 ~self.test~ 。
217 |
218 | - sniem-mark-jump
219 |
220 | sniem-mark-jump 提供了两个 motions,即 ~(sniem-mark-jump-next)~ & ~(sniem-mark-jump-prev)~ 。
221 | 一般情况下,执行它们会跳转到上一个或者下一个 comment mark。但如果你使用了 ~digit-argument~ ,它们将跳转到上一个或下一个指定类型的 comment mark,此类型是以你所使用的 ~digit-argument~ 为索引向类型列表里获取到的结果。
222 | ** 自定义
223 | - ~sniem-center-message~ & ~sniem-mark-message~ , etc.
224 |
225 | 这些变量是其操作的帮助信息。如果你不想要它们,可以执行一下语句:
226 | #+begin_src emacs-lisp
227 | (setq sniem-center-message nil
228 | sniem-mark-message nil
229 | sniem-delete-message nil
230 | sniem-change-message nil
231 | sniem-yank-message nil
232 | sniem-macro-message nil
233 | sniem-pair-message nil)
234 | #+end_src
235 |
236 | - ~sniem-xxx-mode-cursor~
237 |
238 | ~xxx~ 可以是: ~normal~, ~insert~, ~motion~
239 |
240 | - ~sniem-motion-hint-sit-time~
241 |
242 | 这是动作提示的显示时间,默认为 ~1~
243 |
244 | - 模式提示
245 |
246 | 如果你使用 [[https://github.com/manateelazycat/awesome-tray][awesome-tray]], sniem 将自动把 ~(sniem-state)~ 添加到指定列表,供你使用。
247 | 或者,你可以根据你的 modeline 来设置模式提醒。
248 |
249 | 如果你使用的是默认的 modeline, 你可以尝试以下方案:
250 | #+begin_src emacs-lisp
251 | (setq-default mode-line-format (append '((:eval (sniem-state))) mode-line-format))
252 | (force-mode-line-update)
253 | #+end_src
254 |
255 | - sniem-mark-jump
256 |
257 | - ~sniem-mark-jump-author-name~
258 |
259 | 这是 comment mark 中的人名。
260 |
261 | - ~sniem-mark-jump-author-name-enable~
262 |
263 | 这是当前人名的启用状态。
264 |
265 | - ~sniem-mark-attachments~
266 |
267 | 当你选择 symbol 的时候,它会尝试从该变量中获取连接符 。如果光标下的字符处于这个变量中,它将会被视为 symbol 的一部分。
268 | 你可以使用 ~(sniem-mark-set-attachment)~ 来设置该变量。
269 | 实例:
270 | #+begin_src emacs-lisp
271 | (sniem-mark-set-attachment 'global "_")
272 | (sniem-mark-set-attachment 'emacs-lisp-mode "<" ">")
273 | (sniem-mark-set-attachment
274 | 'c-mode
275 | :expand '("::")
276 | ;; Normally, if the expand attachment is one char, it will only work for once.
277 | ;; But if you set it to more chars, the attachment will work like a normal attachment.
278 | )
279 | (sniem-mark-set-attachment
280 | 'python-mode
281 | :expand '(".") ;For expand
282 | )
283 | #+end_src
284 |
285 | - ~sniem-object-catch-global-symbol-alist~
286 |
287 | 这个变量包含能够被“抓取”的 pair ,它也为 ~(sniem-mark)~ & ~(sniem-pair)~ 提供 pair 信息。
288 | 该变量包括全局 pair 和一些具体 mode 的 pair 。
289 |
290 | 你可以使用 ~(add-to-list)~ 来设置全局 pair ,或者使用 ~(sniem-object-catch-mode-defalist)~ 设置具体 mode 的 pair 。
291 | 实例:
292 | #+begin_src emacs-lisp
293 | (add-to-list 'sniem-object-catch-global-symbol-alist '("^" . "^"))
294 |
295 | (sniem-object-catch-mode-defalist emacs-lisp-mode
296 | ("`" . "'")
297 | ("'" . "")) ;Set the back-pair to empty string, means to remove it from pair-list
298 | #+end_src
299 |
--------------------------------------------------------------------------------
/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SpringHan/sniem/89161d8b3c19ffba8b52411de36f28aec1e401f2/screenshot.png
--------------------------------------------------------------------------------
/sniem-cheatsheet.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-cheatsheet.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method.
25 |
26 | ;;; Code:
27 |
28 | (require 's)
29 | (require 'dash)
30 | (require 'sniem-var)
31 |
32 | (defconst sniem-cheatsheet-layout-qwerty
33 | " Cheatsheet For Qwerty
34 |
35 | ┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━━━━┓
36 | ┃ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ DEL ┃
37 | ┃ [~]| [!]| [@]| [#]| [$]| [%]| [^]| [&]| [*]| [(]| [)]| [_]| [+]| ┃
38 | ┠─┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [DEL]┃
39 | ┃ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ ┃
40 | ┃ [`]| [1]| [2]| [3]| [4]| [5]| [6]| [7]| [8]| [9]| [0]| [-]| [=]| ┃
41 | ┠─────────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────────┨
42 | ┃ TAB │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | ┃
43 | ┃ | [Q]| [W]| [E]| [R]| [T]| [Y]| [U]| [I]| [O]| [P]| [{]| [}]| [|]┃
44 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┨
45 | ┃ │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ [ │ ] │ \\ ┃
46 | ┃ | [q]| [w]| [e]| [r]| [t]| [y]| [u]| [i]| [o]| [p]| [[]| []]| [\\]┃
47 | ┠─────────────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─────────┨
48 | ┃ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ \" │ RET ┃
49 | ┃ | [A]| [S]| [D]| [F]| [G]| [H]| [J]| [K]| [L]| [:]| [\"]│ ┃
50 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [RET]┃
51 | ┃ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ ' │ ┃
52 | ┃ | [a]| [s]| [d]| [f]| [g]| [h]| [j]| [k]| [l]| [;]| [']| ┃
53 | ┠───────────────┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────────────────┨
54 | ┃ │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ ┃
55 | ┃ | [Z]| [X]| [C]| [V]| [B]| [N]| [M]| [<]| [>]| [?]| ┃
56 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
57 | ┃ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ ┃
58 | ┃ | [z]| [x]| [c]| [v]| [b]| [n]| [m]| [,]| [.]| [/]| ┃
59 | ┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━╅─────────┴─────────┴─────────┴─────────╆━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
60 | ┃ SPC ┃
61 | ┃ [SPC]┃
62 | ┃ ┃
63 | ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
64 | " )
65 |
66 | (defconst sniem-cheatsheet-layout-dvp
67 | " Cheatsheet For Programmer Dvorak
68 |
69 | ┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━━━━┓
70 | ┃ ~ │ % │ 7 │ 5 │ 3 │ 1 │ 9 │ 0 │ 2 │ 4 │ 6 │ 8 │ ` │ DEL ┃
71 | ┃ [~]│ [%]│ [7]│ [5]│ [3]│ [1]│ [9]│ [0]│ [2]│ [4]│ [6]│ [8]│ [`]│ ┃
72 | ┠─┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [DEL]┃
73 | ┃ $ │ & │ [ │ { │ } │ ( │ = │ * │ ) │ + │ ] │ ! │ # │ ┃
74 | ┃ [$]│ [&]│ [[]│ [{]│ [}]│ [(]│ [=]│ [*]│ [)]│ [+]│ []]│ [!]│ [#]│ ┃
75 | ┠─────────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────────┨
76 | ┃ TAB │ : │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ ^ │ | ┃
77 | ┃ │ [:]│ [<]│ [>]│ [P]│ [Y]│ [F]│ [G]│ [C]│ [R]│ [L]│ [?]│ [^]│ [|]┃
78 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┨
79 | ┃ │ ; │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ @ │ \\ ┃
80 | ┃ │ [;]│ [,]│ [.]│ [p]│ [y]│ [f]│ [g]│ [c]│ [r]│ [l]│ [/]│ [@]│ [\\]┃
81 | ┠─────────────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─────────┨
82 | ┃ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ RET ┃
83 | ┃ │ [A]│ [O]│ [E]│ [U]│ [I]│ [D]│ [H]│ [T]│ [N]│ [S]│ [_]│ ┃
84 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [RET]┃
85 | ┃ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ ┃
86 | ┃ │ [a]│ [o]│ [e]│ [u]│ [i]│ [d]│ [h]│ [t]│ [n]│ [s]│ [-]│ ┃
87 | ┠───────────────┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────────────────┨
88 | ┃ │ \" │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ ┃
89 | ┃ │ [\"]│ [Q]│ [J]│ [K]│ [X]│ [B]│ [M]│ [W]│ [V]│ [Z]│ ┃
90 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
91 | ┃ │ ' │ q │ j │ k │ x │ b │ m │ w │ v │ z │ ┃
92 | ┃ │ [']│ [q]│ [j]│ [k]│ [x]│ [b]│ [m]│ [w]│ [v]│ [z]│ ┃
93 | ┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━╅─────────┴─────────┴─────────┴─────────╆━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
94 | ┃ SPC ┃
95 | ┃ [SPC]┃
96 | ┃ ┃
97 | ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
98 | ")
99 |
100 | (defconst sniem-cheatsheet-layout-dvorak
101 | " Cheatsheet For Dvorak Simplified
102 |
103 | ┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━━━━┓
104 | ┃ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ { │ } │ DEL ┃
105 | ┃ [~]| [!]| [@]| [#]| [$]| [%]| [^]| [&]| [*]| [(]| [)]| [{]| [}]| ┃
106 | ┠─┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [DEL]┃
107 | ┃ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ ┃
108 | ┃ [`]| [1]| [2]| [3]| [4]| [5]| [6]| [7]| [8]| [9]| [0]| [[]| []]| ┃
109 | ┠─────────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────────┨
110 | ┃ TAB │ \" │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ + │ | ┃
111 | ┃ │ [\"]│ [<]│ [>]│ [P]│ [Y]│ [F]│ [G]│ [C]│ [R]│ [L]│ [?]│ [+]│ [|]┃
112 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┨
113 | ┃ │ ' │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ = │ \\ ┃
114 | ┃ │ [']│ [,]│ [.]│ [p]│ [y]│ [f]│ [g]│ [c]│ [r]│ [l]│ [/]│ [=]│ [\\]┃
115 | ┠─────────────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─────────┨
116 | ┃ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ RET ┃
117 | ┃ │ [A]│ [O]│ [E]│ [U]│ [I]│ [D]│ [H]│ [T]│ [N]│ [S]│ [_]│ ┃
118 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [RET]┃
119 | ┃ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ ┃
120 | ┃ │ [a]│ [o]│ [e]│ [u]│ [i]│ [d]│ [h]│ [t]│ [n]│ [s]│ [-]│ ┃
121 | ┠───────────────┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────────────────┨
122 | ┃ │ : │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ ┃
123 | ┃ │ [:]│ [Q]│ [J]│ [K]│ [X]│ [B]│ [M]│ [W]│ [V]│ [Z]│ ┃
124 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
125 | ┃ │ ; │ q │ j │ k │ x │ b │ m │ w │ v │ z │ ┃
126 | ┃ │ [;]│ [q]│ [j]│ [k]│ [x]│ [b]│ [m]│ [w]│ [v]│ [z]│ ┃
127 | ┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━╅─────────┴─────────┴─────────┴─────────╆━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
128 | ┃ SPC ┃
129 | ┃ [SPC]┃
130 | ┃ ┃
131 | ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
132 | ")
133 |
134 | (defconst sniem-cheatsheet-layout-colemak
135 | " Cheatsheet For Colemak
136 |
137 | ┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━━━━┓
138 | ┃ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ DEL ┃
139 | ┃ [~]| [!]| [@]| [#]| [$]| [%]| [^]| [&]| [*]| [(]| [)]| [_]| [+]| ┃
140 | ┠─┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [DEL]┃
141 | ┃ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ ┃
142 | ┃ [`]| [1]| [2]| [3]| [4]| [5]| [6]| [7]| [8]| [9]| [0]| [-]| [=]| ┃
143 | ┠─────────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────────┨
144 | ┃ TAB │ Q │ W │ F │ P │ G │ J │ L │ U │ Y │ : │ { │ } │ | ┃
145 | ┃ | [Q]| [W]| [F]| [P]| [G]| [J]| [L]| [U]| [Y]| [:]| [{]| [}]| [|]┃
146 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┨
147 | ┃ │ q │ w │ f │ p │ g │ j │ l │ u │ y │ ; │ [ │ ] │ \\ ┃
148 | ┃ | [q]| [w]| [f]| [p]| [g]| [j]| [l]| [u]| [y]| [;]| [[]| []]| [\\]┃
149 | ┠─────────────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─────────┨
150 | ┃ │ A │ R │ S │ T │ D │ H │ N │ E │ I │ O │ \" │ RET ┃
151 | ┃ | [A]| [R]| [S]| [T]| [D]| [H]| [N]| [E]| [I]| [O]| [\"]│ ┃
152 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ [RET]┃
153 | ┃ │ a │ r │ s │ t │ d │ h │ n │ e │ i │ o │ ' │ ┃
154 | ┃ | [a]| [r]| [s]| [t]| [d]| [h]| [n]| [e]| [i]| [o]| [']| ┃
155 | ┠───────────────┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────────────────┨
156 | ┃ │ Z │ X │ C │ V │ B │ K │ M │ < │ > │ ? │ ┃
157 | ┃ | [Z]| [X]| [C]| [V]| [B]| [K]| [M]| [<]| [>]| [?]| ┃
158 | ┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
159 | ┃ │ z │ x │ c │ v │ b │ k │ m │ , │ . │ / │ ┃
160 | ┃ | [z]| [x]| [c]| [v]| [b]| [k]| [m]| [,]| [.]| [/]| ┃
161 | ┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━╅─────────┴─────────┴─────────┴─────────╆━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
162 | ┃ SPC ┃
163 | ┃ [SPC]┃
164 | ┃ ┃
165 | ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
166 | " )
167 |
168 | (defconst sniem-cheatsheet-keys
169 | '("a" "A" "b" "B" "c" "C" "d" "D" "e" "E" "f" "F" "g" "G" "h" "H" "i" "I" "j" "J"
170 | "k" "K" "l" "L" "m" "M" "n" "N" "o" "O" "p" "P" "q" "Q" "r" "R" "s" "S" "t" "T"
171 | "u" "U" "v" "V" "w" "W" "x" "X" "y" "Y" "z" "Z" "0" "1" "2" "3" "4" "5" "6" "7"
172 | "8" "9" "!" "@" "" "$" "%" "^" "&" "*" "" "~" "-" "_" "=" "+" "," "<" "." ">"
173 | "/" "?" "(" ")" "[" "]" "{" "}" "\\" "|" ";" ":" "'" "\"" "#" "`" "SPC" "RET" "DEL"))
174 |
175 | (defcustom sniem-cheatsheet-special-key-space
176 | '(("" . " ")
177 | ("
" . " ")
178 | (" " . " "))
179 | "The space for special key."
180 | :type 'list
181 | :group 'sniem)
182 |
183 | (defcustom sniem-cheatsheet-special-key-width
184 | '(("" . 13)
185 | ("
" . 17)
186 | (" " . 39))
187 | "The space for special key."
188 | :type 'list
189 | :group 'sniem)
190 |
191 | (defcustom sniem-cheatsheet-short-commands
192 | '((sniem-forward-char . "→")
193 | (sniem-backward-char . "←")
194 | (sniem-5-forward-char . "5*→")
195 | (sniem-5-backward-char . "←*5")
196 | (sniem-next-line . "↓")
197 | (sniem-prev-line . "↑")
198 | (sniem-5-next-line . "↓*5")
199 | (sniem-5-prev-line . "↑*5")
200 | (digit-argument . "num-arg")
201 | (sniem-digit-argument-or-fn . "num-arg-middle-keyboard-with-functions")
202 | (sniem-beginning-of-line . "line-beg")
203 | (sniem-end-of-line . "line-end")
204 | (sniem-first-line . "1st line")
205 | (sniem-goto-line . "goto-line")
206 | (sniem-next-word . "word →")
207 | (sniem-prev-word . "word ←")
208 | (sniem-next-symbol . "symbol→")
209 | (sniem-prev-symbol . "symbol←")
210 | (sniem-beg-of-mark . "mark-beg")
211 | (sniem-end-of-mark . "mark-end")
212 | (sniem-lock-unlock-last-point . "lock-LP")
213 | (sniem-goto-last-point . "goto-LP")
214 | (sniem-move-last-point . "move-LP-p")
215 | (sniem-goto-next . "lines ↓")
216 | (sniem-goto-prev . "lines ↑")
217 | (sniem-find-forward . "find →")
218 | (sniem-find-backward . "find ←")
219 | (sniem-up-down-case . "↑/↓ case")
220 | (save-buffers-kill-terminal . "exit")
221 | (sniem-yank-in-region . "Y [mark]")
222 | (sniem-delete-in-region . "D [mark]")
223 | (sniem-change-in-region . "C [mark]")
224 | (sniem-paste-in-region . "P [mark]")
225 | (sniem-keyboard-quit . "quit")
226 | (sniem-append-line . "A-line")
227 | (sniem-insert-line . "I-line")
228 | (sniem-delete-char . "D-char")
229 | (sniem-scroll-up-command . "page ↓")
230 | (sniem-scroll-down-command . "page ↑")
231 | (sniem-object-catch-round . "OC-(")
232 | (sniem-object-catch-square . "OC-[")
233 | (sniem-object-catch-curly . "OC-{")
234 | (sniem-replace-char . "R-char")
235 | (sniem-replace-word . "R-word")
236 | (eval-last-sexp . "eval")
237 | (save-buffer . "save")
238 | (execute-extended-command . "M-x")
239 | (sniem-open-line . "new-line↓")
240 | (sniem-open-line-previous . "new-line↑")
241 | (sniem-cheatsheet . "cheatpage"))
242 | "The short commands."
243 | :type 'list
244 | :group 'sniem)
245 |
246 | (defun sniem-cheatsheet ()
247 | "Switch to the cheatsheet buffer and insert the cheatsheet."
248 | (interactive)
249 | (if (null sniem-keyboard-layout)
250 | (user-error "[Sniem]: You should set `sniem-keyboard-layout' first!")
251 | (let ((cheatsheet-layout (pcase sniem-keyboard-layout
252 | ('dvp sniem-cheatsheet-layout-dvp)
253 | ('dvorak sniem-cheatsheet-layout-dvorak)
254 | ('colemak sniem-cheatsheet-layout-colemak)
255 | ('qwerty sniem-cheatsheet-layout-qwerty))))
256 | (-> (propertize cheatsheet-layout 'face 'font-lock-comment-face)
257 | (sniem-cheatsheet--replace)
258 | (sniem-cheatsheet--show-cheatsheet)))))
259 |
260 | (defun sniem-cheatsheet--show-cheatsheet (cs)
261 | "Show the cheatsheet.
262 | Argument CS is the cheatsheet of current keyboard."
263 | (with-current-buffer (get-buffer-create "*Sniem Cheatsheet*")
264 | (setq-local buffer-read-only nil)
265 | (erase-buffer)
266 | (insert cs)
267 | (insert "\nNOTE:\n"
268 | (propertize "[mark]" 'face 'font-lock-constant-face)
269 | " means the operation will edit the regions' content. You can mark a content, "
270 | "then use operations with [mark] sign to edit them.\n"
271 | (propertize "LP" 'face 'font-lock-constant-face)
272 | " means the last-point, all of the sniem motions and most of the operations will use it.")
273 | (text-mode)
274 | (toggle-truncate-lines t)
275 | (display-line-numbers-mode -1)
276 | (line-number-mode -1)
277 | (setq-local buffer-read-only t))
278 | (switch-to-buffer "*Sniem Cheatsheet*")
279 | (goto-char (point-min)))
280 |
281 | (defun sniem-cheatsheet--replace (cs)
282 | "Replace the keys in the cheatsheet.
283 | Argument CS is the cheatsheet of current keyboard."
284 | (-reduce-from
285 | (lambda (cs key)
286 | (let* ((ckey (kbd key))
287 | (cmd (key-binding ckey))
288 | tmp)
289 | (if (and cmd (or (keymapp cmd) (symbolp cmd)))
290 | (let ((case-fold-search nil))
291 | (s-replace
292 | (format (if (setq tmp (alist-get ckey sniem-cheatsheet-special-key-space nil nil 'equal))
293 | (concat tmp "[%s]")
294 | " [%s]")
295 | key)
296 | (if (keymapp cmd)
297 | " leader"
298 | (sniem-cheatsheet--command cmd ckey))
299 | cs))
300 | cs)))
301 | cs sniem-cheatsheet-keys))
302 |
303 | (defun sniem-cheatsheet--command (cmd key)
304 | "Replace the command to short.
305 | Argument CMD is the command.
306 | Argument KEY is the key of command."
307 | (let ((scmd (or (alist-get cmd sniem-cheatsheet-short-commands)
308 | (s-replace "sniem-" "" (symbol-name cmd))))
309 | (sp-cmd-space (when (sniem-cheatsheet--special-key-p cmd key)
310 | (alist-get key sniem-cheatsheet-special-key-width nil nil 'equal))))
311 | (when scmd
312 | (when (string= "undefined" scmd)
313 | (setq scmd ""))
314 | (if (<= (length scmd) (or sp-cmd-space 9))
315 | (-> (->> (or sp-cmd-space 9)
316 | (number-to-string)
317 | (concat "% "))
318 | (concat "s")
319 | (format scmd))
320 | (s-truncate (or sp-cmd-space 9) scmd)))))
321 |
322 | (defun sniem-cheatsheet--special-key-p (cmd key)
323 | "Check if the KEY for CMD is included in `sniem-cheatsheet-special-key-space'."
324 | (catch 'p
325 | (mapc `(lambda (k)
326 | (when (and (equal ,key k) (eq (key-binding k) ',cmd))
327 | (throw 'p k)))
328 | '(" " "
" ""))))
329 |
330 | (provide 'sniem-cheatsheet)
331 |
332 | ;;; sniem-cheatsheet.el ends here
333 |
--------------------------------------------------------------------------------
/sniem-common.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-common.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method
25 |
26 | ;;; Code:
27 |
28 | (require 'sniem-var)
29 |
30 | (declare-function sniem-digit-argument-read-char "sniem")
31 | (declare-function sniem-digit-argument-fn-get "sniem")
32 |
33 | (defun sniem-motion-hint (motion)
34 | "Hint after MOTION."
35 | (let (overlay point)
36 | (when sniem-motion-hint-remove-timer
37 | (cancel-timer sniem-motion-hint-remove-timer))
38 | (sniem--motion-hint-remove)
39 |
40 | (save-mark-and-excursion
41 | (catch 'stop
42 | (dotimes (i 10)
43 | (call-interactively motion)
44 | (if (and point (= (point) point))
45 | (throw 'stop nil)
46 | (setq overlay (make-overlay (point) (1+ (point))))
47 | (overlay-put overlay 'display (format "%s%s"
48 | (propertize (number-to-string (1+ i))
49 | 'face 'sniem-motion-hint-face)
50 | (pcase (following-char)
51 | ((pred (= 10)) "\n")
52 | ((pred (= 9)) "\t")
53 | (_ ""))))
54 | (setq point (point))
55 | (push overlay sniem-motion-hint-overlays)))))
56 | (setq-local sniem-motion-hint-motion motion)
57 | (setq sniem-motion-hint-remove-timer
58 | (run-with-timer sniem-motion-hint-sit-time nil
59 | #'sniem--motion-hint-remove))
60 | (sit-for sniem-motion-hint-sit-time)
61 | (when sniem-motion-hint-remove-timer
62 | (cancel-timer sniem-motion-hint-remove-timer)
63 | (sniem--motion-hint-remove))))
64 |
65 | (defun sniem--motion-hint-remove ()
66 | "Remove motion hint overlays."
67 | (when sniem-motion-hint-overlays
68 | (mapc #'delete-overlay sniem-motion-hint-overlays)
69 | (setq sniem-motion-hint-overlays nil))
70 | (setq sniem-motion-hint-remove-timer nil))
71 |
72 | (defun sniem-move-with-hint-num (num)
73 | "Move with NUM to eval the last `sniem-motion-hint-motion'."
74 | (interactive "P")
75 | (dotimes (_ num)
76 | (funcall-interactively sniem-motion-hint-motion))
77 | (sniem-motion-hint sniem-motion-hint-motion))
78 |
79 | (defun sniem-digit-argument-get (&optional msg)
80 | "A function which make you can use the middle of the keyboard.
81 | Instead of the num keyboard.
82 | Optional argument MSG is the message which will be outputed."
83 | (interactive)
84 | (let ((number "")
85 | (arg "")
86 | (universal-times 0)
87 | fn)
88 | (while (not (string= number "over"))
89 | (setq number (sniem-digit-argument-read-char))
90 | (unless (string= number "over")
91 | (cond ((string= number "delete")
92 | (setq arg (substring arg 0 -1)))
93 | ((setq fn (sniem-digit-argument-fn-get number))
94 | (setq number "over"))
95 | ((string= number "U") ;For C-u
96 | (setq universal-times (1+ universal-times))
97 | (setq arg (concat arg "C-u ")))
98 | ((null number)
99 | (error nil))
100 | (t (setq arg (concat arg number)))))
101 | (message "%s%s" (if msg
102 | msg
103 | "C-u ")
104 | arg))
105 | (setq arg (if (string= "" arg)
106 | nil
107 | (if (/= universal-times 0)
108 | (list (expt 4 (1+ universal-times)))
109 | (string-to-number arg))))
110 | (if fn
111 | (if arg
112 | `(funcall-interactively ',fn ,arg)
113 | `(call-interactively ',fn))
114 | arg)))
115 |
116 | (defun sniem--mems (ele list &optional prefix)
117 | "Like memq, but use `string-equal'.
118 | Argument ELE is the element to check.
119 | Argument LIST is the list to check.
120 | When PREFIX is non-nil, check if ELE is the prefix."
121 | (if (stringp list)
122 | (string= ele list)
123 | (catch 'stop
124 | (dolist (item list)
125 | (when (stringp item)
126 | (if (string-equal item ele)
127 | (throw 'stop t)
128 | (when (and prefix
129 | (string-prefix-p ele item))
130 | (throw 'stop (list t)))))))))
131 |
132 | (defun sniem--list-memq (list1 list2 &optional return-type)
133 | "Check if there are ele of LIST1 which are also in LIST2.
134 | Optional Argument RETURN-TYPE is the type of the return value.
135 | It can be 'index or 'ele. Defaultly it's 'ele.
136 |
137 | If it's true, return the value of the ele.
138 | Otherwise nil will be return."
139 | (let (result ele)
140 | (when (and list1 list2)
141 | (catch 'stop
142 | (dotimes (i (length list1))
143 | (setq ele (nth i list1))
144 | (when (memq ele list2)
145 | (setq result (if (eq return-type 'index)
146 | i
147 | ele))
148 | (throw 'stop nil)))))
149 | result))
150 |
151 | (defun sniem--assoc-with-list-value (value alist)
152 | "Get a cons with its VALUE in ALIST.
153 | And VALUE is a list."
154 | (catch 'result
155 | (when alist
156 | (dolist (e alist)
157 | (when (memq (cdr e) value)
158 | (throw 'result e))))))
159 |
160 | (defun sniem--nth-utill (start end list)
161 | "Get elements in LIST from START to END.
162 | START & END can be nil."
163 | (let (ele)
164 | (unless start
165 | (setq start 0))
166 | (unless end
167 | (setq end (length list)))
168 | (catch 'stop
169 | (dotimes (i (length list))
170 | (when (>= i start)
171 | (if (<= i end)
172 | (setq ele (append ele
173 | (list (nth i list))))
174 | (throw 'stop t)))))
175 | ele))
176 |
177 | (defun sniem--index (ele list)
178 | "Get the index of ELE in LIST."
179 | (catch 'result
180 | (dotimes (i (length list))
181 | (when (equal (nth i list) ele)
182 | (throw 'result i)))))
183 |
184 | (provide 'sniem-common)
185 |
186 | ;;; sniem-common.el ends here
187 |
--------------------------------------------------------------------------------
/sniem-linked-file.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-linked-file.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This program is free software: you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation, either version 3 of the License, or
11 | ;; (at your option) any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; You should have received a copy of the GNU General Public License
19 | ;; along with this program. If not, see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;;; Hands-eased united editing method.
25 |
26 | ;;; Code:
27 |
28 | (defcustom sniem-linked-file-list nil
29 | "The list used to save date of linked files."
30 | :type 'list
31 | :group 'sniem)
32 |
33 | (defcustom sniem-linked-file-root-buffer nil
34 | "The root buffer."
35 | :type 'buffer
36 | :group 'sniem)
37 |
38 | (defun sniem-linked-file-pannel (option)
39 | "Execute commands accroding to OPTION."
40 | (interactive (list (read-char sniem-linked-file-message)))
41 | (call-interactively (pcase option
42 | (?r #'sniem-linked-file-set-root)
43 | (?l #'sniem-linked-file-as-linked)
44 | (?s #'sniem-linked-file-save)
45 | (?o #'sniem-linked-file-open)
46 | (?c #'sniem-linked-file-clean))))
47 |
48 | (defun sniem-linked-file-open ()
49 | "Open linked files of current file."
50 | (interactive)
51 | (let ((linked-files (sniem-linked-file--read)))
52 | (unless linked-files
53 | (user-error "[Sniem]: Cannot find linked files for current file!"))
54 | (dolist (file linked-files)
55 | (find-file-noselect file))
56 | (message "[Sniem]: Have opened linked files.")))
57 |
58 | (defun sniem-linked-file-set-root ()
59 | "Set the current file as the root file."
60 | (interactive)
61 | (setq sniem-linked-file-list (list (buffer-file-name))
62 | sniem-linked-file-root-buffer (current-buffer))
63 | (message "[Sniem]: Have set current buffer as root file."))
64 |
65 | (defun sniem-linked-file-as-linked ()
66 | "Set current file as linked file."
67 | (interactive)
68 | (unless sniem-linked-file-list
69 | (user-error "[Sniem]: You haven't set the root file!"))
70 | (add-to-list 'sniem-linked-file-list (buffer-file-name) t #'string-equal)
71 | (message "[Sniem]: Have set current buffer as linked file."))
72 |
73 | (defun sniem-linked-file-save ()
74 | "Save current linked list."
75 | (interactive)
76 | (sniem-linked-file--save sniem-linked-file-list)
77 | (setq sniem-linked-file-list nil
78 | sniem-linked-file-root-buffer nil)
79 | (message "[Sniem]: Successfully save!"))
80 |
81 | (defun sniem-linked-file-clean ()
82 | "Clean current linked list."
83 | (interactive)
84 | (setq sniem-linked-file-list nil)
85 | (message "[Sniem]: Have cleaned linked list."))
86 |
87 | (defun sniem-linked-file-add-ignore ()
88 | "Add the root conf file into .gitignore."
89 | (interactive)
90 | (let* ((file (concat (sniem-linked-file--root) ".gitignore"))
91 | (prev-content ""))
92 | (if (file-exists-p file)
93 | (setq prev-content (with-temp-buffer
94 | (insert-file-contents file)
95 | (buffer-string)))
96 | (make-empty-file file))
97 | (with-temp-file file
98 | (insert "SNIEM_LINKED_FILE\n" prev-content))))
99 |
100 | (defun sniem-linked-file--save (cont)
101 | "Totally rewrite root conf file with CONT."
102 | (with-current-buffer sniem-linked-file-root-buffer
103 | (let* ((conf-file (sniem-linked-file--root-file))
104 | (prev-content ""))
105 | (if (file-exists-p conf-file)
106 | (setq prev-content (with-temp-buffer
107 | (insert-file-contents conf-file)
108 | (buffer-string)))
109 | (make-empty-file conf-file)
110 | (sniem-linked-file-add-ignore))
111 | (with-temp-file conf-file
112 | (insert (format "%S" cont) "\n" prev-content)))))
113 |
114 | (defun sniem-linked-file--read ()
115 | "Read root conf file."
116 | (with-current-buffer (current-buffer)
117 | (let* ((conf-file (sniem-linked-file--root-file))
118 | (file-content (car (read-from-string
119 | (replace-regexp-in-string
120 | "\n"
121 | ""
122 | (concat "("
123 | (with-temp-buffer
124 | (insert-file-contents conf-file)
125 | (buffer-string))
126 | ")"))))))
127 | (when (file-exists-p conf-file)
128 | (alist-get (buffer-file-name) file-content nil nil #'string-equal)))))
129 |
130 | (defun sniem-linked-file--root-file ()
131 | "Return current root config file."
132 | (concat (sniem-linked-file--root) "SNIEM_LINKED_FILE"))
133 |
134 | (defun sniem-linked-file--root ()
135 | "Get the root directory of the project which includes root file."
136 | (let ((result default-directory)
137 | (get-parent (lambda (path)
138 | (let ((dir (substring path 0 -1)))
139 | (while (not (string-suffix-p "/" dir))
140 | (setq dir (substring dir 0 -1)))
141 | dir))))
142 | (while (not (sniem--mems ".git"
143 | (directory-files result)))
144 | (setq result (funcall get-parent result)))
145 | result))
146 |
147 | (provide 'sniem-linked-file)
148 |
149 | ;;; sniem-linked-file.el ends here
150 |
--------------------------------------------------------------------------------
/sniem-macro.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-macro.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method.
25 |
26 | ;;; Code:
27 |
28 | (defmacro sniem-define-motion (name arg docstring &rest body)
29 | "Define motion for sniem.
30 | Argument NAME is the name of motion.
31 | Argument ARG is the arg of motion.
32 | Argument DOCSTRING is the docstring.
33 | Optional argument BODY is the main body of motion function."
34 | (declare (indent defun)
35 | (doc-string 3)
36 | (debug (&define name lambda-lsit
37 | [&optional stringp]
38 | [&optional ("interactive" [&rest form])]
39 | def-body)))
40 | (let ((inter (if (eq (car-safe (car-safe `,body)) 'interactive)
41 | (pop `,body)
42 | '(interactive))))
43 | (unless (memq '&optional `,arg)
44 | (setq arg (append `,arg '(&optional))))
45 | `(defun ,name (,@arg non-point-set)
46 | ,docstring
47 | ,inter
48 | (unless (or sniem-last-point-locked non-point-set)
49 | (setq-local sniem-last-point (point)))
50 | ,@body)))
51 |
52 | (provide 'sniem-macro)
53 |
54 | ;;; sniem-macro.el ends here
55 |
--------------------------------------------------------------------------------
/sniem-mark-jump.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-mark-jump.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method.
25 |
26 | ;;; Code:
27 |
28 | (require 'sniem-common)
29 | (require 'sniem-operation)
30 |
31 | (declare-function sniem-change-mode "sniem")
32 |
33 | (defcustom sniem-mark-jump-items
34 | '("TODO" "BUG" "NOTE")
35 | "The faces for `sniem-mark-jump'."
36 | :type 'list
37 | :group 'sniem)
38 |
39 | (defcustom sniem-mark-jump-author-name nil
40 | "The default name for mark."
41 | :type 'string
42 | :group 'sniem)
43 |
44 | (defcustom sniem-mark-jump-author-name-enable nil
45 | "If enable the author name."
46 | :type 'boolean
47 | :group 'sniem)
48 |
49 | (defcustom sniem-mark-jump-regexp nil
50 | "The regexp for mark."
51 | :type 'string
52 | :group 'sniem)
53 |
54 | (defun sniem-mark-jump-lisp-mode-p ()
55 | "Check if the current major mode belongs to Lisp mode."
56 | (string-match-p "\\(?:.*\\)lisp\\(?:.*\\)" (symbol-name major-mode)))
57 |
58 | (defun sniem-mark-jump-insert (type &optional name)
59 | "Insert the mark with TYPE.
60 | Optional argument NAME means enable the name."
61 | (interactive (list (completing-read "Enter the type: "
62 | sniem-mark-jump-items)))
63 | (unless (eq (face-at-point) 'font-lock-comment-face)
64 | (if (and (eolp)
65 | (not (looking-back "^[\s\t]*" (line-beginning-position) t)))
66 | (insert (if (not (memq (char-before) '(?\t ?\s)))
67 | " "
68 | "")
69 | comment-start)
70 | (unless (= (line-beginning-position) (line-end-position))
71 | (sniem-open-line-previous))
72 | (insert (if (sniem-mark-jump-lisp-mode-p)
73 | (concat comment-start comment-start)
74 | comment-start))))
75 | (insert (if (string= " " (substring comment-start -1))
76 | ""
77 | " ")
78 | type
79 | (format "%s: " (if (or name sniem-mark-jump-author-name-enable)
80 | (sniem-mark-jump--get-author-name)
81 | "")))
82 | (when comment-end
83 | (save-mark-and-excursion
84 | (insert comment-end)))
85 | (sniem-change-mode 'insert))
86 |
87 | (defun sniem-mark-jump-insert-with-name (&optional name)
88 | "`sniem-mark-jump-insert' with NAME."
89 | (interactive "P")
90 | (if name
91 | (funcall #'sniem-mark-jump-insert
92 | (completing-read "Enter the type: " sniem-mark-jump-items) t)
93 | (call-interactively #'sniem-mark-jump-insert)))
94 |
95 | (sniem-define-motion sniem-mark-jump-next (&optional type)
96 | "Jump next."
97 | (interactive "P")
98 | (when type
99 | (setq type (sniem-mark-jump--get-type type)))
100 | (sniem-mark-jump--jump t type))
101 |
102 | (sniem-define-motion sniem-mark-jump-prev (&optional type)
103 | "Jump previous."
104 | (interactive "P")
105 | (when type
106 | (setq type (sniem-mark-jump--get-type type)))
107 | (sniem-mark-jump--jump nil type))
108 |
109 | (defun sniem-mark-jump--get-type (num)
110 | "Get type by NUM."
111 | (nth (1- num) sniem-mark-jump-items))
112 |
113 | (defun sniem-mark-jump--jump (next &optional type)
114 | "Jump to NEXT/previous item.
115 | Optional argument TYPE is the type of comment mark."
116 | (let ((search-command (if next
117 | 're-search-forward
118 | 're-search-backward))
119 | (point (point))
120 | (case-fold-search nil)
121 | (tmp t))
122 | (when (sniem-mark-jump--comment-face-p)
123 | (sniem-mark-jump--escape-comment (when next t)))
124 | (catch 'stop
125 | (while tmp
126 | (setq tmp (funcall search-command
127 | (concat "\\(" comment-start "*\\)"
128 | (if type
129 | (concat "\\(?:.*\\)" type "\\(?:.*\\)")
130 | sniem-mark-jump-regexp))
131 | nil t))
132 | (when (and tmp (numberp tmp))
133 | (goto-char (comment-beginning))
134 | (throw 'stop t)))
135 | (message "[Sniem]: The mark can not be found.")
136 | (goto-char point))))
137 |
138 | (defun sniem-mark-jump--escape-comment (forward)
139 | "Escape current comment.
140 | Argument FORWARD means search forward."
141 | (let ((motion (if forward
142 | 'forward-char
143 | 'backward-char)))
144 | (while (sniem-mark-jump--comment-face-p)
145 | (funcall motion))))
146 |
147 | (defun sniem-mark-jump--comment-face-p ()
148 | "Check if the content at point has the comment face."
149 | (let ((face-list (get-text-property (point) 'face)))
150 | (when face-list
151 | (or (and (symbolp face-list)
152 | (or (eq face-list 'font-lock-comment-face)
153 | (eq face-list 'font-lock-comment-delimiter-face)))
154 | (and (listp face-list) (memq 'font-lock-comment-face face-list))))))
155 |
156 | (defun sniem-mark-jump--get-author-name ()
157 | "Get the author's name."
158 | (if sniem-mark-jump-author-name
159 | sniem-mark-jump-author-name
160 | (unless sniem-mark-jump-author-name-enable
161 | (setq-local sniem-mark-jump-author-name-enable t))
162 | (let ((tmp (read-string "Enter your name: ")))
163 | (if (string-equal tmp "")
164 | ;; When the name string is empty, disabling to insert author name.
165 | (progn
166 | (setq-local sniem-mark-jump-author-name-enable nil)
167 | "")
168 | tmp))))
169 |
170 | (defun sniem-mark-jump-reset-regexp ()
171 | "Reset the regexp."
172 | (setq sniem-mark-jump-regexp
173 | (concat "\\(?:.*\\)\\("
174 | (mapconcat #'sniem-mark-jump--self sniem-mark-jump-items "\\|")
175 | "\\)\\(?:.*\\)")))
176 |
177 | (defun sniem-mark-jump--self (arg)
178 | "Return ARG itself."
179 | arg)
180 |
181 | (sniem-mark-jump-reset-regexp)
182 |
183 | ;;; For user
184 | (defun sniem-mark-jump-set-items (way item)
185 | "Set `sniem-mark-jump-items'.
186 | The WAY includes:
187 | :add - Add a new ITEM.
188 | :delete - Delete a item."
189 | (pcase way
190 | (:add (unless (sniem--mems item sniem-mark-jump-items)
191 | (setq sniem-mark-jump-items (append sniem-mark-jump-items (list item)))))
192 | (:delete (setq sniem-mark-jump-items (delete item sniem-mark-jump-items))))
193 | (sniem-mark-jump-reset-regexp))
194 |
195 | (provide 'sniem-mark-jump)
196 |
197 | ;;; sniem-mark-jump.el ends here
198 |
--------------------------------------------------------------------------------
/sniem-object-catch.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-object-catch.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method
25 |
26 | ;;; Code:
27 |
28 | (require 'sniem-var)
29 | (require 'sniem-common)
30 | (require 'sniem-macro)
31 |
32 | (defgroup sniem-object-catch nil
33 | "The group of `sniem-object-catch'."
34 | :group 'sniem)
35 |
36 | (defcustom sniem-object-catch-last-points nil
37 | "The last point cons."
38 | :type 'cons
39 | :group 'sniem-object-catch)
40 |
41 | (defcustom sniem-object-catch-action nil
42 | "The action info for the last catch."
43 | :type 'cons
44 | :group 'sniem-object-catch)
45 |
46 | (defcustom sniem-object-catch-forward-p nil
47 | "The direction for catch."
48 | :type 'symbol
49 | :group 'sniem-object-catch)
50 |
51 | (defcustom sniem-object-catch-prefix-string-p nil
52 | "If the prefix is string."
53 | :type 'boolean
54 | :group 'sniem-object-catch)
55 |
56 | (defcustom sniem-object-catch-expand-p nil
57 | "If to expand the region from current selecetion."
58 | :type 'boolean
59 | :group 'sniem-object-catch)
60 |
61 | (defcustom sniem-object-catch-last-expand nil
62 | "The last expand points."
63 | :type 'cons
64 | :group 'sniem-object-catch)
65 |
66 | (defcustom sniem-object-catch-auto-backward nil
67 | "If this variable is non-nil.
68 | When you exit expand-mode, the direction'll be set to backward."
69 | :type 'boolean
70 | :group 'sniem-object-catch)
71 |
72 | (sniem-define-motion sniem-object-catch (&optional char parent)
73 | "Catch region."
74 | (interactive)
75 | (let ((point (point)))
76 | (when (and parent sniem-object-catch-forward-p)
77 | (setq-local sniem-object-catch-forward-p nil))
78 | (while (not (eq 'no (ignore-errors (sniem-object-catch--get char parent))))
79 | (if (bobp)
80 | (progn
81 | (goto-char point)
82 | (when sniem-object-catch-last-points
83 | (push-mark (cdr sniem-object-catch-last-points) t t))
84 | (user-error "[Sniem-Object-Catch]: Can't get more item!"))
85 | (backward-char)))
86 | (when sniem-object-catch-prefix-string-p
87 | (setq-local sniem-object-catch-prefix-string-p nil))))
88 |
89 | (defun sniem-object-catch--get (char parent)
90 | "Get the object.
91 | Argument CHAR is the prefix of pair.
92 | Argument PARENT means get the parent pair of the content selected."
93 | (let ((move (if sniem-object-catch-forward-p
94 | 'forward-char
95 | 'backward-char))
96 | prefix-point second-char second-point tmp go-on)
97 | (save-mark-and-excursion
98 | (when (region-active-p)
99 | (funcall move))
100 | ;; Get the `prefix-point'
101 | (if char
102 | (setq prefix-point
103 | (catch 'point-stop
104 | (while t
105 | (if (and (string=
106 | char
107 | (setq tmp
108 | (buffer-substring-no-properties (point) (1+ (point)))))
109 | (not (sniem-object-catch-backslash-p)))
110 | (throw 'point-stop (point))
111 | (if (or (bobp) (eobp))
112 | (throw 'point-stop nil)
113 | (funcall move))))))
114 | (setq prefix-point
115 | (catch 'point-stop
116 | (while t
117 | (if (and (sniem-object-catch--get-second-char
118 | (setq tmp (buffer-substring-no-properties (point) (1+ (point)))))
119 | (not (sniem-object-catch-backslash-p)))
120 | (progn
121 | (setq char tmp)
122 | (throw 'point-stop (point)))
123 | (if (or (bobp) (eobp))
124 | (throw 'point-stop nil)
125 | (funcall move)))))))
126 | (cond ((and (nth 3 (syntax-ppss prefix-point))
127 | (/= (following-char) 34))
128 | (setq-local sniem-object-catch-prefix-string-p t))
129 | ((and sniem-object-catch-prefix-string-p
130 | (null (nth 3 (syntax-ppss prefix-point))))
131 | (setq-local sniem-object-catch-prefix-string-p nil)))
132 | (if (not char)
133 | (message "[Sniem-Object-Catch]: Can not find a symbol in alist.")
134 | (setq second-char (sniem-object-catch--get-second-char char))
135 | (if (and (not (string= char second-char))
136 | (if (and (bobp)
137 | (= (point) prefix-point))
138 | (ignore-errors (= (char-before) 92))
139 | (= (char-before) 92)))
140 | (setq go-on t)
141 | (setq second-point (if (string= char second-char)
142 | (if (or (and (not (nth 3 (syntax-ppss)))
143 | (nth 8 (syntax-ppss)))
144 | (sniem-object-catch--face-around-eq))
145 | (sniem-object-catch-format-pointc char)
146 | (sniem-object-catch-format-point2 char prefix-point))
147 | (sniem-object-catch-format-point char second-char))))
148 | (when (consp second-point)
149 | (setq prefix-point (car second-point)
150 | second-point (cdr second-point)))
151 | (if (and parent sniem-object-catch-last-points
152 | (> (cdr sniem-object-catch-last-points) second-point)
153 | (< prefix-point (car sniem-object-catch-last-points)))
154 | (setq go-on t)
155 | (setq-local sniem-object-catch-last-points (cons prefix-point second-point)))))
156 | (when sniem-object-catch-expand-p
157 | (when sniem-object-catch-last-expand
158 | (when (< (car sniem-object-catch-last-expand) prefix-point)
159 | (setq prefix-point (car sniem-object-catch-last-expand)))
160 | (when (> (cdr sniem-object-catch-last-expand) second-point)
161 | (setq second-point (cdr sniem-object-catch-last-expand))))
162 | (setq-local sniem-object-catch-last-expand (cons prefix-point second-point)))
163 | (goto-char prefix-point)
164 | (push-mark second-point t t)
165 | (setq-local sniem-object-catch-action `(,char . ,parent))
166 | (unless go-on
167 | (setq go-on 'no))
168 | go-on))
169 |
170 | (defun sniem-object-catch-by-char (char)
171 | "Catch region by CHAR."
172 | (interactive (list (char-to-string (read-char))))
173 | (if (sniem-object-catch--get-second-char char)
174 | (sniem-object-catch char)
175 | (message "[Sniem-Object-Catch]: %s is not defined in the symbol alist." char)))
176 |
177 | (defun sniem-object-catch-char ()
178 | "Catch region by the last char."
179 | (interactive)
180 | (let ((pair (sniem-object-catch--get-last-char)))
181 | (sniem-object-catch pair nil)))
182 |
183 | (defun sniem-object-catch-parent ()
184 | "Catch region for its parent."
185 | (interactive)
186 | (let ((pair (sniem-object-catch--get-last-char)))
187 | (sniem-object-catch pair t)))
188 |
189 | (defun sniem-object-catch-expand ()
190 | "Open/close expand option."
191 | (interactive)
192 | (setq-local sniem-object-catch-last-expand nil)
193 | (if sniem-object-catch-expand-p
194 | (progn
195 | (setq-local sniem-object-catch-expand-p nil)
196 | (message "[Sniem]: Expand closed."))
197 | (when sniem-object-catch-forward-p
198 | (setq-local sniem-object-catch-forward-p nil))
199 | (setq-local sniem-object-catch-expand-p t)
200 | (when (region-active-p)
201 | (setq-local sniem-object-catch-last-expand sniem-object-catch-last-points))
202 | (message "[Sniem]: Expand opened.")))
203 |
204 | (defun sniem-object-catch--get-last-char ()
205 | "Get the last char."
206 | (pcase last-input-event
207 | ((or 41 79 111) "(")
208 | ((or 83 93 115) "[")
209 | ((or 67 125 99) "{")
210 | ((or 39 113 81) "'")
211 | ((or 34 100 68) "\"")
212 | ((or 60 97 65) "<")
213 | (_ nil)))
214 |
215 | (defun sniem-object-catch-parent-by-char (char)
216 | "Catch region for its parent by CHAR."
217 | (interactive (list (char-to-string (read-char))))
218 | (if (sniem-object-catch--get-second-char char)
219 | (sniem-object-catch char t)
220 | (message "[Sniem-Object-Catch]: %s is not defined in the symbol alist." char)))
221 |
222 | (defun sniem-object-catch-repeat ()
223 | "Repeat the last catch."
224 | (interactive)
225 | (when sniem-object-catch-action
226 | (sniem-object-catch (car sniem-object-catch-action) (cdr sniem-object-catch-action))))
227 |
228 | (defun sniem-object-catch-direction-reverse (&optional forward)
229 | "Reverse the catch direction.
230 | Optional argument FORWARD means change the direction to forward."
231 | (interactive)
232 | (setq-local sniem-object-catch-forward-p
233 | (if (or forward (null sniem-object-catch-forward-p))
234 | t
235 | nil))
236 | (message "[Sniem]: The object-catch-direction now is %s."
237 | (if sniem-object-catch-forward-p
238 | "forward"
239 | "backward")))
240 |
241 | (defun sniem-object-catch-format-point (prefix second-char)
242 | "Format point with the PREFIX.
243 | Argument SECOND-CHAR is the end char of the pair."
244 | (let ((times 1)
245 | tmp)
246 | (forward-char)
247 | (while (/= times 0)
248 | (setq tmp (buffer-substring-no-properties (point) (1+ (point))))
249 | (cond ((and (string= tmp prefix) (not (string= prefix second-char))
250 | (or (and sniem-object-catch-prefix-string-p
251 | (nth 3 (syntax-ppss)))
252 | (and (null sniem-object-catch-prefix-string-p)
253 | (null (nth 3 (syntax-ppss)))))
254 | (not (= (char-before) 92)))
255 | (setq times (1+ times)))
256 | ((and (string= tmp second-char) (> times 0)
257 | (not (= (char-before) 92))
258 | (or (and sniem-object-catch-prefix-string-p
259 | (nth 3 (syntax-ppss)))
260 | (and (null sniem-object-catch-prefix-string-p)
261 | (null (nth 3 (syntax-ppss))))))
262 | (setq times (1- times))))
263 | (forward-char))
264 | (point)))
265 |
266 | (defun sniem-object-catch-format-point2 (pair prefix-point)
267 | "Format point for the PAIR with same char.
268 | Argument PREFIX-POINT is the prefix point."
269 | (let ((region-forward-p (when (and (region-active-p) sniem-object-catch-forward-p)
270 | (prog1 (cons (region-beginning) (region-end))
271 | (deactivate-mark))))
272 | (face-eq-p (lambda (face1)
273 | (let ((face2 (get-text-property (point) 'face)))
274 | (when face2
275 | (ignore-errors
276 | (or (eq face1 face2)
277 | (memq face1 face2)
278 | (memq face2 face1)))))))
279 | prefix-face second-point tmp)
280 | (save-mark-and-excursion
281 | (goto-char prefix-point)
282 | (setq prefix-face (face-at-point))
283 | (cond ((or (progn ;Check if the faces of current char and the before one are same.
284 | (backward-char)
285 | (funcall face-eq-p prefix-face))
286 | (progn ;Check if the faces between current char and the previous one are same.
287 | (setq tmp (face-at-point))
288 | (when (search-backward pair nil t)
289 | (forward-char)
290 | (funcall face-eq-p tmp))))
291 | (setq second-point (sniem-object-catch-format-point1 pair prefix-point)
292 | prefix-point (sniem-object-catch-format-point1 pair prefix-point t t)))
293 |
294 | ((or (progn ;Check if the faces of current char and the after one are same.
295 | (goto-char prefix-point)
296 | (forward-char)
297 | (funcall face-eq-p prefix-face))
298 | (progn ;Check if the faces between current char and the next one are same.
299 | (setq tmp (face-at-point))
300 | (when (search-forward pair nil t)
301 | (backward-char 2)
302 | (funcall face-eq-p tmp))))
303 | (setq prefix-point (sniem-object-catch-format-point1 pair prefix-point nil t)
304 | second-point (sniem-object-catch-format-point1 pair (point) t))))
305 | (when region-forward-p
306 | (goto-char (car region-forward-p))
307 | (push-mark (cdr region-forward-p))))
308 | (cons prefix-point (1+ second-point))))
309 |
310 | (defun sniem-object-catch-format-point1 (pair point &optional search prefix)
311 | "Format the POINT for char.
312 | Argument PAIR is the pair."
313 | (save-mark-and-excursion
314 | (goto-char point)
315 | (let ((search-command (if prefix
316 | 'search-backward
317 | 'search-forward)))
318 | (when search
319 | (setq point (progn
320 | (funcall search-command pair)
321 | (unless prefix (backward-char))
322 | (point))))
323 | (when (sniem-object-catch-backslash-p)
324 | (setq point (progn
325 | (forward-char)
326 | (point)))
327 | (while (progn
328 | (setq point (funcall search-command pair))
329 | (sniem-object-catch-backslash-p)))))
330 | point))
331 |
332 | (defun sniem-object-catch-format-pointc (char)
333 | "Format the CHAR has same char in comment."
334 | (let (balone falone)
335 | (setq balone (sniem-object-catch--while-check-format char))
336 | (setq falone (sniem-object-catch--while-check-format char t))
337 | (if balone
338 | (cons balone (1+ (point)))
339 | (1+ falone))))
340 |
341 | (defun sniem-object-catch--while-check-format (char &optional forward)
342 | "Check the pair which has same CHAR in a while with the direction.
343 | When the FORWARD is non-nil, the direction is forward.
344 | Otherwise it's backward."
345 | (let ((command (if forward
346 | 'forward-char
347 | 'backward-char))
348 | current-char alone another-point)
349 | (save-mark-and-excursion
350 | (while (and (not (sniem-object-catch--border forward))
351 | (or (funcall command) t)
352 | (or (nth 8 (syntax-ppss))
353 | (ignore-errors
354 | (= (char-before) 10))
355 | (sniem-object-catch--face-around-eq)))
356 | (when (and (not (sniem-object-catch-backslash-p))
357 | (ignore-errors
358 | (setq current-char
359 | (buffer-substring-no-properties (point) (1+ (point)))))
360 | (string= char current-char))
361 | (cond ((null another-point)
362 | (setq another-point (point)))
363 | (alone (setq alone nil))
364 | (t (setq alone t))))))
365 | (unless alone
366 | another-point)))
367 |
368 | (defun sniem-object-catch--border (forward)
369 | "Check if it's border now.
370 | FORWARD means now it's forward direction."
371 | (if forward
372 | (eobp)
373 | (bobp)))
374 |
375 | (defun sniem-object-catch--face-around-eq ()
376 | "Check if the faces around the point are equal."
377 | (let ((face (face-at-point))
378 | lface rface)
379 | (save-mark-and-excursion
380 | (setq lface (progn
381 | (ignore-errors (backward-char))
382 | (face-at-point))
383 | rface (progn
384 | (ignore-errors (forward-char))
385 | (face-at-point))))
386 | (and (eq face lface)
387 | (eq face rface))))
388 |
389 | (defun sniem-object-catch--symbol-exists-p (symbol)
390 | "Check if the SYMBOL is exists."
391 | (catch 'exists
392 | (let ((index 0))
393 | (dolist (symbol-cons sniem-object-catch-global-symbol-alist)
394 | (when (string= symbol (car symbol-cons))
395 | (throw 'exists index))
396 | (setq index (1+ index))))))
397 |
398 | (defun sniem-object-catch--get-second-char (prefix)
399 | "Get the second char by the PREFIX."
400 | (let ((current-pairs (alist-get major-mode sniem-object-catch-global-symbol-alist))
401 | (default (alist-get prefix sniem-object-catch-global-symbol-alist
402 | nil nil 'equal))
403 | local)
404 | (cond ((and current-pairs
405 | (setq local (alist-get prefix current-pairs nil nil 'equal)))
406 | (if (string= local "")
407 | nil
408 | local))
409 | (t default))))
410 |
411 | (defun sniem-object-catch-backslash-p ()
412 | "Check if the char before current point is \\."
413 | (unless (bobp)
414 | (and (= 92 (char-before))
415 | (not (save-mark-and-excursion
416 | (backward-char)
417 | (if (bobp)
418 | t
419 | (= 92 (char-before))))))))
420 |
421 | (defun sniem-object-catch--index (ele list)
422 | "Get the index of LIST whose first item is equal to ELE."
423 | (catch 'index
424 | (let ((index 0))
425 | (dolist (item list)
426 | (when (equal ele (car item))
427 | (throw 'index index))
428 | (setq index (1+ index))))))
429 |
430 | (defun sniem-object-catch--append (ele list)
431 | "Like `add-to-list', but it will replace the origin, then return it.
432 |
433 | ELE is the element to add.
434 | LIST is the list for operating."
435 | (let (prefix tmp)
436 | (dotimes (n (length list))
437 | (setq prefix (car (nth n list)))
438 | (when (setq tmp (alist-get prefix ele nil nil 'string-equal))
439 | (setf (nth n list) (cons prefix tmp))
440 | (setq ele (delete (nth (sniem-object-catch--index prefix ele) ele) ele))))
441 | (append ele list)))
442 |
443 | (defmacro sniem-object-catch-mode-defalist (modename &rest alist)
444 | "Define ALIST for major mode.
445 | Argument MODENAME if the mode name."
446 | (declare (indent 1))
447 | `(let ((index (sniem-object-catch--index ',modename sniem-object-catch-global-symbol-alist)))
448 | (if index
449 | (setf (nth index sniem-object-catch-global-symbol-alist)
450 | (cons ',modename ',alist))
451 | (setq sniem-object-catch-global-symbol-alist
452 | (append (list (cons ',modename ',alist)) sniem-object-catch-global-symbol-alist)))))
453 |
454 | (provide 'sniem-object-catch)
455 |
456 | ;;; sniem-object-catch.el ends here
457 |
--------------------------------------------------------------------------------
/sniem-var.el:
--------------------------------------------------------------------------------
1 | ;;; sniem-var.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 |
6 | ;; This file is not part of GNU Emacs
7 |
8 | ;; This file is free software; you can redistribute it and/or modify
9 | ;; it under the terms of the GNU General Public License as published by
10 | ;; the Free Software Foundation; either version 3, or (at your option)
11 | ;; any later version.
12 |
13 | ;; This program is distributed in the hope that it will be useful,
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | ;; GNU General Public License for more details.
17 |
18 | ;; For a full copy of the GNU General Public License
19 | ;; see .
20 |
21 |
22 | ;;; Commentary:
23 |
24 | ;; Hands-eased united editing method.
25 |
26 | ;;; Code:
27 |
28 | (defcustom sniem-space-command nil
29 | "The command binded on SPC."
30 | :type 'symbol
31 | :group 'sniem)
32 |
33 | (defcustom sniem-initialized nil
34 | "If the sniem initialized."
35 | :type 'boolean
36 | :group 'sniem)
37 |
38 | (defcustom sniem-mode-keymap
39 | (let ((map (make-sparse-keymap)))
40 | map)
41 | "Mode keymap for sniem."
42 | :type 'keymap
43 | :group 'sniem)
44 |
45 | (defcustom sniem-last-point nil
46 | "The last point."
47 | :type 'number
48 | :group 'sniem)
49 |
50 | (defvar-local sniem-wrong-indentation nil
51 | "Whether emacs doesn't have suitable indentation for current file.")
52 |
53 | (defcustom sniem-last-point-overlay nil
54 | "The overlay for last point."
55 | :type 'overlay
56 | :group 'sniem)
57 |
58 | (defcustom sniem-last-point-locked nil
59 | "If the `sniem-last-point' is locked."
60 | :type 'boolean
61 | :group 'sniem)
62 |
63 | (defcustom sniem-keyboard-layout nil
64 | "User's keyboard layout."
65 | :type 'symbol
66 | :group 'sniem)
67 |
68 | (defcustom sniem-motion-hint-overlays nil
69 | "The list of all the motion hint overlays."
70 | :type 'list
71 | :group 'sniem)
72 |
73 | (defcustom sniem-motion-hint-sit-time 1
74 | "The time for motion hint sit."
75 | :type 'number
76 | :group 'sniem)
77 |
78 | (defcustom sniem-kmacro-range nil
79 | "The range for kmacro."
80 | :type 'overlay
81 | :group 'sniem)
82 |
83 | (defcustom sniem-kmacro-mark-content nil
84 | "The content which was marked by kmacro."
85 | :type 'string
86 | :group 'sniem)
87 |
88 | (defcustom sniem-mark-line nil
89 | "If in the mark line status."
90 | :type 'boolean
91 | :group 'sniem)
92 |
93 | (defcustom sniem-delete-edit nil
94 | "If it's in delete edit."
95 | :type 'boolean
96 | :group 'sniem)
97 |
98 | (defcustom sniem-change-edit nil
99 | "If it's in change edit."
100 | :type 'boolean
101 | :group 'sniem)
102 |
103 | (defcustom sniem-insert-to-normal-hook nil
104 | "The hook running when changing insert to normal."
105 | :type 'hook
106 | :group 'sniem)
107 |
108 | (defcustom sniem-normal-to-insert-hook nil
109 | "The hook running when changing normal to insert."
110 | :type 'hook
111 | :group 'sniem)
112 |
113 | (defvar sniem-normal-mode-cursor t
114 | "Cursor type for normal mode.")
115 |
116 | (defvar sniem-insert-mode-cursor 'bar
117 | "Cursor type for insert mode.")
118 |
119 | (defvar sniem-motion-mode-cursor t
120 | "Cursor type for motion mode.")
121 |
122 | (defvar sniem-insert-quit-key ""
123 | "The `sniem-quit-insert' key.")
124 |
125 | (defcustom sniem-leader-keymap
126 | (let ((map (make-sparse-keymap)))
127 | (define-key map "x" 'sniem-keypad)
128 | (define-key map "m" 'sniem-keypad)
129 | (define-key map "b" 'sniem-keypad)
130 | (define-key map "v" 'sniem-keypad)
131 | (define-key map "c" 'sniem-keypad)
132 | (define-key map "d" 'sniem-digit-argument)
133 | (define-key map (kbd "SPC") 'sniem-execute-space-command)
134 | (define-key map (kbd "TAB") 'sniem-shift)
135 | map)
136 | "Leader keymap."
137 | :type 'keymap
138 | :group 'sniem)
139 |
140 | (defcustom sniem-normal-state-keymap
141 | (let ((map (make-sparse-keymap)))
142 | (suppress-keymap map t)
143 | (define-key map "a" 'sniem-append)
144 | (define-key map "A" 'sniem-append-line)
145 | (define-key map "o" 'sniem-open-line)
146 | (define-key map "O" 'sniem-open-line-previous)
147 | (define-key map "s" 'sniem-search)
148 | (define-key map "S" 'save-buffer)
149 | (define-key map "r" 'sniem-replace-char)
150 | (define-key map "R" 'sniem-replace-word)
151 | (define-key map "z" 'sniem-center)
152 | (define-key map "x" 'sniem-delete-char)
153 | (define-key map "X" 'execute-extended-command)
154 | (define-key map "c" 'sniem-change)
155 | (define-key map "C" 'sniem-change-in-region)
156 | (define-key map "d" 'sniem-delete)
157 | (define-key map "D" 'sniem-delete-in-region)
158 | (define-key map "b" 'sniem-beginning-of-line)
159 | (define-key map "B" 'sniem-end-of-line)
160 | (define-key map "m" 'sniem-mark)
161 | (define-key map "M" 'sniem-expand-enter-or-quit)
162 | (define-key map "/" 'isearch-forward)
163 | (define-key map "w" 'sniem-next-word)
164 | (define-key map "W" 'sniem-prev-word)
165 | (define-key map "f" 'sniem-find-forward)
166 | (define-key map "F" 'sniem-find-backward)
167 | (define-key map "p" 'sniem-paste)
168 | (define-key map "P" 'sniem-paste-in-region)
169 | (define-key map "g" 'sniem-first-line)
170 | (define-key map "G" 'sniem-goto-line)
171 | (define-key map "y" 'sniem-yank)
172 | (define-key map "Y" 'sniem-yank-in-region)
173 | (define-key map "v" 'sniem-scroll-up-command)
174 | (define-key map "V" 'sniem-scroll-down-command)
175 | (define-key map "q" 'sniem-macro)
176 | (define-key map "Q" 'save-buffers-kill-terminal)
177 | (define-key map ";" 'sniem-keyboard-quit)
178 | (define-key map "'" 'sniem-mark-motion)
179 | (define-key map "\"" 'sniem-split-line)
180 | (define-key map "<" 'sniem-goto-prev)
181 | (define-key map ">" 'sniem-goto-next)
182 | (define-key map "`" 'sniem-up-down-case)
183 | (define-key map "1" 'digit-argument)
184 | (define-key map "2" 'digit-argument)
185 | (define-key map "3" 'digit-argument)
186 | (define-key map "4" 'digit-argument)
187 | (define-key map "5" 'digit-argument)
188 | (define-key map "6" 'digit-argument)
189 | (define-key map "7" 'digit-argument)
190 | (define-key map "8" 'digit-argument)
191 | (define-key map "9" 'digit-argument)
192 | (define-key map "0" 'digit-argument)
193 | (define-key map "-" 'kill-current-buffer)
194 | (define-key map "_" 'kill-buffer-and-window)
195 | (define-key map "." 'sniem-move-last-point)
196 | (define-key map "?" 'sniem-cheatsheet)
197 | (define-key map (kbd "SPC") 'sniem-digit-argument-or-fn)
198 | (define-key map (kbd "RET") 'sniem-expand-with-catch)
199 | (define-key map (kbd "TAB") 'sniem-shift)
200 | (define-key map (kbd "(") 'sniem-object-catch-char)
201 | (define-key map (kbd "[") 'sniem-object-catch-char)
202 | (define-key map (kbd "{") 'sniem-object-catch-char)
203 | (define-key map (kbd ")") 'sniem-object-catch-parent)
204 | (define-key map (kbd "]") 'sniem-object-catch-parent)
205 | (define-key map (kbd "}") 'sniem-object-catch-parent)
206 | (define-key map (kbd "") 'sniem-object-catch-parent-by-char)
207 | (define-key map (kbd "C-") 'sniem-object-catch-by-char)
208 | (define-key map (kbd "M-") 'sniem-object-catch-parent)
209 | (define-key map (kbd "DEL") 'sniem-backward-char)
210 | map)
211 | "Normal mode keymap."
212 | :type 'keymap
213 | :group 'sniem)
214 |
215 | (defcustom sniem-insert-state-keymap
216 | (let ((map (make-sparse-keymap)))
217 | (define-key map (kbd "") 'sniem-quit-insert)
218 | map)
219 | "Insert mode keymap."
220 | :type 'keymap
221 | :group 'sniem)
222 |
223 | (defcustom sniem-motion-state-keymap
224 | (let ((map (make-sparse-keymap)))
225 | (define-key map (kbd "SPC") sniem-leader-keymap)
226 | map)
227 | "Motion mode keymap."
228 | :type 'keymap
229 | :group 'sniem)
230 |
231 | (defcustom sniem-expand-state-keymap
232 | (let ((map (make-sparse-keymap)))
233 | (define-key map [remap self-insert-command] 'sniem-expand-enter-or-quit)
234 | (define-key map (kbd "TAB") 'sniem-shift)
235 | (define-key map (kbd "RET") 'sniem-object-catch)
236 | (define-key map "p" 'sniem-object-catch-parent)
237 | (define-key map "r" 'sniem-object-catch-repeat)
238 | (define-key map "b" 'sniem-object-catch-by-char)
239 | (define-key map "B" 'sniem-object-catch-parent-by-char)
240 | (define-key map "s" 'sniem-object-catch-char)
241 | (define-key map "S" 'sniem-object-catch-parent)
242 | (define-key map "o" 'sniem-object-catch-char)
243 | (define-key map "O" 'sniem-object-catch-parent)
244 | (define-key map "c" 'sniem-object-catch-char)
245 | (define-key map "C" 'sniem-object-catch-parent)
246 | (define-key map "q" 'sniem-object-catch-char)
247 | (define-key map "Q" 'sniem-object-catch-parent)
248 | (define-key map "a" 'sniem-object-catch-char)
249 | (define-key map "A" 'sniem-object-catch-parent)
250 | (define-key map "d" 'sniem-object-catch-char)
251 | (define-key map "D" 'sniem-object-catch-parent)
252 | (define-key map "/" 'sniem-object-catch-direction-reverse)
253 | (define-key map "." 'sniem-object-catch-expand)
254 | map)
255 | "Expand mode keymap."
256 | :type 'keymap
257 | :group 'sniem)
258 |
259 | (defcustom sniem-minibuffer-keypad-state-keymap
260 | (let ((map (make-sparse-keymap)))
261 | (define-key map [remap self-insert-command] 'sniem-minibuffer-keypad)
262 | (define-key map (kbd "SPC") 'sniem-minibuffer-keypad-start-or-stop)
263 | map)
264 | "The keymap for minibuffer-keypad state."
265 | :type 'keymap
266 | :group 'sniem)
267 |
268 | (defcustom sniem-motion-hint-motion nil
269 | "The last hint motion."
270 | :type 'symbol
271 | :group 'sniem)
272 |
273 | (defcustom sniem-mark-content-overlay '(nil nil)
274 | "The mark content overlay.
275 | The first element stores untagged contents.
276 | The other one stores tagged contents."
277 | :type 'list
278 | :group 'sniem)
279 |
280 | (defcustom sniem-search-result-tip nil
281 | "The tip of the search result."
282 | :type 'overlay
283 | :group 'sniem)
284 |
285 | (defcustom sniem-locked-macro nil
286 | "The locked kmacro."
287 | :type 'symbol
288 | :group 'sniem)
289 |
290 | (defcustom sniem-macro-file nil
291 | "The file to store kbd macros."
292 | :type 'string
293 | :group 'sniem)
294 |
295 | (defcustom sniem-mark-content-file
296 | (locate-user-emacs-file "sniem-marked-content")
297 | "The file used to store marked-content."
298 | :type 'string
299 | :group 'sniem)
300 |
301 | (defcustom sniem-search-timer nil
302 | "The timer for searching."
303 | :type 'timer
304 | :group 'sniem)
305 |
306 | (defcustom sniem-mark-ov-check-timer nil
307 | "The timer used to avoid disappearance of mark-content overlay."
308 | :type 'timer
309 | :group 'sniem)
310 |
311 | (defcustom sniem-motion-hint-remove-timer nil
312 | "The timer used to remove motion hint."
313 | :type 'timer
314 | :group 'sniem)
315 |
316 | (defcustom sniem-search-result-overlays nil
317 | "The overlays for search results."
318 | :type 'list
319 | :group 'sniem)
320 |
321 | (defcustom sniem-special-clipboard nil
322 | "The special clipboard list."
323 | :type 'list
324 | :group 'sniem)
325 |
326 | (defcustom sniem-minibuffer-keypad-on nil
327 | "If the minibuffer-keypad mode is opened."
328 | :type 'boolean
329 | :group 'sniem)
330 |
331 | (defcustom sniem-minibuffer-keypad-prefix "C-"
332 | "The prefix for minibuffer-keypad."
333 | :type 'string
334 | :group 'sniem)
335 |
336 | (defcustom sniem-shift-binding-key 9
337 | "The key for `sniem-shift'. It's char."
338 | :type 'number
339 | :group 'sniem)
340 |
341 | (defcustom sniem-shift-times 1
342 | "The times pressing shift in one interaction."
343 | :type 'number
344 | :group 'sniem)
345 |
346 | (defcustom sniem-shift-lock nil
347 | "If it is t, you can use upper case defaultly."
348 | :type 'boolean
349 | :group 'sniem)
350 |
351 | (defcustom sniem-mark-next-expanding nil
352 | "A character list, which includes splitted expanding connectors.
353 | When the list is not empty, checking whether the next character
354 | is the firts element of list.
355 |
356 | It can be like: (length . (character1 character 2))."
357 | :type 'list
358 | :group 'sniem)
359 |
360 | (defcustom sniem-object-catch-global-symbol-alist
361 | '((emacs-lisp-mode . (("'" . "") ("`" . "'") ("<" . "")))
362 | ("\"" . "\"")
363 | ("'" . "'")
364 | ("[" . "]")
365 | ("<" . ">")
366 | ("(" . ")")
367 | ("{" . "}"))
368 | "The global symbol alist."
369 | :type 'list
370 | :group 'sniem)
371 |
372 | (defcustom sniem-mark-connectors
373 | '((emacs-lisp-mode "<" ">" "!" "@" "#" "$" "%" "^" "&" "*" "-"
374 | "_" "=" "+" "\\" "|" "," "." "/" ":" "?")
375 | (c-mode :expand ("&" "*" (":" ":") ("-" ">")))
376 | (c++-mode :expand ("&" "*" (":" ":") ("-" ">")))
377 | (python-mode :expand ("."))
378 | (makefile-mode "-")
379 | (rust-mode :expand ("." "&" (":" ":")))
380 | (haskell-mode :expand ("."))
381 | (dart-mode :expand ("."))
382 | (global "_"))
383 | "The connectors when marking symbol."
384 | :type 'list
385 | :group 'sniem)
386 |
387 | (defcustom sniem-ignore-marked-content nil
388 | "Temporarily ignore marked content, making the priority of last-point upper."
389 | :type 'boolean
390 | :group 'sniem)
391 |
392 | (defcustom sniem-enter-command nil
393 | "The enter command of current buffer."
394 | :type 'symbol
395 | :group 'sniem)
396 |
397 | (defvar sniem-normal-mode-alist
398 | '(fundamental-mode text-mode prog-mode conf-mode cider-repl-mode
399 | json-mode wdired-mode deft-mode pass-view-mode telega-chat-mode
400 | restclient-mode help-mode deadgrep-edit-mode mix-mode authinfo-mode)
401 | "The alist of major modes that make sniem open normal mode.")
402 |
403 | (defvar sniem-insert-mode-alist '(shell-mode eshell-mode vterm-mode inferior-emacs-lisp-mode erc-mode term-mode)
404 | "The alist of major modes that make sniem open insert mode.")
405 |
406 | (defvar sniem-input-method-closed nil
407 | "If the input method was closed when user changed to normal state.")
408 |
409 | (defvar sniem-close-mode-alist nil
410 | "The modes alist for close sniem.")
411 |
412 | (defvar sniem-center-message "[z]Center, [t]op, [b]uttom:"
413 | "The message for `sniem-center'.")
414 |
415 | (defvar sniem-mark-message "[m]Normal mark, [p]Mark to last point, [l]ine, [w]ord, [s]ymbol, [SPC]Mark with space around:"
416 | "The message for `sniem-mark'.")
417 |
418 | (defvar sniem-delete-message "[d]Line, [p]Delete from last point, [D]Clear line contents:"
419 | "The message for `sniem-delete'.")
420 |
421 | (defvar sniem-change-message "[c]Line, [p]From last point:"
422 | "The message for `sniem-delete'.")
423 |
424 | (defvar sniem-yank-message "[y]Line, [p]From last point:"
425 | "The message for `sniem-yank'.")
426 |
427 | (defvar sniem-macro-message
428 | "[q]Record, [e]val kmacro, [n]ame for kmacro, [l]ock or unlock kmacro, [.]Forcibly lock kmacro, [c]all kmacro, [i]nsert named kmacro, [;]Clear macro cache:"
429 | "The message for `sniem-macro'.")
430 |
431 | (defvar sniem-pair-message
432 | "[a]Forcibly add pair, [s]Add or delete space around, other keys means pair(like '['):"
433 | "The message for `sniem-pair'.")
434 |
435 | (defvar sniem-paste-message
436 | (propertize "[n]: next page, [p]: prev page or 1, [1-4]: insert content, [q]: cancel"
437 | 'face 'font-lock-comment-face)
438 | "The message for `sniem-paste'.")
439 |
440 | (defvar sniem-linked-file-message "[r] for Root file, [l] for Linked file, [s] for Save, [o] for Open, [c] for Clean"
441 | "The message for `sniem-linked-file'.")
442 |
443 | (defface sniem-motion-hint-face
444 | `((t (:foreground ,(frame-parameter nil 'background-color)
445 | :background ,(frame-parameter nil 'foreground-color))))
446 | "The face for motion hint."
447 | :group 'sniem)
448 |
449 | (defface sniem-edit-content-face
450 | `((t (:foreground ,(frame-parameter nil 'foreground-color)
451 | :background "#FF0000")))
452 | "The face of edit content."
453 | :group 'sniem)
454 |
455 | (provide 'sniem-var)
456 |
457 | ;;; sniem-var.el ends here
458 |
--------------------------------------------------------------------------------
/sniem.el:
--------------------------------------------------------------------------------
1 | ;;; sniem.el --- Hands-eased united editing method -*- lexical-binding: t -*-
2 |
3 | ;; Author: SpringHan
4 | ;; Maintainer: SpringHan
5 | ;; Version: 1.2
6 | ;; Package-Requires: ((emacs "27.1") (s "2.12.0") (dash "1.12.0"))
7 | ;; Homepage: https://github.com/SpringHan/sniem.git
8 | ;; Keywords: convenience, united-editing-method
9 |
10 |
11 | ;; This file is not part of GNU Emacs
12 |
13 | ;; This file is free software; you can redistribute it and/or modify
14 | ;; it under the terms of the GNU General Public License as published by
15 | ;; the Free Software Foundation; either version 3, or (at your option)
16 | ;; any later version.
17 |
18 | ;; This program is distributed in the hope that it will be useful,
19 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 | ;; GNU General Public License for more details.
22 |
23 | ;; For a full copy of the GNU General Public License
24 | ;; see .
25 |
26 |
27 | ;;; Commentary:
28 |
29 | ;; Hands-eased united editing method.
30 |
31 | ;;; Code:
32 |
33 | (require 's)
34 | (require 'dash)
35 |
36 | (defgroup sniem nil
37 | "The group for sniem."
38 | :group 'applications)
39 |
40 | (require 'sniem-var)
41 | (require 'sniem-macro)
42 | (require 'sniem-operation)
43 | (require 'sniem-object-catch)
44 | (require 'sniem-cheatsheet)
45 | (require 'sniem-mark-jump)
46 | (require 'sniem-linked-file)
47 |
48 |
49 | (define-minor-mode sniem-mode
50 | "Hands-eased united editing method mode."
51 | nil nil sniem-mode-keymap
52 | (if sniem-mode
53 | (sniem--enable)
54 | (sniem--disable)))
55 |
56 | ;;;###autoload
57 | (define-globalized-minor-mode global-sniem-mode
58 | sniem-mode sniem-initialize)
59 |
60 | ;;;###autoload
61 | (define-minor-mode sniem-normal-mode
62 | "Normal mode for sniem."
63 | nil nil sniem-normal-state-keymap
64 | (if sniem-normal-mode
65 | (sniem-normal-mode-init)
66 | (sniem-search--cancel-selection)))
67 |
68 | ;;;###autoload
69 | (define-minor-mode sniem-insert-mode
70 | "Insert mode for sniem."
71 | nil nil sniem-insert-state-keymap
72 | (when sniem-insert-mode
73 | (sniem-insert-mode-init)))
74 |
75 | ;;;###autoload
76 | (define-minor-mode sniem-motion-mode
77 | "Motion mode for sniem."
78 | nil nil sniem-motion-state-keymap
79 | (when sniem-motion-mode
80 | (sniem-motion-mode-init)))
81 |
82 | ;;;###autoload
83 | (define-minor-mode sniem-expand-mode
84 | "Expand mode for sniem."
85 | nil nil sniem-expand-state-keymap
86 | (when sniem-expand-mode
87 | (sniem-expand-mode-init)))
88 |
89 | ;;;###autoload
90 | (define-minor-mode sniem-minibuffer-keypad-mode
91 | nil nil sniem-minibuffer-keypad-state-keymap
92 | (when sniem-minibuffer-keypad-mode
93 | (sniem-minibuffer-keypad-mode-init)))
94 |
95 | (defun sniem-normal-mode-init ()
96 | "Normal mode init."
97 | (sniem-insert-mode -1)
98 | (sniem-motion-mode -1)
99 | (sniem-expand-mode -1)
100 | (sniem-minibuffer-keypad-mode -1)
101 | (when current-input-method
102 | (toggle-input-method)
103 | (setq-local sniem-input-method-closed t)))
104 |
105 | (defun sniem-insert-mode-init ()
106 | "Insert mode init."
107 | (sniem-normal-mode -1)
108 | (sniem-motion-mode -1)
109 | (sniem-expand-mode -1)
110 | (sniem-minibuffer-keypad-mode -1)
111 | (when sniem-input-method-closed
112 | (toggle-input-method)
113 | (setq-local sniem-input-method-closed nil)))
114 |
115 | (defun sniem-motion-mode-init ()
116 | "Motion mode init."
117 | (sniem-normal-mode -1)
118 | (sniem-insert-mode -1)
119 | (sniem-expand-mode -1)
120 | (sniem-minibuffer-keypad-mode -1))
121 |
122 | (defun sniem-expand-mode-init ()
123 | "Expand mode init."
124 | (sniem-normal-mode -1)
125 | (sniem-insert-mode -1)
126 | (sniem-motion-mode -1)
127 | (sniem-minibuffer-keypad-mode -1))
128 |
129 | (defun sniem-minibuffer-keypad-mode-init ()
130 | "Minibuffer-keypad mode init."
131 | (sniem-normal-mode -1)
132 | (sniem-insert-mode -1)
133 | (sniem-motion-mode -1)
134 | (sniem-expand-mode -1))
135 |
136 | (defun sniem--enable ()
137 | "Unable sniem."
138 | (unless (apply #'derived-mode-p sniem-close-mode-alist)
139 | (unless sniem-space-command
140 | (setq-local sniem-space-command (key-binding (kbd "SPC"))))
141 | (cond ((apply #'derived-mode-p sniem-normal-mode-alist)
142 | (sniem-change-mode 'normal))
143 | ((apply #'derived-mode-p sniem-insert-mode-alist)
144 | (sniem-change-mode 'insert))
145 | ((minibufferp))
146 | (t (sniem-change-mode 'motion)))
147 | (setq sniem-mark-ov-check-timer
148 | (run-with-idle-timer 2 3 #'sniem--mark-refresh-timer))
149 | (unless sniem-initialized
150 | (add-to-ordered-list 'emulation-mode-map-alists
151 | `((sniem-minibuffer-keypad-mode . ,sniem-minibuffer-keypad-state-keymap)))
152 | (add-to-ordered-list 'emulation-mode-map-alists
153 | `((sniem-expand-mode . ,sniem-expand-state-keymap)))
154 | (add-to-ordered-list 'emulation-mode-map-alists
155 | `((sniem-motion-mode . ,sniem-motion-state-keymap)))
156 | (add-to-ordered-list 'emulation-mode-map-alists
157 | `((sniem-normal-mode . ,sniem-normal-state-keymap)))
158 | (sniem-init-hook)
159 | (sniem-init-advice)
160 | (when (featurep 'awesome-tray)
161 | (defvar awesome-tray-module-alist)
162 | (add-to-list 'awesome-tray-module-alist '("sniem-state" . (sniem-state awesome-tray-module-evil-face))))
163 | (setq sniem-initialized t))))
164 |
165 | (defun sniem--disable ()
166 | "Disable sniem."
167 | (sniem-normal-mode -1)
168 | (sniem-insert-mode -1)
169 | (sniem-motion-mode -1)
170 | (cancel-timer sniem-mark-ov-check-timer)
171 | (setq sniem-mark-ov-check-timer nil)
172 | (when sniem-initialized
173 | (sniem-init-hook)
174 | (sniem-init-advice)
175 | (setq sniem-initialized nil)))
176 |
177 | ;;; Interactive functions
178 |
179 | (defun sniem-expand-with-catch ()
180 | "Enter expand mode with object catch."
181 | (interactive)
182 | (sniem-object-catch)
183 | (sniem-expand-mode t))
184 |
185 | (defun sniem-expand-enter-or-quit ()
186 | "Enter or Quit expand mode.
187 | Normally, if the function is called by user,
188 | quiting expand mode."
189 | (interactive)
190 | (if sniem-expand-mode
191 | (progn
192 | (when sniem-object-catch-expand-p
193 | (sniem-object-catch-expand))
194 | (when (and sniem-object-catch-auto-backward
195 | sniem-object-catch-forward-p)
196 | (setq-local sniem-object-catch-forward-p nil))
197 | (sniem-change-mode 'normal)
198 |
199 | ;; NOTE: Press any other unbounded keys to exit expand mode.
200 | (unless (eq last-input-event 32)
201 | (call-interactively (key-binding (read-kbd-macro (char-to-string last-input-event))))))
202 |
203 | (sniem-change-mode 'expand)))
204 |
205 | (defun sniem-execute-space-command ()
206 | "Execute space command."
207 | (interactive)
208 | (call-interactively sniem-space-command))
209 |
210 | (defun sniem-quit-insert ()
211 | "Quit insert mode."
212 | (interactive)
213 | (sniem-change-mode 'normal))
214 |
215 | (defun sniem-keypad (&optional external-char no-convert pre-arg)
216 | "Execute the keypad command.
217 | EXTERNAL-CHAR is the entrance from minibuffer-keypad mode.
218 | NO-CONVERT means not to convert the EXTERNAL-CHAR to prefix.
219 | PRE-ARG is the prefix arg."
220 | (interactive (list nil nil current-prefix-arg))
221 | (let* ((prefix-used-p nil)
222 | ;; TODO: External-char -> Perhaps the char used to entrance.
223 | ;; Key is the key binding of final result..
224 | (key (if external-char
225 | (if (and (null no-convert)
226 | (memq external-char '(?, ?. ?/))
227 | (/= (sniem-keypad--convert-prefix
228 | sniem-minibuffer-keypad-prefix)
229 | external-char))
230 | (progn
231 | (setq-local sniem-minibuffer-keypad-prefix
232 | (sniem-keypad--convert-prefix external-char))
233 | (setq external-char t
234 | prefix-used-p t)
235 | sniem-minibuffer-keypad-prefix)
236 |
237 | ;; Execute when in minibuffer-keypad-mode
238 | (concat sniem-minibuffer-keypad-prefix
239 | (char-to-string external-char)
240 | " "))
241 |
242 | ;; When the user entered keypad with sniem-leader:
243 | (pcase last-input-event
244 | (?m "M-") (?b "C-M-") (?v "C-")
245 | (_ (concat "C-" (char-to-string last-input-event) " ")))))
246 | tmp command shift)
247 |
248 | (message key)
249 | (catch 'stop
250 | (while t
251 | (when (and (string-equal (substring key -1) " ")
252 | (commandp (setq command (key-binding
253 | (read-kbd-macro (substring key 0 -1))))))
254 | (throw 'stop nil))
255 | (setq tmp (if shift
256 | (progn
257 | (setq shift nil)
258 | (sniem-shift-convert (read-char)
259 | sniem-shift-binding-key))
260 | (read-char)))
261 | (if (= tmp 127) ;DEL
262 | (setq key (substring key 0 -2))
263 | (when (= tmp 59) ; 59 is ;
264 | (keyboard-quit))
265 | (setq key (concat key
266 | (cond ((and (= tmp ?,)
267 | (null prefix-used-p))
268 | (setq prefix-used-p t)
269 | "C-")
270 | ((and (= tmp ?.)
271 | (null prefix-used-p))
272 | (setq prefix-used-p t)
273 | "M-")
274 | ((and (= tmp ?/)
275 | (null prefix-used-p))
276 | (setq prefix-used-p t)
277 | "C-M-")
278 | ((= tmp 32)
279 | (setq prefix-used-p t)
280 | "")
281 | ((= tmp 9) ;Tab
282 | (setq shift t)
283 | "")
284 | ((/= tmp 0)
285 | (when prefix-used-p
286 | (setq prefix-used-p nil))
287 | (concat (char-to-string tmp) " "))))))
288 | (message key)))
289 | (when pre-arg
290 | (setq prefix-arg pre-arg))
291 | (setq this-command command)
292 | (setq real-this-command command)
293 | (command-execute command 'record)))
294 |
295 | (defun sniem-move-last-point ()
296 | "Move the last point to current point."
297 | (interactive)
298 | (setq-local sniem-last-point (point))
299 | (sniem-lock-unlock-last-point))
300 |
301 | (defun sniem-lock-unlock-last-point (&optional lock)
302 | "Lock or unlock `sniem-last-point'.
303 | When LOCK is non-nil, forcibly lock the last point."
304 | (interactive)
305 | (if sniem-search-result-overlays
306 | (sniem-mark-content t)
307 | (setq-local sniem-last-point-locked (if (and (null lock) sniem-last-point-locked)
308 | nil
309 | t))
310 | (sniem-show-last-point (not sniem-last-point-locked))
311 | (message "[Sniem]: Last point %s." (if sniem-last-point-locked
312 | "locked"
313 | "unlocked"))))
314 |
315 | (defun sniem-keyboard-quit ()
316 | "Like `keyboard-quit'.
317 | But when it's recording kmacro and there're region, deactivate mark."
318 | (interactive)
319 | (if (and (region-active-p) defining-kbd-macro)
320 | (deactivate-mark)
321 | (keyboard-quit)))
322 |
323 | (defun sniem-special-clipboard-pop ()
324 | "Pop the last content in special clipboard."
325 | (interactive)
326 | (setq sniem-special-clipboard
327 | (delete (nth (1- (length sniem-special-clipboard))
328 | sniem-special-clipboard)
329 | sniem-special-clipboard))
330 | (message "[Sniem]: Popped the special clipboard."))
331 |
332 | (defun sniem-special-clipboard-clear ()
333 | "Clear the special clipboard."
334 | (interactive)
335 | (setq sniem-special-clipboard nil)
336 | (message "[Sniem]: Cleared the special clipboard."))
337 |
338 | (defun sniem-minibuffer-keypad-start-or-stop ()
339 | "Start or stop the minibuffer-keypad mode."
340 | (interactive)
341 | ;; NOTE: Pressed space:
342 | (if current-input-method
343 | (if (and (= (char-before) 32)
344 | (not (= (point) (line-beginning-position))))
345 | (progn
346 | (sniem-minibuffer-keypad-mode (if sniem-minibuffer-keypad-mode
347 | -1
348 | t))
349 | (call-interactively (key-binding (read-kbd-macro (char-to-string 127)))))
350 | (self-insert-command 1 32))
351 | (self-insert-command 1 32)
352 | (let ((char (read-char)))
353 | (if (= 32 char)
354 | (progn
355 | (sniem-minibuffer-keypad-mode (if sniem-minibuffer-keypad-mode
356 | -1
357 | t))
358 | (call-interactively (key-binding (read-kbd-macro (char-to-string 127)))))
359 | (if (and sniem-minibuffer-keypad-mode
360 | (memq char '(?, ?. ?/)))
361 | (progn
362 | (call-interactively (key-binding (read-kbd-macro (char-to-string 127))))
363 | (sniem-keypad char t))
364 | (sniem-minibuffer-keypad))))))
365 |
366 | (defun sniem-minibuffer-keypad ()
367 | "The function to insert the input key or execute the function."
368 | (interactive)
369 | (if sniem-minibuffer-keypad-mode
370 | (sniem-keypad last-input-event)
371 | ;; TODO: Symbolp ?
372 | (if (or (symbolp last-input-event)
373 | (< last-input-event ?!)
374 | (> last-input-event ?~))
375 | (progn
376 | (let (command)
377 | (if (commandp (setq command
378 | (key-binding
379 | (vector last-input-event))))
380 | (let ((last-command-event last-input-event))
381 | (ignore-errors
382 | (call-interactively command)))
383 | (execute-kbd-macro (vector last-input-event)))))
384 | (let ((last-command-event last-input-event))
385 | (call-interactively #'self-insert-command)))))
386 |
387 | ;;; Functional functions
388 |
389 | (defun sniem-initialize ()
390 | "Initialize sniem."
391 | (sniem-mode t))
392 |
393 | (defun sniem-cursor-change ()
394 | "Change cursor type."
395 | (setq-local cursor-type (pcase (sniem-current-mode)
396 | ('normal sniem-normal-mode-cursor)
397 | ('insert sniem-insert-mode-cursor)
398 | ('motion sniem-motion-mode-cursor)
399 | (_ cursor-type))))
400 |
401 | (defun sniem-set-leader-key (key)
402 | "Set the leader KEY for normal mode."
403 | (define-key sniem-normal-state-keymap (kbd key) sniem-leader-keymap))
404 |
405 | (defun sniem-leader-set-key (&rest keys)
406 | "Bind key to leader keymap.
407 |
408 | \(fn KEY FUNC...)
409 | Optional argument KEYS are the keys you want to add."
410 | (let (key func)
411 | (while keys
412 | (setq key (pop keys)
413 | func (pop keys))
414 | (define-key sniem-leader-keymap (kbd key) func))))
415 |
416 | (defun sniem-normal-set-key (&rest keys)
417 | "Bind key to normal mode keymap.
418 |
419 | \(fn KEY FUNC...)
420 | Optional argument KEYS are the keys you want to add."
421 | (let (key func)
422 | (while keys
423 | (setq key (pop keys)
424 | func (pop keys))
425 | (define-key sniem-normal-state-keymap (kbd key) func))))
426 |
427 | (defun sniem-expand-set-key (&rest keys)
428 | "Bind key to expand mode keymap.
429 |
430 | \(fn KEY FUNC...)
431 | Optional argument KEYS are the keys you want to add."
432 | (let (key func)
433 | (while keys
434 | (setq key (pop keys)
435 | func (pop keys))
436 | (define-key sniem-expand-state-keymap (kbd key) func))))
437 |
438 | (defun sniem-mark-set-connector (mode &rest connector)
439 | "Set special CONNECTOR pair for MODE to mark symbol more accurately."
440 | (let ((index (sniem-object-catch--index mode sniem-mark-connectors)))
441 | (if index
442 | (setf (nth index sniem-mark-connectors)
443 | (append (list mode) connector))
444 | (add-to-list 'sniem-mark-connectors
445 | (append (list mode) connector)))))
446 |
447 | (defun sniem-set-keyboard-layout (layout)
448 | "Set the keyboard layout, then you can use the default keymap for your layout.
449 |
450 | LAYOUT can be qwerty, colemak or dvorak."
451 | (cond
452 | ((eq layout 'qwerty)
453 | (sniem-normal-set-key
454 | "e" 'sniem-join
455 | "u" 'undo
456 | "k" 'sniem-prev-line
457 | "K" 'sniem-5-prev-line
458 | "j" 'sniem-next-line
459 | "J" 'sniem-5-next-line
460 | "i" 'sniem-insert
461 | "I" 'sniem-insert-line
462 | "h" 'sniem-backward-char
463 | "H" 'sniem-5-backward-char
464 | "l" 'sniem-forward-char
465 | "L" 'sniem-5-forward-char
466 | "n" 'sniem-lock-unlock-last-point
467 | "N" 'sniem-goto-last-point
468 | "t" 'sniem-next-symbol
469 | "T" 'sniem-prev-symbol)
470 | (setq sniem-keyboard-layout 'qwerty))
471 | ((eq layout 'colemak)
472 | (sniem-normal-set-key
473 | "j" 'sniem-join
474 | "l" 'undo
475 | "u" 'sniem-prev-line
476 | "U" 'sniem-5-prev-line
477 | "e" 'sniem-next-line
478 | "E" 'sniem-5-next-line
479 | "h" 'sniem-insert
480 | "H" 'sniem-insert-line
481 | "n" 'sniem-backward-char
482 | "N" 'sniem-5-backward-char
483 | "i" 'sniem-forward-char
484 | "I" 'sniem-5-forward-char
485 | "k" 'sniem-lock-unlock-last-point
486 | "K" 'sniem-goto-last-point
487 | "t" 'sniem-next-symbol
488 | "T" 'sniem-prev-symbol)
489 | (setq sniem-keyboard-layout 'colemak))
490 | ((or (eq layout 'dvorak)
491 | (eq layout 'dvp))
492 | (sniem-normal-set-key
493 | "j" 'sniem-join
494 | "u" 'undo
495 | "e" 'sniem-prev-line
496 | "E" 'sniem-5-prev-line
497 | "n" 'sniem-next-line
498 | "N" 'sniem-5-next-line
499 | "i" 'sniem-insert
500 | "I" 'sniem-insert-line
501 | "h" 'sniem-backward-char
502 | "H" 'sniem-5-backward-char
503 | "t" 'sniem-forward-char
504 | "T" 'sniem-5-forward-char
505 | "k" 'sniem-lock-unlock-last-point
506 | "K" 'sniem-goto-last-point
507 | "l" 'sniem-next-symbol
508 | "L" 'sniem-prev-symbol)
509 | (setq sniem-keyboard-layout (if (eq layout 'dvp)
510 | 'dvp
511 | 'dvorak)))
512 | (t (user-error "[Sniem]: The %s layout is not supplied!" layout))))
513 |
514 | (defun sniem-current-mode ()
515 | "Get current mode."
516 | (cond (sniem-normal-mode 'normal)
517 | (sniem-insert-mode 'insert)
518 | (sniem-motion-mode 'motion)
519 | (sniem-expand-mode 'expand)
520 | (sniem-minibuffer-keypad-mode 'minibuffer-keypad)
521 | (t nil)))
522 |
523 | (defun sniem-change-mode (mode)
524 | "Change editing MODE."
525 | (let ((current-mode (sniem-current-mode)))
526 | (unless (eq current-mode mode)
527 | (pcase mode
528 | ('normal (sniem-normal-mode t)
529 | (when (eq current-mode 'insert)
530 | (run-hooks 'sniem-insert-to-normal-hook)))
531 | ('insert (sniem-insert-mode t)
532 | (when (eq current-mode 'normal)
533 | (run-hooks 'sniem-normal-to-insert-hook)))
534 | ('motion (sniem-motion-mode t))
535 | ('expand (sniem-expand-mode t))
536 | ('minibuffer-keypad (sniem-minibuffer-keypad-mode t)))
537 | (sniem-cursor-change))))
538 |
539 | (defun sniem-digit-argument-or-fn (arg)
540 | "The digit argument function.
541 | Argument ARG is the `digit-argument' result."
542 | (interactive (list (ignore-errors (sniem-digit-argument-get))))
543 | (unless arg
544 | (setq arg '(4)))
545 | (if (and (listp arg)
546 | (> (length arg) 1))
547 | (eval arg)
548 | (prefix-command-preserve-state)
549 | (setq prefix-arg arg)
550 | (universal-argument--mode)))
551 |
552 | (defun sniem-digit-argument-fn-get (string)
553 | "Read the fn for `sniem-digit-argument-or-fn'.
554 | Argument STRING is the string get from the input."
555 | (pcase string
556 | ("." 'sniem-mark-content)
557 | ("k" 'sniem-unmark-content-select-it)
558 | ("K" 'sniem-mark-content-pop)
559 | (" " 'sniem-move-with-hint-num)
560 | ("/" 'sniem-object-catch-direction-reverse)
561 | ("," 'sniem-object-catch-repeat)
562 | ("p" 'sniem-pair)
563 | ("m" 'sniem-mark-jump-insert-with-name)
564 | ("<" 'sniem-mark-jump-prev)
565 | (">" 'sniem-mark-jump-next)
566 | ("c" 'sniem-special-clipboard-clear)
567 | ("x" 'sniem-special-clipboard-pop)
568 | ("f" 'sniem-linked-file-pannel) ;NOTE: Maybe useless
569 | ("R" 'sniem-edit-marked-content)
570 | ("I" 'sniem-ignore-or-enable-marked-content)
571 | ("T" 'sniem-handle-tag-mark)
572 | ("j" 'sniem-jump-to-tag-mark)
573 | ("N" 'sniem-ignore-or-enable-indentation)
574 | ("P" (lambda ()
575 | (interactive)
576 | (funcall-interactively #'sniem-paste nil t)))
577 | ("y" (lambda ()
578 | (interactive)
579 | (funcall-interactively #'sniem-yank nil t)))
580 | ("Y" (lambda ()
581 | (interactive)
582 | (sniem-yank-in-region t)))))
583 |
584 | (defun sniem-digit-argument-read-char ()
585 | "Read char for `sniem-digit-argument'."
586 | (pcase sniem-keyboard-layout
587 | ('colemak
588 | (pcase (read-char)
589 | (97 "1") (114 "2") (115 "3") (116 "4") (100 "5")
590 | (104 "6") (110 "7") (101 "8") (105 "9") (111 "0")
591 | (39 "-") (13 "over") (127 "delete") (59 nil)
592 | (9 (char-to-string (sniem-shift-convert (read-char) sniem-shift-binding-key)))
593 | (x (char-to-string x))))
594 | ('qwerty
595 | (pcase (read-char)
596 | (97 "1") (115 "2") (100 "3") (102 "4") (103 "5")
597 | (104 "6") (106 "7") (107 "8") (108 "9") (59 "0")
598 | (39 "-") (13 "over") (127 "delete") (92 nil)
599 | (9 (char-to-string (sniem-shift-convert (read-char) sniem-shift-binding-key)))
600 | (x (char-to-string x))))
601 | ('dvorak
602 | (pcase (read-char)
603 | (97 "1") (111 "2") (101 "3") (117 "4") (105 "5")
604 | (100 "6") (104 "7") (116 "8") (110 "9") (115 "0")
605 | (45 "-") (13 "over") (127 "delete") (59 nil)
606 | (9 (char-to-string (sniem-shift-convert (read-char) sniem-shift-binding-key)))
607 | (x (char-to-string x))))))
608 |
609 | (defun sniem-mark-content (&optional mark)
610 | "Mark/unmark the content.
611 | MARK means mark forcibly. In the meanwhile, it means give it edit face."
612 | (interactive "P")
613 | (let* ((add-ov (lambda (ov)
614 | (setf (car sniem-mark-content-overlay)
615 | (append (list ov) (car sniem-mark-content-overlay)))))
616 | (mark-content (lambda (mark)
617 | (let (ov)
618 | (if (region-active-p)
619 | (progn
620 | (setq ov (make-overlay (region-beginning) (region-end)))
621 | (funcall add-ov ov)
622 | (unless mark
623 | (deactivate-mark)))
624 | (setq ov (make-overlay (point) (1+ (point))))
625 | (funcall add-ov ov))
626 | (overlay-put ov
627 | 'face (if mark
628 | 'sniem-edit-content-face
629 | 'region)))))
630 | existed-ov existed-index)
631 |
632 | (if (eq mark 0)
633 | ;; Clear marked-contents
634 | (let ((target-contents (read-char "Clear [1]untagged, [2]tagged, [0]all:")))
635 | (when (and (or (= target-contents ?0)
636 | (= target-contents ?1))
637 | (car sniem-mark-content-overlay))
638 | (dolist (ov (car sniem-mark-content-overlay))
639 | (delete-overlay ov))
640 | (setf (car sniem-mark-content-overlay) nil))
641 | (when (and (or (= target-contents ?0)
642 | (= target-contents ?2))
643 | (nth 1 sniem-mark-content-overlay))
644 | (dolist (ov (nth 1 sniem-mark-content-overlay))
645 | (delete-overlay (cdr ov)))
646 | (setf (nth 1 sniem-mark-content-overlay) nil)))
647 |
648 | ;; Whether there's a marked-content overlay under cursor
649 | (setq existed-ov (sniem--list-memq (car sniem-mark-content-overlay)
650 | (overlays-at (point)))
651 | existed-index 0)
652 | (unless existed-ov
653 | (setq existed-ov (sniem--assoc-with-list-value (overlays-at (point))
654 | (nth 1 sniem-mark-content-overlay))
655 | existed-index 1))
656 |
657 | (if existed-ov
658 | ;; Remove the content under cursor from marked-content overlays.
659 | (progn
660 | (delete-overlay (if (= existed-index 1)
661 | (cdr existed-ov)
662 | existed-ov))
663 | (setf (nth existed-index sniem-mark-content-overlay)
664 | (delete existed-ov
665 | (nth existed-index sniem-mark-content-overlay))))
666 | (funcall mark-content mark)))))
667 |
668 | (defun sniem-edit-marked-content (content)
669 | "Edit marked content with CONTENT."
670 | (interactive "MEdit with:")
671 | (when (car sniem-mark-content-overlay)
672 | (let (start end)
673 | (dolist (ov (car sniem-mark-content-overlay))
674 | (setq start (overlay-start ov)
675 | end (overlay-end ov))
676 | (delete-overlay ov)
677 | (goto-char start)
678 | (delete-region start end)
679 | (insert content))
680 | (setf (car sniem-mark-content-overlay) nil))))
681 |
682 | (defun sniem-unmark-content-select-it ()
683 | "Unmark the marked content under cursor and select it."
684 | (interactive)
685 | (let* ((tagged-ov nil)
686 | (ov (or (sniem--list-memq (car sniem-mark-content-overlay)
687 | (overlays-at (point)))
688 | (prog1 (sniem--assoc-with-list-value
689 | (overlays-at (point))
690 | (nth 1 sniem-mark-content-overlay))
691 | (setq tagged-ov t))))
692 | points)
693 | (when ov
694 | (if tagged-ov
695 | (progn
696 | (setq points (cons (overlay-start (cdr ov))
697 | (overlay-end (cdr ov))))
698 | (delete-overlay (cdr ov))
699 | (setf (cdr sniem-mark-content-overlay)
700 | (delete ov (cdr sniem-mark-content-overlay))))
701 |
702 | (setq points (cons (overlay-start ov) (overlay-end ov)))
703 | (delete-overlay ov)
704 | (setf (car sniem-mark-content-overlay)
705 | (delete ov (car sniem-mark-content-overlay)))))
706 | (goto-char (car points))
707 | (push-mark (cdr points) t t)))
708 |
709 | (defun sniem-ignore-or-enable-marked-content ()
710 | "Ignore or enable marked content."
711 | (interactive)
712 | (if sniem-ignore-marked-content
713 | (progn
714 | (message "[Sniem]: Enabled marked content.")
715 | (setq-local sniem-ignore-marked-content nil))
716 | (message "[Sniem]: Ignored marked content.")
717 | (setq-local sniem-ignore-marked-content t)))
718 |
719 | (defun sniem-mark-content-pop ()
720 | "Remove the first untagged marked content from list."
721 | (interactive)
722 | (let ((ov (pop (car sniem-mark-content-overlay)))),
723 | (delete-overlay ov)))
724 |
725 | (defun sniem-handle-tag-mark ()
726 | "Give marked-content a tag or remove a tag.
727 | If there's a tag whose name is same as the new one,
728 | replace it with the new one."
729 | (interactive)
730 | (let* ((tagged-ov nil)
731 | (point-ovs (overlays-at (point)))
732 | (target-ov (or (sniem--list-memq (car sniem-mark-content-overlay)
733 | point-ovs)
734 | (prog1 (sniem--assoc-with-list-value
735 | point-ovs
736 | (nth 1 sniem-mark-content-overlay))
737 | (setq tagged-ov t)))))
738 | (unless target-ov
739 | (user-error "[Sniem]: There's no marked content under your cursor!"))
740 | (if tagged-ov
741 | (progn
742 | (setf (nth 1 sniem-mark-content-overlay)
743 | (delete target-ov (nth 1 sniem-mark-content-overlay)))
744 | (setf (car sniem-mark-content-overlay)
745 | (append (list (cdr target-ov)) (car sniem-mark-content-overlay)))
746 | (message "[Sniem]: Successfully removed tag of current mark."))
747 |
748 | (let* ((func-name (which-function))
749 | (tag-name (completing-read "Enter tag name:"
750 | (when func-name
751 | (list func-name))))
752 | (origin-ref (gv-ref (alist-get
753 | tag-name
754 | (nth 1 sniem-mark-content-overlay)
755 | nil nil #'string-equal))))
756 | (setf (car sniem-mark-content-overlay)
757 | (delete target-ov (car sniem-mark-content-overlay)))
758 |
759 | (if (overlayp (gv-deref origin-ref))
760 | ;; Replace the original one with the new one
761 | (progn
762 | (delete-overlay (gv-deref origin-ref))
763 | (setf (gv-deref origin-ref) target-ov)
764 | (message "[Sniem]: Replaced the original tag with current mark."))
765 | (setf (nth 1 sniem-mark-content-overlay)
766 | (append (list (cons tag-name target-ov))
767 | (nth 1 sniem-mark-content-overlay)))
768 | (message "[Sniem]: Successfully added tag for current mark."))))))
769 |
770 | (defun sniem-jump-to-tag-mark ()
771 | "Jump to a tagged marked-content."
772 | (interactive)
773 | (let ((ovs (nth 1 sniem-mark-content-overlay))
774 | tags tag-name target-ov)
775 | (unless ovs
776 | (user-error "[Sniem]: Cannot find tagged marked content!"))
777 | (dolist (ov ovs)
778 | (setq tags (append tags (list (car ov)))))
779 | (setq tag-name (completing-read "Enter target tag:" tags nil t))
780 | (setq target-ov (alist-get tag-name ovs nil nil #'string-equal))
781 | (unless (eq (current-buffer) (overlay-buffer target-ov))
782 | (switch-to-buffer (overlay-buffer target-ov)))
783 | (goto-char (overlay-start target-ov))))
784 |
785 | (defun sniem--mark-refresh-timer ()
786 | "The timer to refresh marked-content overlays with wrong range."
787 | (when (car sniem-mark-content-overlay)
788 | (dolist (ov (car sniem-mark-content-overlay))
789 | (sniem--mark-overlay-refresh ov)))
790 |
791 | (when (nth 1 sniem-mark-content-overlay)
792 | (dolist (ov (nth 1 sniem-mark-content-overlay))
793 | (sniem--mark-overlay-refresh (cdr ov)))))
794 |
795 | (defun sniem--mark-overlay-refresh (ov)
796 | "Check whether the OV (overlay) has wrong range.
797 | Adjusting them if it's true."
798 | (let (start end)
799 | (setq start (overlay-start ov)
800 | end (overlay-end ov))
801 | (when (= start end)
802 | (if (> (point-max) (1+ start))
803 | (move-overlay ov start (1+ start))
804 | (unless (= (point-min) start))
805 | (move-overlay ov (1- start) start)))))
806 |
807 | (defun sniem--remove-marked-contents ()
808 | "Remove marked contents in current buffer."
809 | (when (buffer-file-name)
810 | (let (remain-untagged remain-tagged)
811 | (dolist (ov (car sniem-mark-content-overlay))
812 | (unless (eq (current-buffer) (overlay-buffer ov))
813 | (setq remain-untagged (append remain-untagged (list ov)))))
814 |
815 | (dolist (ov (nth 1 sniem-mark-content-overlay))
816 | (unless (eq (current-buffer) (overlay-buffer (cdr ov)))
817 | (setq remain-tagged (append remain-tagged (list ov)))))
818 |
819 | (setf (car sniem-mark-content-overlay) remain-untagged)
820 | (setf (nth 1 sniem-mark-content-overlay) remain-tagged))))
821 |
822 | (defun sniem--save-tagged-overlays ()
823 | "Save tagged overlays when killing emacs."
824 | (unless (file-exists-p sniem-mark-content-file)
825 | (make-empty-file sniem-mark-content-file))
826 |
827 | (let ((ovs (nth 1 sniem-mark-content-overlay)))
828 | (with-temp-file sniem-mark-content-file
829 | (unless (null ovs)
830 | (insert "(")
831 | (let (file)
832 | (dolist (ov ovs)
833 | (setq file (buffer-file-name (overlay-buffer (cdr ov))))
834 | (when (stringp file)
835 | (insert (format "(\"%s\" \"%s\" %d %d)\n"
836 | file (car ov)
837 | (overlay-start (cdr ov))
838 | (overlay-end (cdr ov)))))))
839 | (insert ")")))))
840 |
841 | (defun sniem--restore-tagged-overlays ()
842 | "Restore tagged overlays when initializing emacs."
843 | (when (file-exists-p sniem-mark-content-file)
844 | (with-temp-buffer
845 | (insert-file-contents sniem-mark-content-file)
846 |
847 | (unless (= (point) (point-max))
848 | (let ((ovs (car (read-from-string (buffer-substring-no-properties
849 | (point-min) (point-max)))))
850 | buf temp-ov restored-ovs)
851 | (dolist (ov ovs)
852 | (setq buf (get-file-buffer (car ov)))
853 |
854 | (when (bufferp buf)
855 | (setq temp-ov (make-overlay (nth 2 ov) (nth 3 ov) buf))
856 | (overlay-put temp-ov 'face 'region)
857 | (push (cons (nth 1 ov) temp-ov) restored-ovs)))
858 |
859 | (when restored-ovs
860 | (setf (nth 1 sniem-mark-content-overlay)
861 | (append restored-ovs
862 | (nth 1 sniem-mark-content-overlay)))))))))
863 |
864 | (defun sniem-show-last-point (&optional hide)
865 | "Show the last point.
866 | Optional argument HIDE is t, the last point will be show."
867 | (let ((cursor-color
868 | `((t (:foreground ,(frame-parameter nil 'background-color))
869 | :background ,(frame-parameter nil 'cursor-color)))))
870 | (if (or sniem-last-point-overlay hide)
871 | (progn
872 | (delete-overlay sniem-last-point-overlay)
873 | (setq-local sniem-last-point-overlay nil))
874 | (setq-local sniem-last-point-overlay
875 | (make-overlay sniem-last-point (1+ sniem-last-point) (current-buffer) t t))
876 | (overlay-put sniem-last-point-overlay 'face cursor-color))))
877 |
878 | (defun sniem-set-quit-insert-key (key)
879 | "Set the `sniem-quit-insert' KEY."
880 | (define-key sniem-insert-state-keymap (kbd sniem-insert-quit-key) 'nil)
881 | (define-key sniem-insert-state-keymap (kbd key) 'sniem-quit-insert)
882 | (setq sniem-insert-quit-key key))
883 |
884 | (defun sniem-shift (&optional arg)
885 | "The function to replace shift key.
886 | ARG is the `prefix-arg'."
887 | (interactive "P")
888 | (let (char result)
889 | ;; NOTE: To ensure the last key is the motion key.
890 | (while (not (setq char (sniem-shift-convert (read-char)
891 | sniem-shift-binding-key))))
892 | (when (numberp char)
893 | (when arg
894 | (setq current-prefix-arg arg))
895 | (setq result (key-binding (vector char)))
896 | (if (keymapp result)
897 | (set-transient-map result)
898 | (setq last-command-event char
899 | last-command result)
900 | (call-interactively result)))))
901 |
902 | (defun sniem-shift-convert (char shift-key)
903 | "Convert the char if it has shift-key.
904 | CHAR is the last input char.
905 | SHIFT-KEY is the shift key bound by user."
906 | (pcase sniem-shift-times
907 | (2 (setq sniem-shift-times 1)
908 | (pcase char
909 | ;; Have pressed `shift-key' three times, so enable shift lock.
910 | ((pred (= shift-key))
911 | (setq-local sniem-shift-lock
912 | (if sniem-shift-lock
913 | (progn
914 | (remove-hook 'pre-command-hook #'sniem-shift-lock-convert t)
915 | nil)
916 | (add-hook 'pre-command-hook #'sniem-shift-lock-convert nil t)
917 | t))
918 | (message "[Sniem]: Shift Lock %s in current buffer."
919 | (if sniem-shift-lock
920 | "opened"
921 | "closed"))
922 | t)
923 | ;; NOTE: Play the same role as `C-g'
924 | (_ t)))
925 | (1 (pcase char
926 | ((pred (= shift-key))
927 | (setq sniem-shift-times 2)
928 | ;; Return nil, tell `sniem-shift' continue.
929 | nil)
930 | (32 t)
931 | (_ (if (sniem-shift--not-alpha-p char)
932 | (if (eq sniem-keyboard-layout 'dvp)
933 | (pcase char
934 | (?$ ?~) (?& ?%) (91 ?7) (123 ?5) (125 ?3) (40 ?1) (?= ?9)
935 | (?* ?0) (41 ?2) (?+ ?4) (93 ?6) (?! ?8) (?# ?~) (59 ?:)
936 | (?, 60) (?. 62) (?/ ??) (?@ ?^) (124 ?|) (?- ?_) (39 34))
937 | (pcase char
938 | (?` ?~) (?1 ?!) (?2 ?@) (?3 ?#) (?4 ?$) (?5 ?%) (?6 ?^)
939 | (?7 ?&) (?8 ?*) (?9 40) (?0 41) (?- ?_) (?= ?+) (59 ?:)
940 | (91 123) (93 125) (39 34) (92 124) (?, 60) (?. 62) (?/ ??)))
941 | (upcase char)))))
942 | (_ (user-error "[Sniem]: The sniem-shift-times is error!"))))
943 |
944 | (defun sniem-shift-lock-convert ()
945 | "The function to play caps_lock's role."
946 | (when (and sniem-insert-mode
947 | (characterp last-command-event)
948 | (or (memq this-command '(self-insert-command isearch-printing-char))
949 | (eq this-command (key-binding [remap self-insert-command]))))
950 | (setq last-command-event
951 | (condition-case nil
952 | (let ((char (upcase last-command-event)))
953 | (if (eq char last-command-event)
954 | (downcase char)
955 | char))
956 | (error last-command-event)))))
957 |
958 | (defun sniem-shift--not-alpha-p (char-string &optional add-number)
959 | "Check if the CHAR belongs to pair.
960 | Argument CHAR-STRING is the string to compair.
961 | When ADD-NUMBER is non-nil, numbers will be regarded as alpha."
962 | (let ((alpha-list '(?a ?A ?b ?B ?c ?C ?d ?D ?e ?E ?f ?F ?g ?G ?h ?H ?i ?I
963 | ?j ?J ?k ?K ?l ?L ?m ?M ?n ?N ?o ?O ?p ?P ?q ?Q ?r ?R
964 | ?s ?S ?t ?T ?u ?U ?v ?V ?w ?W ?x ?X ?y ?Y ?z ?Z))
965 | (number-list '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?0)))
966 | (not (memq (if (stringp char-string)
967 | (string-to-char char-string)
968 | char-string)
969 | (if add-number
970 | (append number-list alpha-list)
971 | alpha-list)))))
972 |
973 | (defun sniem-keypad--convert-prefix (prefix)
974 | "Convert PREFIX from simple signary to specific prefix.
975 | Or convert in turn."
976 | (let* ((prefix-string '("C-" "M-" "C-M-"))
977 | (prefix-char '(44 46 47))
978 | (from (if (stringp prefix)
979 | prefix-string
980 | prefix-char))
981 | (to (if (stringp prefix)
982 | prefix-char
983 | prefix-string))
984 | index)
985 | (setq index (sniem--index prefix from))
986 | (when index
987 | (nth index to))))
988 |
989 | (defun sniem-ignore-or-enable-indentation ()
990 | "Ignore or enable indentation of current file."
991 | (interactive)
992 | (setq-local sniem-wrong-indentation
993 | (if sniem-wrong-indentation
994 | (progn
995 | (message "[Sniem]: Enabled indentation of current file.")
996 | nil)
997 | (message "[Sniem]: Ignored indentation of current file.")
998 | t)))
999 |
1000 | ;;; Initialize
1001 | (sniem-set-leader-key ",")
1002 |
1003 | ;;; Third-Party Settings
1004 | (defun sniem-init-hook ()
1005 | "The inin functions."
1006 | (let ((fn (if sniem-initialized
1007 | 'remove-hook
1008 | 'add-hook)))
1009 | (funcall fn 'deactivate-mark-hook
1010 | (lambda ()
1011 | (when sniem-mark-line
1012 | (setq-local sniem-mark-line nil))
1013 | (when sniem-object-catch-last-points
1014 | (setq-local sniem-object-catch-last-points nil))
1015 | (when sniem-object-catch-prefix-string-p
1016 | (setq-local sniem-object-catch-prefix-string-p nil))))
1017 | (funcall fn 'minibuffer-setup-hook
1018 | (lambda ()
1019 | (define-key (current-local-map) (kbd "SPC") #'sniem-minibuffer-keypad-start-or-stop)))
1020 | (funcall fn 'kill-buffer-hook #'sniem--remove-marked-contents)
1021 | (funcall fn 'kill-emacs-hook #'sniem--save-tagged-overlays)))
1022 |
1023 | (defun sniem-init-advice ()
1024 | "The init function for advice."
1025 | (if sniem-initialized
1026 | (progn
1027 | (advice-remove 'keyboard-quit
1028 | (lambda ()
1029 | (when sniem-kmacro-mark-content
1030 | (setq-local sniem-kmacro-mark-content nil))
1031 | (sniem-search--cancel-selection)))
1032 | (advice-remove 'wdired-change-to-wdired-mode #'sniem-normal-mode)
1033 | (advice-remove 'wdired-change-to-dired-mode #'sniem-motion-mode)
1034 | (advice-remove 'org-cycle #'sniem-org-cycle-advice)
1035 | (when (and (featurep 'yasnippet)
1036 | (sniem-yas--tab-used-p))
1037 | (advice-remove 'yas-expand-from-trigger-key #'sniem-yasnippet-advice-1)))
1038 | (advice-add 'keyboard-quit :before
1039 | (lambda ()
1040 | (when sniem-kmacro-mark-content
1041 | (setq-local sniem-kmacro-mark-content nil))
1042 | (sniem-search--cancel-selection)))
1043 | (advice-add 'wdired-change-to-wdired-mode :after #'sniem-normal-mode)
1044 | (advice-add 'wdired-change-to-dired-mode :after #'sniem-motion-mode)
1045 | (advice-add 'org-cycle :around #'sniem-org-cycle-advice)
1046 | (when (and (featurep 'yasnippet)
1047 | (sniem-yas--tab-used-p))
1048 | (advice-add 'yas-expand-from-trigger-key :around #'sniem-yasnippet-advice-1))))
1049 |
1050 | ;;; Support for yasnippet
1051 | (unless (featurep 'yasnippet)
1052 | (defun yas-expand-from-trigger-key ())
1053 | (defvar yas-keymap))
1054 |
1055 | (defun sniem-yasnippet-advice-1 (orig &optional field)
1056 | "The yasnippet advice for `yas-expand-from-trigger-key'."
1057 | (pcase (sniem-current-mode)
1058 | ('insert (apply orig field))
1059 | ('nil nil)
1060 | (_ (call-interactively #'sniem-shift))))
1061 |
1062 | (defun sniem-org-cycle-advice (orig &optional arg)
1063 | "The advice for `org-cycle'."
1064 | (if (or (bolp)
1065 | sniem-insert-mode)
1066 | (apply orig arg)
1067 | (call-interactively #'sniem-shift)))
1068 |
1069 | (defun sniem-yas--tab-used-p ()
1070 | "Check if yasnippet used tab."
1071 | (eq (nth 2 (alist-get 9 yas-keymap))
1072 | 'yas-next-field-or-maybe-expand))
1073 |
1074 | ;;; State info print support
1075 | (defun sniem-state ()
1076 | "The function to show the current sniem state."
1077 | (pcase (sniem-current-mode)
1078 | ('normal (format "[N:%s%s%s]"
1079 | (if sniem-object-catch-forward-p ">" "<")
1080 | (if sniem-last-point-locked ":l" "")
1081 | (if (car sniem-mark-content-overlay)
1082 | (format ":%d%s"
1083 | (length (car sniem-mark-content-overlay))
1084 | (if sniem-ignore-marked-content
1085 | "X"
1086 | ""))
1087 | "")))
1088 | ('insert (format "[I:%s]"
1089 | (if sniem-shift-lock
1090 | "A"
1091 | "a")))
1092 | ('motion "[M]")
1093 | ('expand (format "[E:%s]"
1094 | (if sniem-object-catch-forward-p ">" "<")))))
1095 |
1096 | (provide 'sniem)
1097 |
1098 | ;;; sniem.el ends here
1099 |
--------------------------------------------------------------------------------