├── .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 | --------------------------------------------------------------------------------