mirror of
https://github.com/lliding/ld-emacs.git
synced 2025-10-12 21:13:05 +00:00
First release.
This commit is contained in:
commit
92c3e19a46
6
.gitattributes
vendored
Normal file
6
.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Automatically normalize line endings (to LF) for all text-based files.
|
||||
* text=auto eol=lf
|
||||
|
||||
# Do not modify line endings for binary files (which are sometimes auto
|
||||
# detected as text files by git).
|
||||
*.png binary
|
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
45
.gitmodules
vendored
Normal file
45
.gitmodules
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
[submodule "site-lisp/extensions-submodule/go-mode.el"]
|
||||
path = site-lisp/extensions-submodule/go-mode.el
|
||||
url = git@github.com:dominikh/go-mode.el.git
|
||||
[submodule "site-lisp/extensions-submodule/jsonian"]
|
||||
path = site-lisp/extensions-submodule/jsonian
|
||||
url = git@github.com:iwahbe/jsonian.git
|
||||
[submodule "site-lisp/extensions-submodule/ace-window"]
|
||||
path = site-lisp/extensions-submodule/ace-window
|
||||
url = git@github.com:abo-abo/ace-window.git
|
||||
[submodule "site-lisp/extensions-submodule/dash.el"]
|
||||
path = site-lisp/extensions-submodule/dash.el
|
||||
url = git@github.com:magnars/dash.el.git
|
||||
[submodule "site-lisp/extensions-submodule/avy"]
|
||||
path = site-lisp/extensions-submodule/avy
|
||||
url = git@github.com:abo-abo/avy.git
|
||||
[submodule "site-lisp/extensions-submodule/emacs-which-key"]
|
||||
path = site-lisp/extensions-submodule/emacs-which-key
|
||||
url = git@github.com:justbur/emacs-which-key.git
|
||||
[submodule "site-lisp/extensions-submodule/lua-mode"]
|
||||
path = site-lisp/extensions-submodule/lua-mode
|
||||
url = git@github.com:immerrr/lua-mode.git
|
||||
[submodule "site-lisp/extensions-submodule/markdown-mode"]
|
||||
path = site-lisp/extensions-submodule/markdown-mode
|
||||
url = git@github.com:jrblevin/markdown-mode.git
|
||||
[submodule "site-lisp/extensions-submodule/modus-themes"]
|
||||
path = site-lisp/extensions-submodule/modus-themes
|
||||
url = git@github.com:protesilaos/modus-themes.git
|
||||
[submodule "site-lisp/extensions-submodule/swiper"]
|
||||
path = site-lisp/extensions-submodule/swiper
|
||||
url = git@github.com:abo-abo/swiper.git
|
||||
[submodule "site-lisp/extensions-submodule/web-mode"]
|
||||
path = site-lisp/extensions-submodule/web-mode
|
||||
url = git@github.com:fxbois/web-mode.git
|
||||
[submodule "site-lisp/extensions-submodule/yasnippet"]
|
||||
path = site-lisp/extensions-submodule/yasnippet
|
||||
url = git@github.com:joaotavora/yasnippet.git
|
||||
[submodule "site-lisp/extensions-submodule/multiple-cursors.el"]
|
||||
path = site-lisp/extensions-submodule/multiple-cursors.el
|
||||
url = git@github.com:magnars/multiple-cursors.el.git
|
||||
[submodule "site-lisp/extensions-submodule/citre"]
|
||||
path = site-lisp/extensions-submodule/citre
|
||||
url = git@github.com:universal-ctags/citre.git
|
||||
[submodule "site-lisp/extensions-submodule/company-mode"]
|
||||
path = site-lisp/extensions-submodule/company-mode
|
||||
url = git@github.com:company-mode/company-mode.git
|
661
LICENSE
Normal file
661
LICENSE
Normal file
@ -0,0 +1,661 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
||||
# Install elisp files
|
||||
|
||||
## Debian / Ubuntu
|
||||
|
||||
Clone this repo to home path.
|
||||
|
||||
Build config symlink to emacs directory:
|
||||
|
||||
```bash
|
||||
sudo ln -s ~/ld-emacs/site-lisp /usr/share/emacs/ld
|
||||
```
|
||||
|
||||
Copy site-start.el in emacs directory to start my config:
|
||||
|
||||
```bash
|
||||
sudo cp ~/ld-emacs/site-start.el /usr/share/emacs/site-lisp/
|
||||
```
|
||||
|
||||
Initialize submodules:
|
||||
|
||||
```plaintext
|
||||
cd ~/ld-emacs && git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## Windows
|
||||
|
||||
Clone this repo to `C:\Users\<username>\AppData\Roaming\ld-emacs` and initialize submodules.
|
||||
|
||||
Put the content below to `~/.emacs.d/init.el` (to `C:\Users\<username>\AppData\Roaming\.emacs.d\init.el`).
|
||||
|
||||
```lisp
|
||||
(load-file "~/ld-emacs/site-start.el")
|
||||
```
|
||||
|
||||
# Install dependencies for extensions
|
||||
|
||||
## Debian / Ubuntu
|
||||
|
||||
```plaintext
|
||||
# for citre (ctags frontend)
|
||||
sudo apt install universal-ctags
|
||||
|
||||
# for counsel-rg
|
||||
sudo apt install ripgrep
|
||||
```
|
||||
|
||||
Note: Emacs will load ~/.profile for env variables at the start. According to the code in ~/.profile, emacs will not load ~/.bashrc. So if user wish to add some env variables, the code should be written to ~/.profile.
|
||||
|
||||
## Windows
|
||||
|
||||
Download Universal-ctags binary and add it to environment variable `Path`.
|
||||
|
||||
Download the ripgrep for windows from [ripgrep](https://github.com/BurntSushi/ripgrep) and add the .exe file to env variable `Path`.
|
126
site-lisp/extensions-local/auto-save.el
Normal file
126
site-lisp/extensions-local/auto-save.el
Normal file
@ -0,0 +1,126 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defgroup auto-save nil
|
||||
"Auto save file when emacs idle."
|
||||
:group 'auto-save)
|
||||
|
||||
(defcustom auto-save-idle 1
|
||||
"The idle seconds to auto save file."
|
||||
:type 'integer
|
||||
:group 'auto-save)
|
||||
|
||||
(defcustom auto-save-silent nil
|
||||
"Nothing to dirty minibuffer if this option is non-nil."
|
||||
:type 'boolean
|
||||
:group 'auto-save)
|
||||
|
||||
(defcustom auto-save-delete-trailing-whitespace nil
|
||||
"Delete trailing whitespace when save if this option is non-nil.
|
||||
Note, this option is non-nil, will delete all training whitespace execpet current line,
|
||||
avoid delete current indent space when you programming."
|
||||
:type 'boolean
|
||||
:group 'auto-save)
|
||||
|
||||
(defvar auto-save-disable-predicates
|
||||
nil "disable auto save in these case.")
|
||||
|
||||
;; Emacs' default auto-save is stupid to generate #foo# files!
|
||||
(setq make-backup-files nil)
|
||||
(setq auto-save-default nil)
|
||||
(setq create-lockfiles nil)
|
||||
|
||||
(defun auto-save-buffers ()
|
||||
(interactive)
|
||||
(let ((autosave-buffer-list))
|
||||
(ignore-errors
|
||||
(save-current-buffer
|
||||
(dolist (buf (buffer-list))
|
||||
(set-buffer buf)
|
||||
(when (and
|
||||
;; Buffer associate with a filename?
|
||||
(buffer-file-name)
|
||||
;; Buffer is modifiable?
|
||||
(buffer-modified-p)
|
||||
;; Yassnippet is not active?
|
||||
(or (not (boundp 'yas--active-snippets))
|
||||
(not yas--active-snippets))
|
||||
;; Company is not active?
|
||||
(or (not (boundp 'company-candidates))
|
||||
(not company-candidates))
|
||||
;; Corfu is not active?
|
||||
(or (not (boundp 'corfu--total))
|
||||
(zerop corfu--total))
|
||||
;; Org-capture is not active?
|
||||
(not (eq (buffer-base-buffer (get-buffer (concat "CAPTURE-" (buffer-name))))
|
||||
buf))
|
||||
;; tell auto-save don't save
|
||||
(not (seq-some (lambda (predicate)
|
||||
(funcall predicate))
|
||||
auto-save-disable-predicates)))
|
||||
(push (buffer-name) autosave-buffer-list)
|
||||
(if auto-save-silent
|
||||
;; `inhibit-message' can shut up Emacs, but we want
|
||||
;; it doesn't clean up echo area during saving
|
||||
(with-temp-message ""
|
||||
(let ((inhibit-message t))
|
||||
(basic-save-buffer)))
|
||||
(basic-save-buffer))
|
||||
))
|
||||
;; Tell user when auto save files.
|
||||
(unless auto-save-silent
|
||||
(cond
|
||||
;; It's stupid tell user if nothing to save.
|
||||
((= (length autosave-buffer-list) 1)
|
||||
(message "# Saved %s" (car autosave-buffer-list)))
|
||||
((> (length autosave-buffer-list) 1)
|
||||
(message "# Saved %d files: %s"
|
||||
(length autosave-buffer-list)
|
||||
(mapconcat 'identity autosave-buffer-list ", ")))))
|
||||
))))
|
||||
|
||||
(defun auto-save-delete-trailing-whitespace-except-current-line ()
|
||||
(interactive)
|
||||
(when auto-save-delete-trailing-whitespace
|
||||
(let ((begin (line-beginning-position))
|
||||
(end (point)))
|
||||
(save-excursion
|
||||
(when (< (point-min) begin)
|
||||
(save-restriction
|
||||
(narrow-to-region (point-min) (1- begin))
|
||||
(delete-trailing-whitespace)))
|
||||
(when (> (point-max) end)
|
||||
(save-restriction
|
||||
(narrow-to-region end (point-max))
|
||||
(delete-trailing-whitespace)))))))
|
||||
|
||||
(defvar auto-save-timer nil)
|
||||
|
||||
(defun auto-save-set-timer ()
|
||||
"Set the auto-save timer.
|
||||
Cancel any previous timer."
|
||||
(auto-save-cancel-timer)
|
||||
(setq auto-save-timer
|
||||
(run-with-idle-timer auto-save-idle t 'auto-save-buffers)))
|
||||
|
||||
(defun auto-save-cancel-timer ()
|
||||
(when auto-save-timer
|
||||
(cancel-timer auto-save-timer)
|
||||
(setq auto-save-timer nil)))
|
||||
|
||||
(defun auto-save-enable ()
|
||||
(interactive)
|
||||
(auto-save-set-timer)
|
||||
(add-hook 'before-save-hook 'auto-save-delete-trailing-whitespace-except-current-line)
|
||||
)
|
||||
|
||||
(defun auto-save-disable ()
|
||||
(interactive)
|
||||
(auto-save-cancel-timer)
|
||||
(remove-hook 'before-save-hook 'auto-save-delete-trailing-whitespace-except-current-line)
|
||||
)
|
||||
|
||||
(provide 'auto-save)
|
||||
|
||||
;;; auto-save.el ends here
|
533
site-lisp/extensions-local/cmake-mode.el
Normal file
533
site-lisp/extensions-local/cmake-mode.el
Normal file
@ -0,0 +1,533 @@
|
||||
;;; cmake-mode.el --- major-mode for editing CMake sources
|
||||
|
||||
;; Package-Requires: ((emacs "24.1"))
|
||||
;; Package-Version: 20220823.1201
|
||||
;; Package-Commit: 5936d4f2adeec64e0ff748b2c6c34f0436b19a97
|
||||
|
||||
; Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
; file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides syntax highlighting and indentation for CMakeLists.txt and
|
||||
;; *.cmake source files.
|
||||
;;
|
||||
;; Add this code to your .emacs file to use the mode:
|
||||
;;
|
||||
;; (setq load-path (cons (expand-file-name "/dir/with/cmake-mode") load-path))
|
||||
;; (require 'cmake-mode)
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;; Code:
|
||||
;;
|
||||
;; cmake executable variable used to run cmake --help-command
|
||||
;; on commands in cmake-mode
|
||||
;;
|
||||
;; cmake-command-help Written by James Bigler
|
||||
;;
|
||||
|
||||
(require 'rst)
|
||||
(require 'rx)
|
||||
|
||||
(defcustom cmake-mode-cmake-executable "cmake"
|
||||
"*The name of the cmake executable.
|
||||
|
||||
This can be either absolute or looked up in $PATH. You can also
|
||||
set the path with these commands:
|
||||
(setenv \"PATH\" (concat (getenv \"PATH\") \";C:\\\\Program Files\\\\CMake 2.8\\\\bin\"))
|
||||
(setenv \"PATH\" (concat (getenv \"PATH\") \":/usr/local/cmake/bin\"))"
|
||||
:type 'file
|
||||
:group 'cmake)
|
||||
|
||||
;; Keywords
|
||||
(defconst cmake-keywords-block-open '("BLOCK" "IF" "MACRO" "FOREACH" "ELSE" "ELSEIF" "WHILE" "FUNCTION"))
|
||||
(defconst cmake-keywords-block-close '("ENDBLOCK" "ENDIF" "ENDFOREACH" "ENDMACRO" "ELSE" "ELSEIF" "ENDWHILE" "ENDFUNCTION"))
|
||||
(defconst cmake-keywords
|
||||
(let ((kwds (append cmake-keywords-block-open cmake-keywords-block-close nil)))
|
||||
(delete-dups kwds)))
|
||||
|
||||
;; Regular expressions used by line indentation function.
|
||||
;;
|
||||
(defconst cmake-regex-blank "^[ \t]*$")
|
||||
(defconst cmake-regex-comment "#.*")
|
||||
(defconst cmake-regex-paren-left "(")
|
||||
(defconst cmake-regex-paren-right ")")
|
||||
(defconst cmake-regex-closing-parens-line (concat "^[[:space:]]*\\("
|
||||
cmake-regex-paren-right
|
||||
"+\\)[[:space:]]*$"))
|
||||
(defconst cmake-regex-argument-quoted
|
||||
(rx ?\" (* (or (not (any ?\" ?\\)) (and ?\\ anything))) ?\"))
|
||||
(defconst cmake-regex-argument-unquoted
|
||||
(rx (or (not (any space "()#\"\\\n")) (and ?\\ nonl))
|
||||
(* (or (not (any space "()#\\\n")) (and ?\\ nonl)))))
|
||||
(defconst cmake-regex-token
|
||||
(rx-to-string `(group (or (regexp ,cmake-regex-comment)
|
||||
?\( ?\)
|
||||
(regexp ,cmake-regex-argument-unquoted)
|
||||
(regexp ,cmake-regex-argument-quoted)))))
|
||||
(defconst cmake-regex-indented
|
||||
(rx-to-string `(and bol (* (group (or (regexp ,cmake-regex-token) (any space ?\n)))))))
|
||||
(defconst cmake-regex-block-open
|
||||
(rx-to-string `(and symbol-start (or ,@(append cmake-keywords-block-open
|
||||
(mapcar 'downcase cmake-keywords-block-open))) symbol-end)))
|
||||
(defconst cmake-regex-block-close
|
||||
(rx-to-string `(and symbol-start (or ,@(append cmake-keywords-block-close
|
||||
(mapcar 'downcase cmake-keywords-block-close))) symbol-end)))
|
||||
(defconst cmake-regex-close
|
||||
(rx-to-string `(and bol (* space) (regexp ,cmake-regex-block-close)
|
||||
(* space) (regexp ,cmake-regex-paren-left))))
|
||||
(defconst cmake-regex-token-paren-left (concat "^" cmake-regex-paren-left "$"))
|
||||
(defconst cmake-regex-token-paren-right (concat "^" cmake-regex-paren-right "$"))
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;; Line indentation helper functions
|
||||
|
||||
(defun cmake-line-starts-inside-string ()
|
||||
"Determine whether the beginning of the current line is in a string."
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let ((parse-end (point)))
|
||||
(goto-char (point-min))
|
||||
(nth 3 (parse-partial-sexp (point) parse-end))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun cmake-find-last-indented-line ()
|
||||
"Move to the beginning of the last line that has meaningful indentation."
|
||||
(let ((point-start (point))
|
||||
region)
|
||||
(forward-line -1)
|
||||
(setq region (buffer-substring-no-properties (point) point-start))
|
||||
(while (and (not (bobp))
|
||||
(or (looking-at cmake-regex-blank)
|
||||
(cmake-line-starts-inside-string)
|
||||
(not (and (string-match cmake-regex-indented region)
|
||||
(= (length region) (match-end 0))))))
|
||||
(forward-line -1)
|
||||
(setq region (buffer-substring-no-properties (point) point-start))
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;
|
||||
;; Indentation increment.
|
||||
;;
|
||||
(defcustom cmake-tab-width 2
|
||||
"Number of columns to indent cmake blocks"
|
||||
:type 'integer
|
||||
:group 'cmake)
|
||||
|
||||
;;
|
||||
;; Line indentation function.
|
||||
;;
|
||||
(defun cmake-indent ()
|
||||
"Indent current line as CMake code."
|
||||
(interactive)
|
||||
(unless (cmake-line-starts-inside-string)
|
||||
(if (bobp)
|
||||
(cmake-indent-line-to 0)
|
||||
(let (cur-indent)
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let ((point-start (point))
|
||||
(closing-parens-only (looking-at cmake-regex-closing-parens-line))
|
||||
(case-fold-search t) ;; case-insensitive
|
||||
token)
|
||||
;; Search back for the last indented line.
|
||||
(cmake-find-last-indented-line)
|
||||
;; Start with the indentation on this line.
|
||||
(setq cur-indent (current-indentation))
|
||||
(if closing-parens-only
|
||||
(let ((open-parens 0))
|
||||
(while (re-search-forward cmake-regex-token point-start t)
|
||||
(setq token (match-string 0))
|
||||
(cond
|
||||
((string-match cmake-regex-token-paren-left token)
|
||||
(setq open-parens (+ open-parens 1)))
|
||||
((string-match cmake-regex-token-paren-right token)
|
||||
(setq open-parens (- open-parens 1)))))
|
||||
;; Don't outdent if last indented line has open parens
|
||||
(unless (> open-parens 0)
|
||||
(setq cur-indent (- cur-indent cmake-tab-width))))
|
||||
;; Skip detailed analysis if last indented line is a 'closing
|
||||
;; parens only line'
|
||||
(unless (looking-at cmake-regex-closing-parens-line)
|
||||
;; Search forward counting tokens that adjust indentation.
|
||||
(while (re-search-forward cmake-regex-token point-start t)
|
||||
(setq token (match-string 0))
|
||||
(when (or (string-match cmake-regex-token-paren-left token)
|
||||
(and (string-match cmake-regex-block-open token)
|
||||
(looking-at (concat "[ \t]*" cmake-regex-paren-left))))
|
||||
(setq cur-indent (+ cur-indent cmake-tab-width)))
|
||||
(when (string-match cmake-regex-token-paren-right token)
|
||||
(setq cur-indent (- cur-indent cmake-tab-width)))
|
||||
))
|
||||
(goto-char point-start)
|
||||
;; If next token closes the block, decrease indentation
|
||||
(when (looking-at cmake-regex-close)
|
||||
(setq cur-indent (- cur-indent cmake-tab-width))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
;; Indent this line by the amount selected.
|
||||
(cmake-indent-line-to (max cur-indent 0))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun cmake-point-in-indendation ()
|
||||
(string-match "^[ \\t]*$" (buffer-substring (point-at-bol) (point))))
|
||||
|
||||
(defun cmake-indent-line-to (column)
|
||||
"Indent the current line to COLUMN.
|
||||
If point is within the existing indentation it is moved to the end of
|
||||
the indentation. Otherwise it retains the same position on the line"
|
||||
(if (cmake-point-in-indendation)
|
||||
(indent-line-to column)
|
||||
(save-excursion (indent-line-to column))))
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;
|
||||
;; Helper functions for buffer
|
||||
;;
|
||||
(defun cmake-unscreamify-buffer ()
|
||||
"Convert all CMake commands to lowercase in buffer."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(while (re-search-forward "^\\([ \t]*\\)\\_<\\(\\(?:\\w\\|\\s_\\)+\\)\\_>\\([ \t]*(\\)" nil t)
|
||||
(replace-match
|
||||
(concat
|
||||
(match-string 1)
|
||||
(downcase (match-string 2))
|
||||
(match-string 3))
|
||||
t))
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;
|
||||
;; Navigation / marking by function or macro
|
||||
;;
|
||||
|
||||
(defconst cmake--regex-defun-start
|
||||
(rx line-start
|
||||
(zero-or-more space)
|
||||
(or "function" "macro")
|
||||
(zero-or-more space)
|
||||
"("))
|
||||
|
||||
(defconst cmake--regex-defun-end
|
||||
(rx line-start
|
||||
(zero-or-more space)
|
||||
"end"
|
||||
(or "function" "macro")
|
||||
(zero-or-more space)
|
||||
"(" (zero-or-more (not-char ")")) ")"))
|
||||
|
||||
(defun cmake-beginning-of-defun ()
|
||||
"Move backward to the beginning of a CMake function or macro.
|
||||
|
||||
Return t unless search stops due to beginning of buffer."
|
||||
(interactive)
|
||||
(when (not (region-active-p))
|
||||
(push-mark))
|
||||
(let ((case-fold-search t))
|
||||
(when (re-search-backward cmake--regex-defun-start nil 'move)
|
||||
t)))
|
||||
|
||||
(defun cmake-end-of-defun ()
|
||||
"Move forward to the end of a CMake function or macro.
|
||||
|
||||
Return t unless search stops due to end of buffer."
|
||||
(interactive)
|
||||
(when (not (region-active-p))
|
||||
(push-mark))
|
||||
(let ((case-fold-search t))
|
||||
(when (re-search-forward cmake--regex-defun-end nil 'move)
|
||||
(forward-line)
|
||||
t)))
|
||||
|
||||
(defun cmake-mark-defun ()
|
||||
"Mark the current CMake function or macro.
|
||||
|
||||
This puts the mark at the end, and point at the beginning."
|
||||
(interactive)
|
||||
(cmake-end-of-defun)
|
||||
(push-mark nil :nomsg :activate)
|
||||
(cmake-beginning-of-defun))
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
;;
|
||||
;; Keyword highlighting regex-to-face map.
|
||||
;;
|
||||
(defconst cmake-font-lock-keywords
|
||||
`((,(rx-to-string `(and symbol-start
|
||||
(or ,@cmake-keywords
|
||||
,@(mapcar #'downcase cmake-keywords))
|
||||
symbol-end))
|
||||
. font-lock-keyword-face)
|
||||
(,(rx symbol-start (group (+ (or word (syntax symbol)))) (* blank) ?\()
|
||||
1 font-lock-function-name-face)
|
||||
(,(rx "${" (group (+(any alnum "-_+/."))) "}")
|
||||
1 font-lock-variable-name-face t)
|
||||
)
|
||||
"Highlighting expressions for CMake mode.")
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
(defun cmake--syntax-propertize-until-bracket-close (syntax)
|
||||
;; This function assumes that a previous search has matched the
|
||||
;; beginning of a bracket_comment or bracket_argument and that the
|
||||
;; second capture group has matched the equal signs between the two
|
||||
;; opening brackets
|
||||
(let* ((mb (match-beginning 2))
|
||||
(me (match-end 2))
|
||||
(cb (format "]%s]" (buffer-substring mb me))))
|
||||
(save-match-data
|
||||
(if (search-forward cb end 'move)
|
||||
(progn
|
||||
(setq me (match-end 0))
|
||||
(put-text-property
|
||||
(1- me)
|
||||
me
|
||||
'syntax-table
|
||||
(string-to-syntax syntax)))
|
||||
(setq me end)))
|
||||
(put-text-property
|
||||
(match-beginning 1)
|
||||
me
|
||||
'syntax-multiline
|
||||
t)))
|
||||
|
||||
(defconst cmake--syntax-propertize-function
|
||||
(syntax-propertize-rules
|
||||
("\\(#\\)\\[\\(=*\\)\\["
|
||||
(1
|
||||
(prog1 "!" (cmake--syntax-propertize-until-bracket-close "!"))))
|
||||
("\\(\\[\\)\\(=*\\)\\["
|
||||
(1
|
||||
(prog1 "|" (cmake--syntax-propertize-until-bracket-close "|"))))))
|
||||
|
||||
;; Syntax table for this mode.
|
||||
(defvar cmake-mode-syntax-table nil
|
||||
"Syntax table for CMake mode.")
|
||||
(or cmake-mode-syntax-table
|
||||
(setq cmake-mode-syntax-table
|
||||
(let ((table (make-syntax-table)))
|
||||
(modify-syntax-entry ?\( "()" table)
|
||||
(modify-syntax-entry ?\) ")(" table)
|
||||
(modify-syntax-entry ?# "<" table)
|
||||
(modify-syntax-entry ?\n ">" table)
|
||||
(modify-syntax-entry ?$ "'" table)
|
||||
table)))
|
||||
|
||||
;;
|
||||
;; User hook entry point.
|
||||
;;
|
||||
(defvar cmake-mode-hook nil)
|
||||
|
||||
;;------------------------------------------------------------------------------
|
||||
;; Mode definition.
|
||||
;;
|
||||
;;;###autoload
|
||||
(define-derived-mode cmake-mode prog-mode "CMake"
|
||||
"Major mode for editing CMake source files."
|
||||
|
||||
; Setup font-lock mode.
|
||||
(set (make-local-variable 'font-lock-defaults) '(cmake-font-lock-keywords))
|
||||
; Setup indentation function.
|
||||
(set (make-local-variable 'indent-line-function) 'cmake-indent)
|
||||
; Setup comment syntax.
|
||||
(set (make-local-variable 'comment-start) "#")
|
||||
;; Setup syntax propertization
|
||||
(set (make-local-variable 'syntax-propertize-function) cmake--syntax-propertize-function)
|
||||
(add-hook 'syntax-propertize-extend-region-functions #'syntax-propertize-multiline nil t))
|
||||
|
||||
;; Default cmake-mode key bindings
|
||||
(define-key cmake-mode-map "\e\C-a" #'cmake-beginning-of-defun)
|
||||
(define-key cmake-mode-map "\e\C-e" #'cmake-end-of-defun)
|
||||
(define-key cmake-mode-map "\e\C-h" #'cmake-mark-defun)
|
||||
|
||||
|
||||
; Help mode starts here
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-command-run (type &optional topic buffer)
|
||||
"Runs the command cmake with the arguments specified. The
|
||||
optional argument topic will be appended to the argument list."
|
||||
(interactive "s")
|
||||
(let* ((bufname (if buffer buffer (concat "*CMake" type (if topic "-") topic "*")))
|
||||
(buffer (if (get-buffer bufname) (get-buffer bufname) (generate-new-buffer bufname)))
|
||||
(command (concat cmake-mode-cmake-executable " " type " " topic))
|
||||
;; Turn of resizing of mini-windows for shell-command.
|
||||
(resize-mini-windows nil)
|
||||
)
|
||||
(shell-command command buffer)
|
||||
(save-selected-window
|
||||
(select-window (display-buffer buffer 'not-this-window))
|
||||
(cmake-mode)
|
||||
(read-only-mode 1)
|
||||
(view-mode 1))
|
||||
)
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-command-run-help (type &optional topic buffer)
|
||||
"`cmake-command-run' but rendered in `rst-mode'."
|
||||
(interactive "s")
|
||||
(let* ((bufname (if buffer buffer (concat "*CMake" type (if topic "-") topic "*")))
|
||||
(buffer (if (get-buffer bufname) (get-buffer bufname) (generate-new-buffer bufname)))
|
||||
(command (concat cmake-mode-cmake-executable " " type " " topic))
|
||||
;; Turn of resizing of mini-windows for shell-command.
|
||||
(resize-mini-windows nil)
|
||||
)
|
||||
(shell-command command buffer)
|
||||
(save-selected-window
|
||||
(select-window (display-buffer buffer 'not-this-window))
|
||||
(rst-mode)
|
||||
(read-only-mode 1)
|
||||
(view-mode 1))
|
||||
)
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help-list-commands ()
|
||||
"Prints out a list of the cmake commands."
|
||||
(interactive)
|
||||
(cmake-command-run-help "--help-command-list")
|
||||
)
|
||||
|
||||
(defvar cmake-commands '() "List of available topics for --help-command.")
|
||||
(defvar cmake-help-command-history nil "Command read history.")
|
||||
(defvar cmake-modules '() "List of available topics for --help-module.")
|
||||
(defvar cmake-help-module-history nil "Module read history.")
|
||||
(defvar cmake-variables '() "List of available topics for --help-variable.")
|
||||
(defvar cmake-help-variable-history nil "Variable read history.")
|
||||
(defvar cmake-properties '() "List of available topics for --help-property.")
|
||||
(defvar cmake-help-property-history nil "Property read history.")
|
||||
(defvar cmake-help-complete-history nil "Complete help read history.")
|
||||
(defvar cmake-string-to-list-symbol
|
||||
'(("command" cmake-commands cmake-help-command-history)
|
||||
("module" cmake-modules cmake-help-module-history)
|
||||
("variable" cmake-variables cmake-help-variable-history)
|
||||
("property" cmake-properties cmake-help-property-history)
|
||||
))
|
||||
|
||||
(defun cmake-get-list (listname)
|
||||
"If the value of LISTVAR is nil, run cmake --help-LISTNAME-list
|
||||
and store the result as a list in LISTVAR."
|
||||
(let ((listvar (car (cdr (assoc listname cmake-string-to-list-symbol)))))
|
||||
(if (not (symbol-value listvar))
|
||||
(let ((temp-buffer-name "*CMake Temporary*"))
|
||||
(save-window-excursion
|
||||
(cmake-command-run-help (concat "--help-" listname "-list") nil temp-buffer-name)
|
||||
(with-current-buffer temp-buffer-name
|
||||
; FIXME: Ignore first line if it is "cmake version ..." from CMake < 3.0.
|
||||
(set listvar (split-string (buffer-substring-no-properties (point-min) (point-max)) "\n" t)))))
|
||||
(symbol-value listvar)
|
||||
))
|
||||
)
|
||||
|
||||
(require 'thingatpt)
|
||||
(defun cmake-symbol-at-point ()
|
||||
(let ((symbol (symbol-at-point)))
|
||||
(and (not (null symbol))
|
||||
(symbol-name symbol))))
|
||||
|
||||
(defun cmake-help-type (type)
|
||||
(let* ((default-entry (cmake-symbol-at-point))
|
||||
(history (car (cdr (cdr (assoc type cmake-string-to-list-symbol)))))
|
||||
(input (completing-read
|
||||
(format "CMake %s: " type) ; prompt
|
||||
(cmake-get-list type) ; completions
|
||||
nil ; predicate
|
||||
t ; require-match
|
||||
default-entry ; initial-input
|
||||
history
|
||||
)))
|
||||
(if (string= input "")
|
||||
(error "No argument given")
|
||||
input))
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help-command ()
|
||||
"Prints out the help message for the command the cursor is on."
|
||||
(interactive)
|
||||
(cmake-command-run-help "--help-command" (cmake-help-type "command") "*CMake Help*"))
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help-module ()
|
||||
"Prints out the help message for the module the cursor is on."
|
||||
(interactive)
|
||||
(cmake-command-run-help "--help-module" (cmake-help-type "module") "*CMake Help*"))
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help-variable ()
|
||||
"Prints out the help message for the variable the cursor is on."
|
||||
(interactive)
|
||||
(cmake-command-run-help "--help-variable" (cmake-help-type "variable") "*CMake Help*"))
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help-property ()
|
||||
"Prints out the help message for the property the cursor is on."
|
||||
(interactive)
|
||||
(cmake-command-run-help "--help-property" (cmake-help-type "property") "*CMake Help*"))
|
||||
|
||||
;;;###autoload
|
||||
(defun cmake-help ()
|
||||
"Queries for any of the four available help topics and prints out the appropriate page."
|
||||
(interactive)
|
||||
(let* ((default-entry (cmake-symbol-at-point))
|
||||
(command-list (cmake-get-list "command"))
|
||||
(variable-list (cmake-get-list "variable"))
|
||||
(module-list (cmake-get-list "module"))
|
||||
(property-list (cmake-get-list "property"))
|
||||
(all-words (append command-list variable-list module-list property-list))
|
||||
(input (completing-read
|
||||
"CMake command/module/variable/property: " ; prompt
|
||||
all-words ; completions
|
||||
nil ; predicate
|
||||
t ; require-match
|
||||
default-entry ; initial-input
|
||||
'cmake-help-complete-history
|
||||
)))
|
||||
(if (string= input "")
|
||||
(error "No argument given")
|
||||
(if (member input command-list)
|
||||
(cmake-command-run-help "--help-command" input "*CMake Help*")
|
||||
(if (member input variable-list)
|
||||
(cmake-command-run-help "--help-variable" input "*CMake Help*")
|
||||
(if (member input module-list)
|
||||
(cmake-command-run-help "--help-module" input "*CMake Help*")
|
||||
(if (member input property-list)
|
||||
(cmake-command-run-help "--help-property" input "*CMake Help*")
|
||||
(error "Not a know help topic.") ; this really should not happen
|
||||
))))))
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(progn
|
||||
(add-to-list 'auto-mode-alist '("CMakeLists\\.txt\\'" . cmake-mode))
|
||||
(add-to-list 'auto-mode-alist '("\\.cmake\\'" . cmake-mode)))
|
||||
|
||||
; This file provides cmake-mode.
|
||||
(provide 'cmake-mode)
|
||||
|
||||
;;; cmake-mode.el ends here
|
528
site-lisp/extensions-local/company-ctags.el
Normal file
528
site-lisp/extensions-local/company-ctags.el
Normal file
@ -0,0 +1,528 @@
|
||||
;;; company-ctags.el --- Fastest company-mode completion backend for ctags -*- lexical-binding: t -*-
|
||||
|
||||
;; Copyright (C) 2019,2020 Chen Bin
|
||||
|
||||
;; Author: Chen Bin <chenbin.sh@gmail.com>
|
||||
;; URL: https://github.com/redguardtoo/company-ctags
|
||||
;; Version: 0.0.7
|
||||
;; Keywords: convenience
|
||||
;; Package-Requires: ((emacs "25.1") (company "0.9.0"))
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
;; GNU Emacs is free software: you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; GNU Emacs is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This library completes code using tags file created by Ctags.
|
||||
;; It uses a much faster algorithm optimized for ctags.
|
||||
;; It takes only 9 seconds to load 300M tags file which is created by
|
||||
;; scanning the Linux Kernel code v5.3.1.
|
||||
;; After initial loading, this library will respond immediately
|
||||
;; when new tags file is created.
|
||||
;;
|
||||
;; Usage:
|
||||
;;
|
||||
;; Step 0, Make sure `company-mode' is already set up
|
||||
;; See http://company-mode.github.io/ for details.
|
||||
;;
|
||||
;; Step 1, insert below code into your configuration,
|
||||
;;
|
||||
;; (with-eval-after-load 'company
|
||||
;; (company-ctags-auto-setup))
|
||||
;;
|
||||
;; Step 2, Use Ctags to create tags file and enjoy.
|
||||
;;
|
||||
;; Tips:
|
||||
;;
|
||||
;; - Turn on `company-ctags-support-etags' to support tags
|
||||
;; file created by etags. But it will increase initial loading time.
|
||||
;;
|
||||
;; - Set `company-ctags-extra-tags-files' to load extra tags files,
|
||||
;;
|
||||
;; (setq company-ctags-extra-tags-files '("$HOME/TAGS" "/usr/include/TAGS"))
|
||||
;;
|
||||
;; - Set `company-ctags-fuzzy-match-p' to fuzzy match the candidates.
|
||||
;; The input could match any part of the candidate instead of the beginning of
|
||||
;; the candidate.
|
||||
;;
|
||||
;; - Set `company-ctags-ignore-case' to ignore case when fetching candidates
|
||||
;;
|
||||
;; - Use rusty-tags to generate tags file for Rust programming language.
|
||||
;; Add below code into ~/.emacs,
|
||||
;; (setq company-ctags-tags-file-name "rusty-tags.emacs")
|
||||
;;
|
||||
;; - Make sure CLI program diff is executable on Windows.
|
||||
;; It's optional but highly recommended. It can speed up tags file updating.
|
||||
;; This package uses diff through variable `diff-command'.
|
||||
;;
|
||||
;; - `company-ctags-debug-info' for debugging.
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'find-file)
|
||||
(require 'company nil t)
|
||||
(require 'cl-lib)
|
||||
(require 'subr-x)
|
||||
|
||||
(defgroup company-ctags nil
|
||||
"Completion backend for ctags."
|
||||
:group 'company)
|
||||
|
||||
(defcustom company-ctags-use-main-table-list t
|
||||
"Always search `tags-table-list' if set.
|
||||
If this is disabled, `company-ctags' will try to find the one table for each
|
||||
buffer automatically."
|
||||
:type '(choice (const :tag "off" nil)
|
||||
(const :tag "on" t)))
|
||||
|
||||
(defcustom company-ctags-ignore-case nil
|
||||
"Non-nil to ignore case in completion candidates."
|
||||
:type 'boolean
|
||||
:package-version '(company . "0.7.3"))
|
||||
|
||||
(defcustom company-ctags-extra-tags-files nil
|
||||
"List of extra tags files which are loaded only once.
|
||||
|
||||
A typical format is,
|
||||
|
||||
(\"./TAGS\" \"/usr/include/TAGS\" \"$PROJECT/*/include/TAGS\")
|
||||
|
||||
Environment variables can be inserted between slashes (`/').
|
||||
They will be replaced by their definitions. If a variable does
|
||||
not exist, it is replaced (silently) with an empty string."
|
||||
:type '(repeat 'string))
|
||||
|
||||
(defcustom company-ctags-quiet nil
|
||||
"Be quiet and do not notify user tags file status."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom company-ctags-support-etags nil
|
||||
"Support tags file created by etags.
|
||||
If t, it increases the loading time."
|
||||
:type 'boolean)
|
||||
|
||||
(defcustom company-ctags-everywhere nil
|
||||
"Non-nil to offer completions in comments and strings.
|
||||
Set it to t or to a list of major modes."
|
||||
:type '(choice (const :tag "Off" nil)
|
||||
(const :tag "Any supported mode" t)
|
||||
(repeat :tag "Some major modes"
|
||||
(symbol :tag "Major mode")))
|
||||
:package-version '(company . "0.9.0"))
|
||||
|
||||
(defcustom company-ctags-check-tags-file-interval 30
|
||||
"The interval (seconds) to check tags file.
|
||||
Default value is 30 seconds."
|
||||
:type 'integer)
|
||||
|
||||
(defcustom company-ctags-tags-file-name "TAGS"
|
||||
"The name of tags file."
|
||||
:type 'string)
|
||||
|
||||
(defcustom company-ctags-tag-name-valid-characters
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$#@%_!*&1234567890"
|
||||
"The characters of tag name. It's used for partition algorithm."
|
||||
:type 'string)
|
||||
|
||||
(defcustom company-ctags-fuzzy-match-p nil
|
||||
"If t, fuzzy match the candidates.
|
||||
The input could match any part of the candidate instead of the beginning of
|
||||
the candidate."
|
||||
:type 'boolean)
|
||||
|
||||
(defvar company-ctags-modes
|
||||
'(prog-mode
|
||||
c-mode
|
||||
objc-mode
|
||||
c++-mode
|
||||
java-mode
|
||||
jde-mode
|
||||
pascal-mode
|
||||
perl-mode
|
||||
python-mode
|
||||
lua-mode
|
||||
web-mode))
|
||||
|
||||
(defvar company-backends) ; avoid compiling warning
|
||||
|
||||
(defvar-local company-ctags-buffer-table-internal nil)
|
||||
|
||||
(defvar company-ctags-tags-file-caches nil
|
||||
"The cached tags files.")
|
||||
|
||||
(defvar company-ctags-cached-candidates nil
|
||||
"The cached candidates searched with certain prefix.")
|
||||
|
||||
(defconst company-ctags-fast-pattern
|
||||
"\177\\([^\177\001\n]+\\)\001"
|
||||
"Pattern to extract tag name created by Ctags only.")
|
||||
|
||||
(defconst company-ctags-slow-pattern
|
||||
"\\([^\f\t\n\r()=,; ]*\\)[\f\t\n\r()=,; ]*\177\\\(?:\\([^\n\001]+\\)\001\\)?"
|
||||
"Pattern to extract tag name created by Ctags/Etags.")
|
||||
|
||||
(defun company-ctags-find-table ()
|
||||
"Find tags file."
|
||||
(let* ((file (expand-file-name
|
||||
company-ctags-tags-file-name
|
||||
(locate-dominating-file (or buffer-file-name
|
||||
default-directory)
|
||||
company-ctags-tags-file-name))))
|
||||
(when (and file (file-regular-p file))
|
||||
(list file))))
|
||||
|
||||
(defun company-ctags-buffer-table ()
|
||||
"Find buffer table."
|
||||
(or (and company-ctags-use-main-table-list tags-table-list)
|
||||
(or company-ctags-buffer-table-internal
|
||||
(setq company-ctags-buffer-table-internal
|
||||
(company-ctags-find-table)))))
|
||||
|
||||
(defun company-ctags-char-in-string-p (character string)
|
||||
"Test if CHARACTER is in STRING."
|
||||
(let (rlt (i 0) (len (length string)))
|
||||
(while (and (not rlt) (< i len))
|
||||
(setq rlt (eq (elt string i) character))
|
||||
(setq i (1+ i)))
|
||||
rlt))
|
||||
|
||||
(defun company-ctags-tag-name-character-p (character)
|
||||
"Test if CHARACTER is in `company-ctags-tag-name-valid-characters'."
|
||||
(company-ctags-char-in-string-p character
|
||||
company-ctags-tag-name-valid-characters))
|
||||
|
||||
(defmacro company-ctags-push-tagname (tagname tagname-dict)
|
||||
"Push TAGNAME into TAGNAME-DICT."
|
||||
`(let ((c (elt ,tagname 0)))
|
||||
(when (company-ctags-tag-name-character-p c)
|
||||
(push ,tagname (gethash c ,tagname-dict)))))
|
||||
|
||||
(defun company-ctags-n-items (n tagnames)
|
||||
"Return first N items of TAGNAMES."
|
||||
(cond
|
||||
((<= (length tagnames) n)
|
||||
tagnames)
|
||||
(t
|
||||
(let (rlt (i 0))
|
||||
(while (< i n)
|
||||
(push (nth i tagnames) rlt)
|
||||
(setq i (1+ i)))
|
||||
(push " ..." rlt)
|
||||
(nreverse rlt)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-ctags-debug-info ()
|
||||
"Print all debug information."
|
||||
(interactive)
|
||||
(let* ((caches company-ctags-tags-file-caches)
|
||||
(keys (hash-table-keys caches)))
|
||||
(message "* cache contents")
|
||||
(dolist (k keys)
|
||||
(let* ((h (gethash k caches))
|
||||
(timestamp (plist-get h :timestamp))
|
||||
(filesize (plist-get h :filesize))
|
||||
(dict (plist-get h :tagname-dict))
|
||||
(dict-keys (hash-table-keys dict)))
|
||||
(message "** key=%s timestamp=%s filesize=%s\n" k timestamp filesize)
|
||||
(dolist (dk dict-keys)
|
||||
(let* ((items (company-ctags-n-items 4 (gethash dk dict))))
|
||||
(when (> (length items) 0)
|
||||
(message " %s: %s" (string dk) items))))))))
|
||||
|
||||
(defun company-ctags-init-tagname-dict ()
|
||||
"Initialize tagname dict."
|
||||
(let* ((i 0)
|
||||
(dict (make-hash-table))
|
||||
(len (length company-ctags-tag-name-valid-characters)))
|
||||
(while (< i len)
|
||||
(puthash (elt company-ctags-tag-name-valid-characters i) '() dict)
|
||||
(setq i (1+ i)))
|
||||
dict))
|
||||
|
||||
(defun company-ctags-parse-tags (text &optional dict)
|
||||
"Extract tag names from TEXT.
|
||||
DICT is the existing lookup dictionary contains tag names.
|
||||
If it's nil, return a dictionary, or else return the existing dictionary."
|
||||
(let* ((start 0)
|
||||
(case-fold-search company-ctags-ignore-case))
|
||||
(unless dict (setq dict (company-ctags-init-tagname-dict)))
|
||||
|
||||
;; Code inside the loop should be optimized.
|
||||
;; Please avoid calling lisp function inside the loop.
|
||||
(cond
|
||||
(company-ctags-support-etags
|
||||
;; slow algorithm, need support both explicit and implicit tags name
|
||||
(while (string-match company-ctags-slow-pattern text start)
|
||||
(cond
|
||||
((match-beginning 2)
|
||||
;; There is an explicit tag name.
|
||||
(company-ctags-push-tagname (substring text (match-beginning 2) (match-end 2))
|
||||
dict))
|
||||
(t
|
||||
;; No explicit tag name. Backtrack a little,
|
||||
;; and look for the implicit one.
|
||||
(company-ctags-push-tagname (substring text (match-beginning 1) (match-end 1))
|
||||
dict)))
|
||||
(setq start (+ 4 (match-end 0)))))
|
||||
(t
|
||||
;; fast algorithm, support explicit tags name only
|
||||
(while (string-match company-ctags-fast-pattern text start)
|
||||
(company-ctags-push-tagname (substring text (match-beginning 1) (match-end 1))
|
||||
dict)
|
||||
(setq start (+ 4 (match-end 0))))))
|
||||
|
||||
dict))
|
||||
|
||||
(defun company-ctags-all-completions (string collection)
|
||||
"Search match to STRING in COLLECTION to see if it begins with STRING.
|
||||
If `company-ctags-fuzzy-match-p' is t, check if the match contains STRING."
|
||||
(let ((case-fold-search company-ctags-ignore-case))
|
||||
(cond
|
||||
(company-ctags-fuzzy-match-p
|
||||
(let* (rlt)
|
||||
;; code should be efficient in side the this loop
|
||||
(dolist (c collection)
|
||||
(if (string-match string c) (push c rlt)))
|
||||
rlt))
|
||||
(t
|
||||
(all-completions string collection)))))
|
||||
|
||||
(defun company-ctags-fetch-by-first-char (c prefix tagname-dict)
|
||||
"Fetch candidates by first character C of PREFIX from TAGNAME-DICT."
|
||||
(let* ((rlt (company-ctags-all-completions prefix (gethash c tagname-dict))))
|
||||
(when company-ctags-ignore-case
|
||||
(let (c2 (offset (- ?a ?A)))
|
||||
(cond
|
||||
((company-ctags-char-in-string-p c "abcdefghijklmnopqrstuvwxyz")
|
||||
(setq c2 (- c offset)))
|
||||
|
||||
((company-ctags-char-in-string-p c "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
(setq c2 (+ c offset))))
|
||||
|
||||
(when c2
|
||||
(setq rlt (nconc rlt (company-ctags-all-completions prefix (gethash c2 tagname-dict)))))))
|
||||
rlt))
|
||||
|
||||
(defun company-ctags-all-candidates (prefix tagname-dict)
|
||||
"Search for partial match to PREFIX in TAGNAME-DICT."
|
||||
(cond
|
||||
(company-ctags-fuzzy-match-p
|
||||
(let* ((keys (hash-table-keys tagname-dict))
|
||||
rlt)
|
||||
;; search all hash tables
|
||||
;; don't care the first character of prefix
|
||||
(dolist (c keys)
|
||||
(setq rlt (nconc rlt (company-ctags-fetch-by-first-char c prefix tagname-dict))))
|
||||
rlt))
|
||||
(t
|
||||
(company-ctags-fetch-by-first-char (elt prefix 0) prefix tagname-dict))))
|
||||
|
||||
(defun company-ctags-load-tags-file (file static-p &optional force no-diff-prog)
|
||||
"Load tags from FILE.
|
||||
If STATIC-P is t, the corresponding tags file is read only once.
|
||||
If FORCE is t, tags file is read without `company-ctags-tags-file-caches'.
|
||||
If NO-DIFF-PROG is t, do NOT use diff on tags file.
|
||||
This function return t if any tag file is reloaded."
|
||||
(let* (raw-content
|
||||
(file-info (and company-ctags-tags-file-caches
|
||||
(gethash file company-ctags-tags-file-caches)))
|
||||
(use-diff (and (not no-diff-prog)
|
||||
file-info
|
||||
(plist-get file-info :raw-content)
|
||||
(executable-find diff-command)))
|
||||
tagname-dict
|
||||
reloaded)
|
||||
|
||||
(when (or force
|
||||
(not file-info)
|
||||
(and
|
||||
;; the tags file is static and is already read into cache
|
||||
;; so don't read it again
|
||||
;; (not (plist-get file-info :static-p))
|
||||
;; time to expire cache from tags file
|
||||
(> (- (float-time (current-time))
|
||||
(plist-get file-info :timestamp))
|
||||
company-ctags-check-tags-file-interval)
|
||||
;; When generating new tags file, file size could be
|
||||
;; temporarily smaller than cached file size.
|
||||
;; Don't reload tags file until new tags file is bigger.
|
||||
(> (nth 7 (file-attributes file))
|
||||
(plist-get file-info :filesize))))
|
||||
|
||||
;; Read file content
|
||||
(setq reloaded t)
|
||||
(cond
|
||||
(use-diff
|
||||
;; actually don't change raw-content attached to file-info
|
||||
(setq raw-content (plist-get file-info :raw-content))
|
||||
|
||||
;; use diff to find the new tags
|
||||
(let (diff-output)
|
||||
(with-temp-buffer
|
||||
(insert (plist-get file-info :raw-content))
|
||||
;; when process finished, replace temp buffer with program output
|
||||
(call-process-region (point-min) (point-max) diff-command t t nil "-ab" file "-")
|
||||
(setq diff-output (buffer-string)))
|
||||
|
||||
;; compare old and new tags file, extract tag names from diff output which
|
||||
;; should be merged with old tag names
|
||||
(setq tagname-dict
|
||||
(company-ctags-parse-tags diff-output
|
||||
(plist-get file-info :tagname-dict)))))
|
||||
(t
|
||||
(unless company-ctags-quiet (message "Please be patient when loading %s" file))
|
||||
(setq raw-content (with-temp-buffer
|
||||
(insert-file-contents file)
|
||||
(buffer-string)))
|
||||
;; collect all tag names
|
||||
(setq tagname-dict (company-ctags-parse-tags raw-content))
|
||||
(unless company-ctags-quiet (message "%s is loaded." file))))
|
||||
|
||||
;; initialize hash table if needed
|
||||
(unless company-ctags-tags-file-caches
|
||||
(set 'company-ctags-tags-file-caches (make-hash-table :test #'equal)))
|
||||
|
||||
;; finalize tags file info
|
||||
(puthash file
|
||||
;; if the tags file is read only once, it will never be updated
|
||||
;; by `diff-command', so don't need store original raw content
|
||||
;; of tags file in order to save memory.
|
||||
(list :raw-content (unless static-p raw-content)
|
||||
:tagname-dict tagname-dict
|
||||
:static-p static-p
|
||||
:timestamp (float-time (current-time))
|
||||
:filesize (nth 7 (file-attributes file)))
|
||||
company-ctags-tags-file-caches))
|
||||
reloaded))
|
||||
|
||||
(defun company-ctags--test-cached-candidates (prefix)
|
||||
"Test PREFIX in `company-ctags-cached-candidates'."
|
||||
(let* ((cands company-ctags-cached-candidates)
|
||||
(key (plist-get cands :key))
|
||||
(keylen (length key))
|
||||
(case-fold-search company-ctags-ignore-case))
|
||||
;; prefix is "hello" and cache's prefix "ell"
|
||||
(and (>= (length prefix) keylen)
|
||||
(if company-ctags-fuzzy-match-p (string-match key prefix)
|
||||
;; key is the beginning of prefix
|
||||
(string= (substring prefix 0 keylen) key)))))
|
||||
|
||||
(defun company-ctags--candidates (prefix)
|
||||
"Get candidate with PREFIX."
|
||||
(when (and prefix (> (length prefix) 0))
|
||||
(let* ((file (and tags-file-name (file-truename tags-file-name)))
|
||||
(completion-ignore-case company-ctags-ignore-case)
|
||||
(all-tags-files (mapcar (lambda (f)
|
||||
(file-truename f))
|
||||
(delete-dups (append (if file (list file))
|
||||
(company-ctags-buffer-table)))))
|
||||
(extra-tags-files (ff-list-replace-env-vars company-ctags-extra-tags-files))
|
||||
rlt)
|
||||
|
||||
;; load tags files, maybe
|
||||
(dolist (f all-tags-files)
|
||||
(when (and f (file-exists-p f))
|
||||
(when (company-ctags-load-tags-file f
|
||||
nil ; primary tags file, not static
|
||||
nil
|
||||
nil)
|
||||
;; invalidate cached candidates if any tags file is reloaded
|
||||
(setq company-ctags-cached-candidates nil))))
|
||||
|
||||
(when extra-tags-files
|
||||
(dolist (f extra-tags-files)
|
||||
(when (and f (file-exists-p f))
|
||||
;; tags file in `company-ctags-extra-tags-files' is read only once.
|
||||
(company-ctags-load-tags-file f
|
||||
t ; static tags file, read only once
|
||||
nil
|
||||
nil))))
|
||||
|
||||
(cond
|
||||
;; re-use cached candidates
|
||||
((and (not company-ctags-fuzzy-match-p)
|
||||
company-ctags-cached-candidates
|
||||
(company-ctags--test-cached-candidates prefix))
|
||||
|
||||
(let* ((cands (plist-get company-ctags-cached-candidates :cands)))
|
||||
(setq rlt (company-ctags-all-completions prefix cands))))
|
||||
|
||||
;; search candidates through tags files
|
||||
(t
|
||||
(dolist (f (nconc all-tags-files extra-tags-files))
|
||||
(let* ((cache (gethash f company-ctags-tags-file-caches))
|
||||
(tagname-dict (plist-get cache :tagname-dict)))
|
||||
(when tagname-dict
|
||||
(setq rlt (append rlt (company-ctags-all-candidates prefix tagname-dict))))))
|
||||
|
||||
;; fuzzy algorithm don't use caching algorithm
|
||||
(unless company-ctags-fuzzy-match-p
|
||||
(setq company-ctags-cached-candidates
|
||||
;; clone the rlt into cache
|
||||
(list :key prefix :cands (mapcar 'identity rlt))))))
|
||||
|
||||
;; cleanup
|
||||
(if rlt (delete-dups rlt)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-ctags (command &optional arg &rest ignored)
|
||||
"Completion backend of for ctags. Execute COMMAND with ARG and IGNORED."
|
||||
(interactive (list 'interactive))
|
||||
(cl-case command
|
||||
(interactive (company-begin-backend 'company-ctags))
|
||||
(prefix (and (apply #'derived-mode-p company-ctags-modes)
|
||||
(or (eq t company-ctags-everywhere)
|
||||
(apply #'derived-mode-p company-ctags-everywhere)
|
||||
(not (company-in-string-or-comment)))
|
||||
(company-ctags-buffer-table)
|
||||
(or (company-grab-symbol) 'stop)))
|
||||
(candidates (company-ctags--candidates arg))
|
||||
(location (let ((tags-table-list (company-ctags-buffer-table)))
|
||||
(when (fboundp 'find-tag-noselect)
|
||||
(save-excursion
|
||||
(let ((buffer (find-tag-noselect arg)))
|
||||
(cons buffer (with-current-buffer buffer (point))))))))
|
||||
(ignore-case company-ctags-ignore-case)))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-ctags-replace-backend (backends)
|
||||
"Replace `company-etags' with `company-ctags' in BACKENDS."
|
||||
(let* (rlt)
|
||||
(dolist (b backends)
|
||||
(cond
|
||||
((eq b 'company-etags)
|
||||
(push 'company-ctags rlt))
|
||||
((listp b)
|
||||
(let* (children)
|
||||
(dolist (c b)
|
||||
(cond
|
||||
((eq c 'company-etags)
|
||||
(push 'company-ctags children))
|
||||
(t
|
||||
(push c children))))
|
||||
(push (nreverse children) rlt)))
|
||||
(t
|
||||
(push b rlt))))
|
||||
(nreverse rlt)))
|
||||
|
||||
;;;###autoload
|
||||
(defun company-ctags-auto-setup ()
|
||||
"Set up `company-backends'."
|
||||
(setq company-backends
|
||||
(company-ctags-replace-backend company-backends)))
|
||||
|
||||
(provide 'company-ctags)
|
||||
;;; company-ctags.el ends here
|
87
site-lisp/extensions-local/dired-display-buffer.el
Normal file
87
site-lisp/extensions-local/dired-display-buffer.el
Normal file
@ -0,0 +1,87 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defcustom dired-display-buffer-switch-window t
|
||||
"Switch focus to the newly created buffer window. nil to disable."
|
||||
:type 'boolean
|
||||
)
|
||||
|
||||
(defun ld-display-buffer (buffer-or-name alist direction &optional size pixelwise)
|
||||
"BUFFER: The buffer that will be displayed.
|
||||
ALIST: See the doc-string of `display-buffer' for more information.
|
||||
DIRECTION: Must use one of these symbols: 'left 'right 'below 'above
|
||||
SIZE: See the doc-string for `split-window'.
|
||||
PIXELWISE: See the doc-string for `split-window'.
|
||||
There are three possibilities:
|
||||
- (1) If a window on the frame already displays the target buffer,
|
||||
then just reuse the same window.
|
||||
- (2) If there is already a window in the specified direction in relation
|
||||
to the selected window, then display the target buffer in said window.
|
||||
- (3) If there is no window in the specified direction, then create one
|
||||
in that direction and display the target buffer in said window."
|
||||
(let* ((buffer
|
||||
(if (bufferp buffer-or-name)
|
||||
buffer-or-name
|
||||
(get-buffer buffer-or-name)))
|
||||
(window
|
||||
(cond
|
||||
((get-buffer-window buffer (selected-frame)))
|
||||
((window-in-direction direction))
|
||||
(t
|
||||
(split-window (selected-window) size direction pixelwise)))))
|
||||
;; (window--display-buffer buffer window 'window alist display-buffer-mark-dedicated)
|
||||
(window--display-buffer buffer window 'window alist)
|
||||
(if dired-display-buffer-switch-window
|
||||
(select-window window))
|
||||
))
|
||||
|
||||
(defun dired-display-buffer (&optional direction alist)
|
||||
"Display a dired-mode buffer or a file underneath point in a dired-mode buffer."
|
||||
(interactive)
|
||||
(let* ((file-or-dir (or (and (eq major-mode 'dired-mode) (dired-get-file-for-visit))
|
||||
(read-directory-name "Directory: ")))
|
||||
(buffer (find-file-noselect file-or-dir))
|
||||
(direction
|
||||
(if direction
|
||||
direction
|
||||
(let ((char (read-char-exclusive (concat
|
||||
"["
|
||||
(propertize "l" 'face '(:foreground "red"))
|
||||
"]"
|
||||
(propertize "eft" 'face '(:foreground "blue"))
|
||||
" | ["
|
||||
(propertize "r" 'face '(:foreground "red"))
|
||||
"]"
|
||||
(propertize "ight" 'face '(:foreground "blue"))
|
||||
" | ["
|
||||
(propertize "a" 'face '(:foreground "red"))
|
||||
"]"
|
||||
(propertize "bove" 'face '(:foreground "blue"))
|
||||
" | ["
|
||||
(propertize "b" 'face '(:foreground "red"))
|
||||
"]"
|
||||
(propertize "elow" 'face '(:foreground "blue"))))))
|
||||
(cond
|
||||
((eq char ?l)
|
||||
'left)
|
||||
((eq char ?r)
|
||||
'right)
|
||||
((eq char ?a)
|
||||
'above)
|
||||
((eq char ?b)
|
||||
'below)
|
||||
;;; FIXME: @lawlist may add a loop similar to `org-capture'
|
||||
;;; whereby a new `read-char-exclusive' will be initiated if
|
||||
;;; a user did not initially choose a valid option (l/r/a/b).
|
||||
(t
|
||||
(let ((debug-on-quit nil)
|
||||
(msg (concat "dired-display-buffer: "
|
||||
"You did not select l/r/a/b "
|
||||
"-- exiting.")))
|
||||
(signal 'quit `(,msg)))))))))
|
||||
(ld-display-buffer buffer alist direction)))
|
||||
|
||||
(provide 'dired-display-buffer)
|
||||
|
||||
;;; dired-display-buffer.el ends here
|
273
site-lisp/extensions-local/dired-hacks-utils.el
Normal file
273
site-lisp/extensions-local/dired-hacks-utils.el
Normal file
@ -0,0 +1,273 @@
|
||||
;;; dired-hacks-utils.el --- Utilities and helpers for dired-hacks collection
|
||||
|
||||
;; Copyright (C) 2014-2015 Matúš Goljer
|
||||
|
||||
;; Author: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Maintainer: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Keywords: files
|
||||
;; Version: 0.0.1
|
||||
;; Created: 14th February 2014
|
||||
;; Package-Requires: ((dash "2.5.0"))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Utilities and helpers for `dired-hacks' collection of dired
|
||||
;; improvements.
|
||||
|
||||
;; This package also provides these interactive functions:
|
||||
;; * `dired-hacks-next-file' - go to next file, skipping empty and non-file lines
|
||||
;; * `dired-hacks-previous-file' - go to previous file, skipping empty
|
||||
;; and non-file lines
|
||||
;; * `dired-utils-format-information-line-mode' - Format the information
|
||||
;; (summary) line file sizes to be human readable (e.g. 1GB instead of 1048576).
|
||||
|
||||
|
||||
;; See https://github.com/Fuco1/dired-hacks for the entire collection
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dash)
|
||||
(require 'dired)
|
||||
|
||||
(defgroup dired-hacks ()
|
||||
"Collection of useful dired additions."
|
||||
:group 'dired
|
||||
:prefix "dired-hacks-")
|
||||
|
||||
(defcustom dired-hacks-file-size-formatter #'file-size-human-readable
|
||||
"The function used to format file sizes.
|
||||
|
||||
See `dired-utils-format-file-sizes'."
|
||||
:type 'function
|
||||
:group 'dired-hacks)
|
||||
|
||||
(defcustom dired-hacks-datetime-regexp
|
||||
"\\sw\\sw\\sw....\\(?:[0-9][0-9]:[0-9][0-9]\\|.[0-9]\\{4\\}\\)"
|
||||
"A regexp matching the date/time in the dired listing.
|
||||
|
||||
It is used to determine where the filename starts. It should
|
||||
*not* match any characters after the last character of the
|
||||
timestamp. It is assumed that the timestamp is preceded and
|
||||
followed by at least one space character. You should only use
|
||||
shy groups (prefixed with ?:) because the first group is used by
|
||||
the font-lock to determine what portion of the name should be
|
||||
colored."
|
||||
:type 'regexp
|
||||
:group 'dired-hacks)
|
||||
|
||||
(defalias 'dired-utils--string-trim
|
||||
(if (and (require 'subr-x nil t)
|
||||
(fboundp 'string-trim))
|
||||
#'string-trim
|
||||
(lambda (string)
|
||||
(let ((s string))
|
||||
(when (string-match "\\`[ \t\n\r]+" s)
|
||||
(setq s (replace-match "" t t s)))
|
||||
(when (string-match "[ \t\n\r]+\\'" s)
|
||||
(setq s (replace-match "" t t s)))
|
||||
s)))
|
||||
"Trim STRING of trailing whitespace.
|
||||
|
||||
\(fn STRING)")
|
||||
|
||||
(defun dired-utils-get-filename (&optional localp)
|
||||
"Like `dired-get-filename' but never signal an error.
|
||||
|
||||
Optional arg LOCALP with value `no-dir' means don't include
|
||||
directory name in result."
|
||||
(dired-get-filename localp t))
|
||||
|
||||
(defun dired-utils-get-all-files (&optional localp)
|
||||
"Return all files in this dired buffer as a list.
|
||||
|
||||
LOCALP has same semantics as in `dired-get-filename'."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let (r)
|
||||
(while (= 0 (forward-line))
|
||||
(--when-let (dired-utils-get-filename localp)
|
||||
(push it r)))
|
||||
(nreverse r))))
|
||||
|
||||
(defconst dired-utils-file-attributes-keywords
|
||||
'(:isdir :nlinks :uid :gid :atime :mtime :ctime :size :modes :gidchg :inode :devnum)
|
||||
"List of keywords to map with `file-attributes'.")
|
||||
|
||||
(defconst dired-utils-info-keywords
|
||||
`(:name :issym :target ,@dired-utils-file-attributes-keywords)
|
||||
"List of keywords available for `dired-utils-get-info'.")
|
||||
|
||||
(defun dired-utils--get-keyword-info (keyword)
|
||||
"Get file information about KEYWORD."
|
||||
(let ((filename (dired-utils-get-filename)))
|
||||
(cl-case keyword
|
||||
(:name filename)
|
||||
(:isdir (file-directory-p filename))
|
||||
(:issym (and (file-symlink-p filename) t))
|
||||
(:target (file-symlink-p filename))
|
||||
(t
|
||||
(nth (-elem-index keyword dired-utils-file-attributes-keywords)
|
||||
(file-attributes filename))))))
|
||||
|
||||
(defun dired-utils-get-info (&rest keywords)
|
||||
"Query for info about the file at point.
|
||||
|
||||
KEYWORDS is a list of attributes to query.
|
||||
|
||||
When querying for one attribute, its value is returned. When
|
||||
querying for more than one, a list of results is returned.
|
||||
|
||||
The available keywords are listed in
|
||||
`dired-utils-info-keywords'."
|
||||
(let ((attributes (mapcar 'dired-utils--get-keyword-info keywords)))
|
||||
(if (> (length attributes) 1)
|
||||
attributes
|
||||
(car attributes))))
|
||||
|
||||
(defun dired-utils-goto-line (filename)
|
||||
"Go to line describing FILENAME in listing.
|
||||
|
||||
Should be absolute file name matched against
|
||||
`dired-get-filename'."
|
||||
(goto-char (point-min))
|
||||
(let (stop)
|
||||
(while (and (not stop)
|
||||
(= (forward-line) 0))
|
||||
(when (equal filename (dired-utils-get-filename))
|
||||
(setq stop t)
|
||||
(dired-move-to-filename)))
|
||||
stop))
|
||||
|
||||
(defun dired-utils-match-filename-regexp (filename alist)
|
||||
"Match FILENAME against each car in ALIST and return first matched cons.
|
||||
|
||||
Each car in ALIST is a regular expression.
|
||||
|
||||
The matching is done using `string-match-p'."
|
||||
(let (match)
|
||||
(--each-while alist (not match)
|
||||
(when (string-match-p (car it) filename)
|
||||
(setq match it)))
|
||||
match))
|
||||
|
||||
(defun dired-utils-match-filename-extension (filename alist)
|
||||
"Match FILENAME against each car in ALIST and return first matched cons.
|
||||
|
||||
Each car in ALIST is a string representing file extension
|
||||
*without* the delimiting dot."
|
||||
(let (done)
|
||||
(--each-while alist (not done)
|
||||
(when (string-match-p (concat "\\." (regexp-quote (car it)) "\\'") filename)
|
||||
(setq done it)))
|
||||
done))
|
||||
|
||||
(defun dired-utils-format-information-line ()
|
||||
"Format the disk space on the Dired information line."
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(forward-line)
|
||||
(let ((inhibit-read-only t)
|
||||
(limit (line-end-position)))
|
||||
(while (re-search-forward "\\(?:directory\\|available\\) \\(\\<[0-9]+$\\>\\)" nil t)
|
||||
(replace-match
|
||||
(save-match-data
|
||||
(propertize (dired-utils--string-trim
|
||||
(funcall dired-hacks-file-size-formatter
|
||||
(* 1024 (string-to-number (match-string 1))) t))
|
||||
'invisible 'dired-hide-details-information))
|
||||
t nil nil 1)))))
|
||||
|
||||
|
||||
;;; Predicates
|
||||
(defun dired-utils-is-file-p ()
|
||||
"Return non-nil if the line at point is a file or a directory."
|
||||
(dired-utils-get-filename 'no-dir))
|
||||
|
||||
(defun dired-utils-is-dir-p ()
|
||||
"Return non-nil if the line at point is a directory."
|
||||
(--when-let (dired-utils-get-filename)
|
||||
(file-directory-p it)))
|
||||
|
||||
|
||||
;;; Interactive
|
||||
;; TODO: add wrap-around option
|
||||
(defun dired-hacks-next-file (&optional arg)
|
||||
"Move point to the next file.
|
||||
|
||||
Optional prefix ARG says how many lines to move; default is one
|
||||
line."
|
||||
(interactive "p")
|
||||
(unless arg (setq arg 1))
|
||||
(if (< arg 0)
|
||||
(dired-hacks-previous-file (- arg))
|
||||
(--dotimes arg
|
||||
(forward-line)
|
||||
(while (and (or (not (dired-utils-is-file-p))
|
||||
(get-text-property (point) 'invisible))
|
||||
(= (forward-line) 0))))
|
||||
(if (not (= (point) (point-max)))
|
||||
(dired-move-to-filename)
|
||||
(forward-line -1)
|
||||
(dired-move-to-filename)
|
||||
nil)))
|
||||
|
||||
(defun dired-hacks-previous-file (&optional arg)
|
||||
"Move point to the previous file.
|
||||
|
||||
Optional prefix ARG says how many lines to move; default is one
|
||||
line."
|
||||
(interactive "p")
|
||||
(unless arg (setq arg 1))
|
||||
(if (< arg 0)
|
||||
(dired-hacks-next-file (- arg))
|
||||
(--dotimes arg
|
||||
(forward-line -1)
|
||||
(while (and (or (not (dired-utils-is-file-p))
|
||||
(get-text-property (point) 'invisible))
|
||||
(= (forward-line -1) 0))))
|
||||
(if (not (= (point) (point-min)))
|
||||
(dired-move-to-filename)
|
||||
(dired-hacks-next-file)
|
||||
nil)))
|
||||
|
||||
(defun dired-hacks-compare-files (file-a file-b)
|
||||
"Test if two files FILE-A and FILE-B are the (probably) the same."
|
||||
(interactive (let ((other-dir (dired-dwim-target-directory)))
|
||||
(list (read-file-name "File A: " default-directory (car (dired-get-marked-files)) t)
|
||||
(read-file-name "File B: " other-dir (with-current-buffer (cdr (assoc other-dir dired-buffers))
|
||||
(car (dired-get-marked-files))) t))))
|
||||
(let ((md5-a (with-temp-buffer
|
||||
(shell-command (format "md5sum %s" file-a) (current-buffer))
|
||||
(buffer-string)))
|
||||
(md5-b (with-temp-buffer
|
||||
(shell-command (format "md5sum %s" file-b) (current-buffer))
|
||||
(buffer-string))))
|
||||
(message "%s%sFiles are %s." md5-a md5-b
|
||||
(if (equal (car (split-string md5-a))
|
||||
(car (split-string md5-b)))
|
||||
"probably the same" "different"))))
|
||||
|
||||
(define-minor-mode dired-utils-format-information-line-mode
|
||||
"Toggle formatting of disk space in the Dired information line."
|
||||
:group 'dired-utils
|
||||
:lighter ""
|
||||
(if dired-utils-format-information-line-mode
|
||||
(add-hook 'dired-after-readin-hook #'dired-utils-format-information-line)
|
||||
(remove-hook 'dired-after-readin-hook #'dired-utils-format-information-line)))
|
||||
|
||||
(provide 'dired-hacks-utils)
|
||||
|
||||
;;; dired-hacks-utils.el ends here
|
356
site-lisp/extensions-local/dired-narrow.el
Normal file
356
site-lisp/extensions-local/dired-narrow.el
Normal file
@ -0,0 +1,356 @@
|
||||
;;; dired-narrow.el --- Live-narrowing of search results for dired
|
||||
|
||||
;; Copyright (C) 2014-2015 Matúš Goljer
|
||||
|
||||
;; Author: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Maintainer: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Version: 0.0.1
|
||||
;; Created: 14th February 2014
|
||||
;; Package-Requires: ((dash "2.7.0") (dired-hacks-utils "0.0.1"))
|
||||
;; Keywords: files
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 3
|
||||
;; of the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; This package provides live filtering of files in dired buffers. In
|
||||
;; general, after calling the respective narrowing function you type a
|
||||
;; filter string into the minibuffer. After each change the changes
|
||||
;; automatically reflect in the buffer. Typing C-g will cancel the
|
||||
;; narrowing and restore the original view, typing RET will exit the
|
||||
;; live filtering mode and leave the dired buffer in the narrowed
|
||||
;; state. To bring it back to the original view, you can call
|
||||
;; `revert-buffer' (usually bound to `g').
|
||||
|
||||
;; During the filtering process, several special functions are
|
||||
;; available. You can customize the binding by changing
|
||||
;; `dired-narrow-map'.
|
||||
|
||||
;; * `dired-narrow-next-file' (<down> or C-n) - move the point to the
|
||||
;; next file
|
||||
;; * `dired-narrow-previous-file' (<up> or C-p) - move the point to the
|
||||
;; previous file
|
||||
;; * `dired-narrow-enter-directory' (<right> or C-j) - descend into the
|
||||
;; directory under point and immediately go back to narrowing mode
|
||||
|
||||
;; You can customize what happens after exiting the live filtering
|
||||
;; mode by customizing `dired-narrow-exit-action'.
|
||||
|
||||
;; These narrowing functions are provided:
|
||||
|
||||
;; * `dired-narrow'
|
||||
;; * `dired-narrow-regexp'
|
||||
;; * `dired-narrow-fuzzy'
|
||||
|
||||
;; You can also create your own narrowing functions quite easily. To
|
||||
;; define new narrowing function, use `dired-narrow--internal' and
|
||||
;; pass it an apropriate filter. The filter should take one argument
|
||||
;; which is the filter string from the minibuffer. It is then called
|
||||
;; at each line that describes a file with point at the beginning of
|
||||
;; the file name. If the filter returns nil, the file is removed from
|
||||
;; the view. As an inspiration, look at the built-in functions
|
||||
;; mentioned above.
|
||||
|
||||
;; See https://github.com/Fuco1/dired-hacks for the entire collection.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dash)
|
||||
(require 'dired-hacks-utils)
|
||||
|
||||
(require 'delsel)
|
||||
|
||||
(defgroup dired-narrow ()
|
||||
"Live-narrowing of search results for dired."
|
||||
:group 'dired-hacks
|
||||
:prefix "dired-narrow-")
|
||||
|
||||
(defvar dired-narrow-map
|
||||
(let ((map (make-sparse-keymap)))
|
||||
(define-key map (kbd "<up>") 'dired-narrow-previous-file)
|
||||
(define-key map (kbd "<down>") 'dired-narrow-next-file)
|
||||
(define-key map (kbd "<right>") 'dired-narrow-enter-directory)
|
||||
(define-key map (kbd "C-p") 'dired-narrow-previous-file)
|
||||
(define-key map (kbd "C-n") 'dired-narrow-next-file)
|
||||
(define-key map (kbd "C-j") 'dired-narrow-enter-directory)
|
||||
(define-key map (kbd "C-g") 'minibuffer-keyboard-quit)
|
||||
(define-key map (kbd "RET") 'exit-minibuffer)
|
||||
(define-key map (kbd "<return>") 'exit-minibuffer)
|
||||
map)
|
||||
"Keymap used while `dired-narrow' is reading the pattern.")
|
||||
|
||||
(defcustom dired-narrow-exit-action 'ignore
|
||||
"Function to call after exiting minibuffer.
|
||||
|
||||
Function takes no argument and is called with point over the file
|
||||
we should act on."
|
||||
:type '(choice (const :tag "Open file under point" dired-narrow-find-file)
|
||||
(function :tag "Use custom function."))
|
||||
:group 'dired-narrow)
|
||||
|
||||
(defcustom dired-narrow-exit-when-one-left nil
|
||||
"If there is only one file left while narrowing,
|
||||
exit minibuffer and call `dired-narrow-exit-action'."
|
||||
:type 'boolean
|
||||
:group 'dired-narrow)
|
||||
|
||||
(defcustom dired-narrow-enable-blinking t
|
||||
"If non-nil, highlight the chosen file shortly.
|
||||
Only works when `dired-narrow-exit-when-one-left' is non-nil."
|
||||
:type 'boolean
|
||||
:group 'dired-narrow)
|
||||
|
||||
(defcustom dired-narrow-blink-time 0.2
|
||||
"How many seconds should a chosen file be highlighted."
|
||||
:type 'number
|
||||
:group 'dired-narrow)
|
||||
|
||||
(defface dired-narrow-blink
|
||||
'((t :background "#eadc62"
|
||||
:foreground "black"))
|
||||
"The face used to highlight a chosen file
|
||||
when `dired-narrow-exit-when-one-left' and `dired-narrow-enable-blinking' are true."
|
||||
:group 'dired-narrow)
|
||||
|
||||
|
||||
;; Utils
|
||||
|
||||
;; this is `gnus-remove-text-with-property'
|
||||
(defun dired-narrow--remove-text-with-property (prop)
|
||||
"Delete all text in the current buffer with text property PROP."
|
||||
(let ((start (point-min))
|
||||
end)
|
||||
(unless (get-text-property start prop)
|
||||
(setq start (next-single-property-change start prop)))
|
||||
(while start
|
||||
(setq end (text-property-any start (point-max) prop nil))
|
||||
(delete-region start (or end (point-max)))
|
||||
(setq start (when end
|
||||
(next-single-property-change start prop))))))
|
||||
|
||||
(defvar dired-narrow-filter-function 'identity
|
||||
"Filter function used to filter the dired view.")
|
||||
|
||||
(defvar dired-narrow--current-file nil
|
||||
"Value of point just before exiting minibuffer.")
|
||||
|
||||
(defun dired-narrow--update (filter)
|
||||
"Make the files not matching the FILTER invisible.
|
||||
Return the count of visible files that are left after update."
|
||||
|
||||
(let ((inhibit-read-only t)
|
||||
(visible-files-cnt 0))
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
;; TODO: we might want to call this only if the filter gets less
|
||||
;; specialized.
|
||||
(dired-narrow--restore)
|
||||
(while (dired-hacks-next-file)
|
||||
(if (funcall dired-narrow-filter-function filter)
|
||||
(progn
|
||||
(setq visible-files-cnt (1+ visible-files-cnt))
|
||||
(when (fboundp 'dired-insert-set-properties)
|
||||
(dired-insert-set-properties (line-beginning-position) (1+ (line-end-position)))))
|
||||
(put-text-property (line-beginning-position) (1+ (line-end-position)) :dired-narrow t)
|
||||
(put-text-property (line-beginning-position) (1+ (line-end-position)) 'invisible :dired-narrow))))
|
||||
(unless (dired-hacks-next-file)
|
||||
(dired-hacks-previous-file))
|
||||
(unless (dired-utils-get-filename)
|
||||
(dired-hacks-previous-file))
|
||||
visible-files-cnt))
|
||||
|
||||
(defun dired-narrow--restore ()
|
||||
"Restore the invisible files of the current buffer."
|
||||
(let ((inhibit-read-only t))
|
||||
(remove-list-of-text-properties (point-min) (point-max)
|
||||
'(invisible :dired-narrow))
|
||||
(when (fboundp 'dired-insert-set-properties)
|
||||
(dired-insert-set-properties (point-min) (point-max)))))
|
||||
|
||||
|
||||
(defun dired-narrow--blink-current-file ()
|
||||
(let* ((beg (line-beginning-position))
|
||||
(end (line-end-position))
|
||||
(overlay (make-overlay beg end)))
|
||||
(overlay-put overlay 'face 'dired-narrow-blink)
|
||||
(redisplay)
|
||||
(sleep-for dired-narrow-blink-time)
|
||||
(discard-input)
|
||||
(delete-overlay overlay)))
|
||||
|
||||
|
||||
;; Live filtering
|
||||
|
||||
(defvar dired-narrow-buffer nil
|
||||
"Dired buffer we are currently filtering.")
|
||||
|
||||
(defvar dired-narrow--minibuffer-content ""
|
||||
"Content of the minibuffer during narrowing.")
|
||||
|
||||
(defun dired-narrow--minibuffer-setup ()
|
||||
"Set up the minibuffer for live filtering."
|
||||
(when dired-narrow-buffer
|
||||
(add-hook 'post-command-hook 'dired-narrow--live-update nil :local)))
|
||||
|
||||
(add-hook 'minibuffer-setup-hook 'dired-narrow--minibuffer-setup)
|
||||
|
||||
(defun dired-narrow--live-update ()
|
||||
"Update the dired buffer based on the contents of the minibuffer."
|
||||
(when dired-narrow-buffer
|
||||
(let ((current-filter (minibuffer-contents-no-properties))
|
||||
visible-files-cnt)
|
||||
(with-current-buffer dired-narrow-buffer
|
||||
(setq visible-files-cnt
|
||||
(unless (equal current-filter dired-narrow--minibuffer-content)
|
||||
(dired-narrow--update current-filter)))
|
||||
|
||||
(setq dired-narrow--minibuffer-content current-filter)
|
||||
(setq dired-narrow--current-file (dired-utils-get-filename))
|
||||
(set-window-point (get-buffer-window (current-buffer)) (point))
|
||||
|
||||
(when (and dired-narrow-exit-when-one-left
|
||||
visible-files-cnt
|
||||
(= visible-files-cnt 1))
|
||||
(when dired-narrow-enable-blinking
|
||||
(dired-narrow--blink-current-file))
|
||||
(exit-minibuffer))))))
|
||||
|
||||
(defun dired-narrow--internal (filter-function)
|
||||
"Narrow a dired buffer to the files matching a filter.
|
||||
|
||||
The function FILTER-FUNCTION is called on each line: if it
|
||||
returns non-nil, the line is kept, otherwise it is removed. The
|
||||
function takes one argument, which is the current filter string
|
||||
read from minibuffer."
|
||||
(let ((dired-narrow-buffer (current-buffer))
|
||||
(dired-narrow-filter-function filter-function)
|
||||
(disable-narrow nil))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(dired-narrow-mode 1)
|
||||
(add-to-invisibility-spec :dired-narrow)
|
||||
(setq disable-narrow (read-from-minibuffer
|
||||
(pcase dired-narrow-filter-function
|
||||
('dired-narrow--regexp-filter
|
||||
"Regex Filter:\s")
|
||||
('dired-narrow--fuzzy-filter
|
||||
"Fuzzy Filter:\s")
|
||||
(_ "Filter:\s"))
|
||||
nil dired-narrow-map))
|
||||
(let ((inhibit-read-only t))
|
||||
(dired-narrow--remove-text-with-property :dired-narrow))
|
||||
;; If the file no longer exists, we can't do anything, so
|
||||
;; set to nil
|
||||
(unless (dired-utils-goto-line dired-narrow--current-file)
|
||||
(setq dired-narrow--current-file nil)))
|
||||
(with-current-buffer dired-narrow-buffer
|
||||
(unless disable-narrow (dired-narrow-mode -1))
|
||||
(remove-from-invisibility-spec :dired-narrow)
|
||||
(dired-narrow--restore))
|
||||
(when (and disable-narrow
|
||||
dired-narrow--current-file
|
||||
dired-narrow-exit-action)
|
||||
(funcall dired-narrow-exit-action))
|
||||
(cond
|
||||
((equal disable-narrow "dired-narrow-enter-directory")
|
||||
(dired-narrow--internal filter-function))))))
|
||||
|
||||
|
||||
;; Interactive
|
||||
|
||||
(defun dired-narrow--regexp-filter (filter)
|
||||
(condition-case nil
|
||||
(string-match-p filter (dired-utils-get-filename 'no-dir))
|
||||
;; Return t if your regexp is incomplete/has errors, thus
|
||||
;; filtering nothing until you fix the regexp.
|
||||
(invalid-regexp t)))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-narrow-regexp ()
|
||||
"Narrow a dired buffer to the files matching a regular expression."
|
||||
(interactive)
|
||||
(dired-narrow--internal 'dired-narrow--regexp-filter))
|
||||
|
||||
(defun dired-narrow--string-filter (filter)
|
||||
(let ((words (split-string filter " ")))
|
||||
(--all? (save-excursion (search-forward it (line-end-position) t)) words)))
|
||||
|
||||
(defun dired-narrow-next-file ()
|
||||
"Move point to the next file."
|
||||
(interactive)
|
||||
(with-current-buffer dired-narrow-buffer
|
||||
(dired-hacks-next-file)))
|
||||
|
||||
(defun dired-narrow-previous-file ()
|
||||
"Move point to the previous file."
|
||||
(interactive)
|
||||
(with-current-buffer dired-narrow-buffer
|
||||
(dired-hacks-previous-file)))
|
||||
|
||||
(defun dired-narrow-find-file ()
|
||||
"Run `dired-find-file' or any remapped action on file under point."
|
||||
(interactive)
|
||||
(let ((function (or (command-remapping 'dired-find-file)
|
||||
'dired-find-file)))
|
||||
(funcall function)))
|
||||
|
||||
(defun dired-narrow-enter-directory ()
|
||||
"Descend into directory under point and initiate narrowing."
|
||||
(interactive)
|
||||
(let ((inhibit-read-only t))
|
||||
(erase-buffer)
|
||||
(insert "dired-narrow-enter-directory"))
|
||||
(exit-minibuffer))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-narrow ()
|
||||
"Narrow a dired buffer to the files matching a string.
|
||||
|
||||
If the string contains spaces, then each word is matched against
|
||||
the file name separately. To succeed, all of them have to match
|
||||
but the order does not matter.
|
||||
|
||||
For example \"foo bar\" matches filename \"bar-and-foo.el\"."
|
||||
(interactive)
|
||||
(dired-narrow--internal 'dired-narrow--string-filter))
|
||||
|
||||
(defun dired-narrow--fuzzy-filter (filter)
|
||||
(re-search-forward
|
||||
(mapconcat 'regexp-quote
|
||||
(mapcar 'char-to-string (string-to-list filter))
|
||||
".*")
|
||||
(line-end-position) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-narrow-fuzzy ()
|
||||
"Narrow a dired buffer to the files matching a fuzzy string.
|
||||
|
||||
A fuzzy string is constructed from the filter string by inserting
|
||||
\".*\" between each letter. This is then matched as regular
|
||||
expression against the file name."
|
||||
(interactive)
|
||||
(dired-narrow--internal 'dired-narrow--fuzzy-filter))
|
||||
|
||||
(define-minor-mode dired-narrow-mode
|
||||
"Minor mode for indicating when narrowing is in progress."
|
||||
:lighter " dired-narrow")
|
||||
|
||||
(defun dired-narrow--disable-on-revert ()
|
||||
"Disable `dired-narrow-mode' after revert."
|
||||
(dired-narrow-mode -1))
|
||||
|
||||
(add-hook 'dired-after-readin-hook 'dired-narrow--disable-on-revert)
|
||||
|
||||
(provide 'dired-narrow)
|
||||
;;; dired-narrow.el ends here
|
784
site-lisp/extensions-local/dired-subtree.el
Normal file
784
site-lisp/extensions-local/dired-subtree.el
Normal file
@ -0,0 +1,784 @@
|
||||
;;; dired-subtree.el --- Insert subdirectories in a tree-like fashion
|
||||
|
||||
;; Copyright (C) 2014-2015 Matúš Goljer
|
||||
|
||||
;; Author: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Maintainer: Matúš Goljer <matus.goljer@gmail.com>
|
||||
;; Keywords: files
|
||||
;; Version: 0.0.1
|
||||
;; Created: 25th February 2014
|
||||
;; Package-Requires: ((dash "2.5.0") (dired-hacks-utils "0.0.1"))
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Introduction
|
||||
;; ------------
|
||||
|
||||
;; The basic command to work with subdirectories in dired is `i',
|
||||
;; which inserts the subdirectory as a separate listing in the active
|
||||
;; dired buffer.
|
||||
|
||||
;; This package defines function `dired-subtree-insert' which instead
|
||||
;; inserts the subdirectory directly below its line in the original
|
||||
;; listing, and indent the listing of subdirectory to resemble a
|
||||
;; tree-like structure (somewhat similar to tree(1) except the pretty
|
||||
;; graphics). The tree display is somewhat more intuitive than the
|
||||
;; default "flat" subdirectory manipulation provided by `i'.
|
||||
|
||||
;; There are several presentation options and faces you can customize
|
||||
;; to change the way subtrees are displayed.
|
||||
|
||||
;; You can further remove the unwanted lines from the subtree by using
|
||||
;; `k' command or some of the built-in "focusing" functions, such as
|
||||
;; `dired-subtree-only-*' (see list below).
|
||||
|
||||
;; If you have the package `dired-filter', you can additionally filter
|
||||
;; the subtrees with global or local filters.
|
||||
|
||||
;; A demo of basic functionality is available on youtube:
|
||||
;; https://www.youtube.com/watch?v=z26b8HKFsNE
|
||||
|
||||
;; Interactive functions
|
||||
;; ---------------------
|
||||
|
||||
;; Here's a list of available interactive functions. You can read
|
||||
;; more about each one by using the built-in documentation facilities
|
||||
;; of emacs. It is adviced to place bindings for these into a
|
||||
;; convenient prefix key map, for example C-,
|
||||
|
||||
;; * `dired-subtree-insert'
|
||||
;; * `dired-subtree-remove'
|
||||
;; * `dired-subtree-toggle'
|
||||
;; * `dired-subtree-cycle'
|
||||
;; * `dired-subtree-revert'
|
||||
;; * `dired-subtree-narrow'
|
||||
;; * `dired-subtree-up'
|
||||
;; * `dired-subtree-down'
|
||||
;; * `dired-subtree-next-sibling'
|
||||
;; * `dired-subtree-previous-sibling'
|
||||
;; * `dired-subtree-beginning'
|
||||
;; * `dired-subtree-end'
|
||||
;; * `dired-subtree-mark-subtree'
|
||||
;; * `dired-subtree-unmark-subtree'
|
||||
;; * `dired-subtree-only-this-file'
|
||||
;; * `dired-subtree-only-this-directory'
|
||||
|
||||
;; If you have package `dired-filter', additional command
|
||||
;; `dired-subtree-apply-filter' is available.
|
||||
|
||||
;; See https://github.com/Fuco1/dired-hacks for the entire collection.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'dired-hacks-utils)
|
||||
(require 'dash)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defgroup dired-subtree ()
|
||||
"Insert subdirectories in a tree-like fashion."
|
||||
:group 'dired-hacks
|
||||
:prefix "dired-subtree-")
|
||||
|
||||
(defcustom dired-subtree-line-prefix " "
|
||||
"A prefix put into each nested subtree.
|
||||
|
||||
The prefix is repeated \"depth\" times.
|
||||
|
||||
Alternatively, it can be a function taking one argument---the
|
||||
depth---that creates the prefix."
|
||||
:type '(choice string function)
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-line-prefix-face 'parents
|
||||
"Specifies how the prefix is fontified."
|
||||
:type '(radio
|
||||
(const :tag "No face applied" nil)
|
||||
(const :tag "Inherit from current subtree" subtree)
|
||||
(const :tag "Inherit from all parents" parents))
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-use-backgrounds t
|
||||
"When non-nil, add a background face to a subtree listing."
|
||||
:type 'boolean
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-after-insert-hook ()
|
||||
"Hook run at the end of `dired-subtree-insert'."
|
||||
:type 'hook
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-after-remove-hook ()
|
||||
"Hook run at the end of `dired-subtree-remove'."
|
||||
:type 'hook
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-cycle-depth 3
|
||||
"Default depth expanded by `dired-subtree-cycle'."
|
||||
:type 'natnum
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defcustom dired-subtree-ignored-regexp
|
||||
(concat "^" (regexp-opt vc-directory-exclusion-list) "$")
|
||||
"Matching directories will not be expanded in `dired-subtree-cycle'."
|
||||
:type 'regexp
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defgroup dired-subtree-faces ()
|
||||
"Faces used in `dired-subtree'."
|
||||
:group 'dired-subtree)
|
||||
|
||||
(defface dired-subtree-depth-1-face
|
||||
'((t (:background "#252e30")))
|
||||
"Background for depth 1 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defface dired-subtree-depth-2-face
|
||||
'((t (:background "#232a2b")))
|
||||
"Background for depth 2 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defface dired-subtree-depth-3-face
|
||||
'((t (:background "#212627")))
|
||||
"Background for depth 3 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defface dired-subtree-depth-4-face
|
||||
'((t (:background "#1e2223")))
|
||||
"Background for depth 4 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defface dired-subtree-depth-5-face
|
||||
'((t (:background "#1c1d1e")))
|
||||
"Background for depth 5 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defface dired-subtree-depth-6-face
|
||||
'((t (:background "#1a191a")))
|
||||
"Background for depth 6 subtrees"
|
||||
:group 'dired-subtree-faces)
|
||||
|
||||
(defvar dired-subtree-overlays nil
|
||||
"Subtree overlays in this buffer.")
|
||||
(make-variable-buffer-local 'dired-subtree-overlays)
|
||||
|
||||
|
||||
;;; Overlay manipulation
|
||||
;; Maybe we should abstract the overlay-foo into some subtree
|
||||
;; functions instead!!!
|
||||
|
||||
(defun dired-subtree--remove-overlay (ov)
|
||||
"Remove dired-subtree overlay OV."
|
||||
(setq dired-subtree-overlays
|
||||
(--remove (equal it ov) dired-subtree-overlays))
|
||||
(delete-overlay ov))
|
||||
|
||||
(defun dired-subtree--remove-overlays (ovs)
|
||||
"Remove dired-subtree overlays OVS."
|
||||
(mapc 'dired-subtree--remove-overlay ovs))
|
||||
|
||||
(defun dired-subtree--cleanup-overlays ()
|
||||
"Remove the `nil' values from `dired-subtree-overlays'."
|
||||
(setq dired-subtree-overlays
|
||||
(--remove (not (overlay-buffer it)) dired-subtree-overlays)))
|
||||
|
||||
(defun dired-subtree--get-all-ovs ()
|
||||
"Get all dired-subtree overlays in this buffer."
|
||||
(--filter (overlay-get it 'dired-subtree-depth) (overlays-in (point-min) (point-max))))
|
||||
|
||||
(defun dired-subtree--get-all-ovs-at-point (&optional p)
|
||||
"Get all dired-subtree overlays at point P."
|
||||
(setq p (or p (point)))
|
||||
(--filter (overlay-get it 'dired-subtree-depth) (overlays-at (point))))
|
||||
|
||||
(defun dired-subtree--get-ovs-in (&optional beg end)
|
||||
"Get all dired-subtree overlays between BEG and END.
|
||||
|
||||
BEG and END default to the region spanned by overlay at point."
|
||||
(when (not beg)
|
||||
(let ((ov (dired-subtree--get-ov)))
|
||||
(setq beg (overlay-start ov))
|
||||
(setq end (overlay-end ov))))
|
||||
(--filter (and (overlay-get it 'dired-subtree-depth)
|
||||
(>= (overlay-start it) beg)
|
||||
(<= (overlay-end it) end))
|
||||
(overlays-in (point-min) (point-max))))
|
||||
|
||||
(defun dired-subtree--get-ov (&optional p)
|
||||
"Get the parent subtree overlay at point."
|
||||
(setq p (or p (point)))
|
||||
(car (--sort (> (overlay-get it 'dired-subtree-depth)
|
||||
(overlay-get other 'dired-subtree-depth))
|
||||
(dired-subtree--get-all-ovs-at-point p))))
|
||||
|
||||
(defun dired-subtree--get-depth (ov)
|
||||
"Get subtree depth."
|
||||
(or (and ov (overlay-get ov 'dired-subtree-depth)) 0))
|
||||
|
||||
|
||||
|
||||
;;; helpers
|
||||
(defvar dired-subtree-preserve-properties '(dired-subtree-filter)
|
||||
"Properties that should be preserved between read-ins.")
|
||||
|
||||
(defun dired-subtree--after-readin (&optional subtrees)
|
||||
"Insert the SUBTREES again after dired buffer has been reverted.
|
||||
|
||||
If no SUBTREES are specified, use `dired-subtree-overlays'."
|
||||
(-when-let (subtrees-to-process (or subtrees dired-subtree-overlays))
|
||||
(let* ((ovs-by-depth (--sort (< (car it) (car other))
|
||||
(--group-by (overlay-get it 'dired-subtree-depth)
|
||||
subtrees-to-process)))
|
||||
(sorted-ovs (--map (cons (car it)
|
||||
(--map (-cons* it
|
||||
(overlay-get it 'dired-subtree-name)
|
||||
(-map (lambda (x) (cons x (overlay-get it x)))
|
||||
dired-subtree-preserve-properties)) (cdr it)))
|
||||
ovs-by-depth)))
|
||||
;; (depth (path1 ov1 (prop1 . value1) (prop2 . value2)) (path2 ...))
|
||||
(--each sorted-ovs
|
||||
(--each (cdr it)
|
||||
(when (dired-utils-goto-line (cadr it))
|
||||
(dired-subtree--remove-overlay (car it))
|
||||
(dired-subtree-insert)
|
||||
(let ((ov (dired-subtree--get-ov)))
|
||||
(--each (cddr it)
|
||||
(overlay-put ov (car it) (cdr it)))
|
||||
(dired-subtree--filter-subtree ov))))))))
|
||||
|
||||
(defun dired-subtree--after-insert ()
|
||||
"After inserting the subtree, setup dired-details/dired-hide-details-mode."
|
||||
(if (fboundp 'dired-insert-set-properties)
|
||||
(let ((inhibit-read-only t)
|
||||
(ov (dired-subtree--get-ov)))
|
||||
(dired-insert-set-properties (overlay-start ov) (overlay-end ov)))
|
||||
(when (featurep 'dired-details)
|
||||
(dired-details-delete-overlays)
|
||||
(dired-details-activate))))
|
||||
|
||||
(add-hook 'dired-after-readin-hook 'dired-subtree--after-readin)
|
||||
|
||||
(add-hook 'dired-subtree-after-insert-hook 'dired-subtree--after-insert)
|
||||
|
||||
(defun dired-subtree--unmark ()
|
||||
"Unmark a file without moving point."
|
||||
(save-excursion (dired-unmark 1)))
|
||||
|
||||
(defun dired-subtree--dired-line-is-directory-or-link-p ()
|
||||
"Return non-nil if line under point is a directory or symlink"
|
||||
;; We've replaced `file-directory-p' with the regexp test to
|
||||
;; speed up filters over TRAMP. So long as dired/ls format
|
||||
;; doesn't change, we're good.
|
||||
;; 'd' for directories, 'l' for potential symlinks to directories.
|
||||
(save-excursion (beginning-of-line) (looking-at "..[dl]")))
|
||||
|
||||
(defun dired-subtree--is-expanded-p ()
|
||||
"Return non-nil if directory under point is expanded."
|
||||
(save-excursion
|
||||
(when (dired-utils-get-filename)
|
||||
(let ((depth (dired-subtree--get-depth (dired-subtree--get-ov))))
|
||||
(dired-next-line 1)
|
||||
(< depth (dired-subtree--get-depth (dired-subtree--get-ov)))))))
|
||||
|
||||
(defmacro dired-subtree-with-subtree (&rest forms)
|
||||
"Run FORMS on each file in this subtree."
|
||||
(declare (debug (body)))
|
||||
`(save-excursion
|
||||
(dired-subtree-beginning)
|
||||
,@forms
|
||||
(while (dired-subtree-next-sibling)
|
||||
,@forms)))
|
||||
|
||||
|
||||
;;;; Interactive
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-narrow ()
|
||||
"Narrow the buffer to this subtree."
|
||||
(interactive)
|
||||
(-when-let (ov (dired-subtree--get-ov))
|
||||
(narrow-to-region (overlay-start ov)
|
||||
(overlay-end ov))))
|
||||
|
||||
;;; Navigation
|
||||
|
||||
;; make the arguments actually do something
|
||||
;;;###autoload
|
||||
(defun dired-subtree-up (&optional arg)
|
||||
"Jump up one directory."
|
||||
(interactive "p")
|
||||
(-when-let (ov (dired-subtree--get-ov))
|
||||
(goto-char (overlay-start ov))
|
||||
(dired-previous-line 1)))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-down (&optional arg)
|
||||
"Jump down one directory."
|
||||
(interactive "p")
|
||||
(-when-let* ((p (point))
|
||||
(ov (car (--sort
|
||||
(< (overlay-start it)
|
||||
(overlay-start other))
|
||||
(--remove
|
||||
(< (overlay-start it) p)
|
||||
(dired-subtree--get-all-ovs))))))
|
||||
(goto-char (overlay-start ov))
|
||||
(dired-move-to-filename)))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-next-sibling (&optional arg)
|
||||
"Go to the next sibling."
|
||||
(interactive "p")
|
||||
(let ((current-ov (dired-subtree--get-ov)))
|
||||
(dired-next-line 1)
|
||||
(let ((new-ov (dired-subtree--get-ov)))
|
||||
(cond
|
||||
((not (dired-utils-is-file-p))
|
||||
nil)
|
||||
((< (dired-subtree--get-depth current-ov)
|
||||
(dired-subtree--get-depth new-ov))
|
||||
(goto-char (overlay-end new-ov))
|
||||
(dired-move-to-filename)
|
||||
t)
|
||||
((> (dired-subtree--get-depth current-ov)
|
||||
(dired-subtree--get-depth new-ov))
|
||||
;; add option to either go to top or stay at the end
|
||||
(dired-previous-line 1)
|
||||
nil)
|
||||
(t t)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-previous-sibling (&optional arg)
|
||||
"Go to the previous sibling."
|
||||
(interactive "p")
|
||||
(let ((current-ov (dired-subtree--get-ov)))
|
||||
(dired-previous-line 1)
|
||||
(let ((new-ov (dired-subtree--get-ov)))
|
||||
(cond
|
||||
;; this will need better handlign if we have inserted
|
||||
;; subdirectories
|
||||
((not (dired-utils-is-file-p))
|
||||
nil)
|
||||
((< (dired-subtree--get-depth current-ov)
|
||||
(dired-subtree--get-depth new-ov))
|
||||
(goto-char (overlay-start new-ov))
|
||||
(dired-previous-line 1)
|
||||
t)
|
||||
((> (dired-subtree--get-depth current-ov)
|
||||
(dired-subtree--get-depth new-ov))
|
||||
;; add option to either go to top or stay at the end
|
||||
(dired-next-line 1)
|
||||
nil)
|
||||
(t t)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-beginning ()
|
||||
"Go to the first file in this subtree."
|
||||
(interactive)
|
||||
(let ((ov (dired-subtree--get-ov)))
|
||||
(if (not ov)
|
||||
;; do something when not in subtree
|
||||
t
|
||||
(goto-char (overlay-start ov))
|
||||
(dired-move-to-filename))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-end ()
|
||||
"Go to the first file in this subtree."
|
||||
(interactive)
|
||||
(let ((ov (dired-subtree--get-ov)))
|
||||
(if (not ov)
|
||||
;; do something when not in subtree
|
||||
t
|
||||
(goto-char (overlay-end ov))
|
||||
(dired-previous-line 1))))
|
||||
|
||||
;;; Marking
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-mark-subtree (&optional all)
|
||||
"Mark all files in this subtree.
|
||||
|
||||
With prefix argument mark all the files in subdirectories
|
||||
recursively."
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(if all
|
||||
(let ((beg (save-excursion
|
||||
(dired-subtree-beginning)
|
||||
(point)))
|
||||
(end (save-excursion
|
||||
(dired-subtree-end)
|
||||
(point))))
|
||||
(dired-mark-files-in-region
|
||||
(progn (goto-char beg) (line-beginning-position))
|
||||
(progn (goto-char end) (line-end-position))))
|
||||
(dired-subtree-beginning)
|
||||
(save-excursion (dired-mark 1))
|
||||
(while (dired-subtree-next-sibling)
|
||||
(save-excursion (dired-mark 1))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-unmark-subtree (&optional all)
|
||||
"Unmark all files in this subtree.
|
||||
|
||||
With prefix argument unmark all the files in subdirectories
|
||||
recursively."
|
||||
(interactive)
|
||||
(let ((dired-marker-char ? ))
|
||||
(dired-subtree-mark-subtree all)))
|
||||
|
||||
;;; Insertion/deletion
|
||||
;;;###autoload
|
||||
(defun dired-subtree-revert ()
|
||||
"Revert the subtree.
|
||||
|
||||
This means reinserting the content of this subtree and all its
|
||||
children."
|
||||
(interactive)
|
||||
(let ((inhibit-read-only t)
|
||||
(file-name (dired-utils-get-filename)))
|
||||
(-when-let* ((ov (dired-subtree--get-ov))
|
||||
(ovs (dired-subtree--get-ovs-in)))
|
||||
(dired-subtree-up)
|
||||
(delete-region (overlay-start ov) (overlay-end ov))
|
||||
(dired-subtree--after-readin ovs)
|
||||
(when file-name
|
||||
(dired-utils-goto-line file-name)))))
|
||||
|
||||
(defun dired-subtree--readin (dir-name)
|
||||
"Read in the directory.
|
||||
|
||||
Return a string suitable for insertion in `dired' buffer."
|
||||
(with-temp-buffer
|
||||
(insert-directory dir-name dired-listing-switches nil t)
|
||||
(delete-char -1)
|
||||
(goto-char (point-min))
|
||||
(delete-region
|
||||
(progn (beginning-of-line) (point))
|
||||
(progn (forward-line
|
||||
(if (save-excursion
|
||||
(forward-line 1)
|
||||
(end-of-line)
|
||||
(looking-back "\\."))
|
||||
3 1)) (point)))
|
||||
(insert " ")
|
||||
(while (= (forward-line) 0)
|
||||
(insert " "))
|
||||
(delete-char -2)
|
||||
(buffer-string)))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-insert ()
|
||||
"Insert subtree under this directory."
|
||||
(interactive)
|
||||
(when (and (dired-subtree--dired-line-is-directory-or-link-p)
|
||||
(not (dired-subtree--is-expanded-p)))
|
||||
(let* ((dir-name (dired-get-filename nil))
|
||||
(listing (dired-subtree--readin (file-name-as-directory dir-name)))
|
||||
beg end)
|
||||
(read-only-mode -1)
|
||||
(move-end-of-line 1)
|
||||
;; this is pretty ugly, I'm sure it can be done better
|
||||
(save-excursion
|
||||
(insert listing)
|
||||
(setq end (+ (point) 2)))
|
||||
(newline)
|
||||
(setq beg (point))
|
||||
(let ((inhibit-read-only t))
|
||||
(remove-text-properties (1- beg) beg '(dired-filename)))
|
||||
(let* ((ov (make-overlay beg end))
|
||||
(parent (dired-subtree--get-ov (1- beg)))
|
||||
(depth (or (and parent (1+ (overlay-get parent 'dired-subtree-depth)))
|
||||
1))
|
||||
(face (intern (format "dired-subtree-depth-%d-face" depth))))
|
||||
(when dired-subtree-use-backgrounds
|
||||
(overlay-put ov 'face face))
|
||||
;; refactor this to some function
|
||||
(overlay-put ov 'line-prefix
|
||||
(if (stringp dired-subtree-line-prefix)
|
||||
(if (not dired-subtree-use-backgrounds)
|
||||
(apply 'concat (-repeat depth dired-subtree-line-prefix))
|
||||
(cond
|
||||
((eq nil dired-subtree-line-prefix-face)
|
||||
(apply 'concat
|
||||
(-repeat depth dired-subtree-line-prefix)))
|
||||
((eq 'subtree dired-subtree-line-prefix-face)
|
||||
(concat
|
||||
dired-subtree-line-prefix
|
||||
(propertize
|
||||
(apply 'concat
|
||||
(-repeat (1- depth) dired-subtree-line-prefix))
|
||||
'face face)))
|
||||
((eq 'parents dired-subtree-line-prefix-face)
|
||||
(concat
|
||||
dired-subtree-line-prefix
|
||||
(apply 'concat
|
||||
(--map
|
||||
(propertize dired-subtree-line-prefix
|
||||
'face
|
||||
(intern (format "dired-subtree-depth-%d-face" it)))
|
||||
(number-sequence 1 (1- depth))))))))
|
||||
(funcall dired-subtree-line-prefix depth)))
|
||||
(overlay-put ov 'dired-subtree-name dir-name)
|
||||
(overlay-put ov 'dired-subtree-parent parent)
|
||||
(overlay-put ov 'dired-subtree-depth depth)
|
||||
(overlay-put ov 'evaporate t)
|
||||
(push ov dired-subtree-overlays))
|
||||
(goto-char beg)
|
||||
(dired-move-to-filename)
|
||||
(read-only-mode 1)
|
||||
(when (bound-and-true-p dired-filter-mode) (dired-filter-mode 1))
|
||||
(run-hooks 'dired-subtree-after-insert-hook))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-remove ()
|
||||
"Remove subtree at point."
|
||||
(interactive)
|
||||
(-when-let* ((ov (dired-subtree--get-ov))
|
||||
(ovs (dired-subtree--get-ovs-in
|
||||
(overlay-start ov)
|
||||
(overlay-end ov))))
|
||||
(let ((inhibit-read-only t))
|
||||
(dired-subtree-up)
|
||||
(delete-region (overlay-start ov)
|
||||
(overlay-end ov))
|
||||
(dired-subtree--remove-overlays ovs)))
|
||||
(run-hooks 'dired-subtree-after-remove-hook))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-toggle ()
|
||||
"Insert subtree at point or remove it if it was not present."
|
||||
(interactive)
|
||||
(if (dired-subtree--is-expanded-p)
|
||||
(progn
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-remove)
|
||||
;; #175 fixes the case of the first line in dired when the
|
||||
;; cursor jumps to the header in dired rather then to the
|
||||
;; first file in buffer
|
||||
(when (bobp)
|
||||
(dired-next-line 1)))
|
||||
(save-excursion (dired-subtree-insert))))
|
||||
|
||||
(defun dired-subtree--insert-recursive (depth max-depth)
|
||||
"Insert full subtree at point."
|
||||
(save-excursion
|
||||
(let ((name (dired-get-filename nil t)))
|
||||
(when (and name (file-directory-p name)
|
||||
(<= depth (or max-depth depth))
|
||||
(or (= 1 depth)
|
||||
(not (string-match-p dired-subtree-ignored-regexp
|
||||
(file-name-nondirectory name)))))
|
||||
(if (dired-subtree--is-expanded-p)
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-insert))
|
||||
(dired-subtree-end)
|
||||
(dired-subtree--insert-recursive (1+ depth) max-depth)
|
||||
(while (dired-subtree-previous-sibling)
|
||||
(dired-subtree--insert-recursive (1+ depth) max-depth))))))
|
||||
|
||||
(defvar dired-subtree--cycle-previous nil
|
||||
"Remember previous action for `dired-subtree-cycle'")
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-cycle (&optional max-depth)
|
||||
"Org-mode like cycle visibility:
|
||||
|
||||
1) Show subtree
|
||||
2) Show subtree recursively (if previous command was cycle)
|
||||
3) Remove subtree
|
||||
|
||||
Numeric prefix will set max depth"
|
||||
(interactive "P")
|
||||
(save-excursion
|
||||
(cond
|
||||
;; prefix - show subtrees up to max-depth
|
||||
(max-depth
|
||||
(when (dired-subtree--is-expanded-p)
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-remove))
|
||||
(dired-subtree--insert-recursive 1 (if (integerp max-depth) max-depth nil))
|
||||
(setq dired-subtree--cycle-previous :full))
|
||||
;; if directory is not expanded, expand one level
|
||||
((not (dired-subtree--is-expanded-p))
|
||||
(dired-subtree-insert)
|
||||
(setq dired-subtree--cycle-previous :insert))
|
||||
;; hide if previous command was not cycle or tree was fully expanded
|
||||
((or (not (eq last-command 'dired-subtree-cycle))
|
||||
(eq dired-subtree--cycle-previous :full))
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-remove)
|
||||
(setq dired-subtree--cycle-previous :remove))
|
||||
(t
|
||||
(dired-subtree--insert-recursive 1 dired-subtree-cycle-depth)
|
||||
(setq dired-subtree--cycle-previous :full)))))
|
||||
|
||||
(defun dired-subtree--filter-up (keep-dir kill-siblings)
|
||||
(save-excursion
|
||||
(let (ov)
|
||||
(save-excursion
|
||||
(while (dired-subtree-up))
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-mark-subtree t))
|
||||
(if keep-dir
|
||||
(dired-subtree-unmark-subtree)
|
||||
(dired-subtree--unmark))
|
||||
(while (and (dired-subtree-up)
|
||||
(> (dired-subtree--get-depth (dired-subtree--get-ov)) 0))
|
||||
(if (not kill-siblings)
|
||||
(dired-subtree--unmark)
|
||||
(dired-subtree--unmark)
|
||||
(let ((here (point)))
|
||||
(dired-subtree-with-subtree
|
||||
(when (and (dired-subtree--is-expanded-p)
|
||||
(/= (point) here))
|
||||
(dired-subtree--unmark)
|
||||
(save-excursion
|
||||
(dired-next-line 1)
|
||||
(dired-subtree-unmark-subtree t)))))))
|
||||
(dired-do-kill-lines)
|
||||
(dired-subtree--cleanup-overlays))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-only-this-file (&optional arg)
|
||||
"Remove all the siblings on the route from this file to the top-most directory.
|
||||
|
||||
With ARG non-nil, do not remove expanded directories in parents."
|
||||
(interactive "P")
|
||||
(dired-subtree--filter-up nil arg))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-only-this-directory (&optional arg)
|
||||
"Remove all the siblings on the route from this directory to the top-most directory.
|
||||
|
||||
With ARG non-nil, do not remove expanded directories in parents."
|
||||
(interactive "P")
|
||||
(dired-subtree--filter-up t arg))
|
||||
|
||||
;;; filtering
|
||||
(defun dired-subtree--filter-update-bs (ov)
|
||||
"Update the local filter list.
|
||||
|
||||
This function assumes that `dired-filter-stack' is dynamically
|
||||
bound to relevant value."
|
||||
(let* ((filt (dired-filter--describe-filters))
|
||||
(before-str (if (equal filt "") nil (concat " Local filters: " filt "\n"))))
|
||||
(overlay-put ov 'before-string before-str)))
|
||||
|
||||
(defun dired-subtree--filter-subtree (ov)
|
||||
"Run the filter for this subtree.
|
||||
|
||||
It is only safe to call this from readin.
|
||||
|
||||
This depends on `dired-filter' package."
|
||||
(when (featurep 'dired-filter)
|
||||
(let ((dired-filter-stack (overlay-get ov 'dired-subtree-filter)))
|
||||
(save-restriction
|
||||
(widen)
|
||||
(dired-subtree-narrow)
|
||||
(dired-filter--expunge)
|
||||
(dired-subtree--filter-update-bs ov)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun dired-subtree-apply-filter ()
|
||||
"Push a local filter for this subtree.
|
||||
|
||||
This depends on `dired-filter' package.
|
||||
|
||||
It works exactly the same as global dired filters, only
|
||||
restricted to a subtree. The global filter is also applied to
|
||||
the subtree. The filter action is read from `dired-filter-map'."
|
||||
(interactive)
|
||||
(when (featurep 'dired-filter)
|
||||
(-when-let (ov (dired-subtree--get-ov))
|
||||
(let ((dired-filter-stack (overlay-get ov 'dired-subtree-filter))
|
||||
(glob (current-global-map))
|
||||
(loc (current-local-map))
|
||||
cmd)
|
||||
(cl-flet ((dired-filter--update
|
||||
()
|
||||
(save-restriction
|
||||
(overlay-put ov 'dired-subtree-filter dired-filter-stack)
|
||||
(widen)
|
||||
(dired-subtree-revert)
|
||||
(dired-subtree--filter-update-bs ov))))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(use-global-map dired-filter-map)
|
||||
(use-local-map nil)
|
||||
(setq cmd (key-binding (read-key-sequence "Choose filter action: "))))
|
||||
(use-global-map glob)
|
||||
(use-local-map loc))
|
||||
(let ((p (point))
|
||||
(beg (overlay-start ov))
|
||||
(current-file (dired-utils-get-filename)))
|
||||
(unwind-protect
|
||||
(call-interactively cmd)
|
||||
(unless (dired-utils-goto-line current-file)
|
||||
(goto-char beg)
|
||||
(forward-line)
|
||||
(goto-char (min p (1- (overlay-end (dired-subtree--get-ov)))))
|
||||
(dired-move-to-filename)))))))))
|
||||
|
||||
|
||||
;;; Here we redefine a couple of functions from dired.el to make them
|
||||
;;; subtree-aware
|
||||
|
||||
;; If the point is in a subtree, we need to provide a proper
|
||||
;; directory, not the one that would come from `dired-subdir-alist'.
|
||||
(defun dired-current-directory (&optional localp)
|
||||
"Return the name of the subdirectory to which this line belongs.
|
||||
This returns a string with trailing slash, like `default-directory'.
|
||||
Optional argument means return a file name relative to `default-directory'."
|
||||
(let ((here (point))
|
||||
(alist (or dired-subdir-alist
|
||||
;; probably because called in a non-dired buffer
|
||||
(error "No subdir-alist in %s" (current-buffer))))
|
||||
elt dir)
|
||||
(while alist
|
||||
(setq elt (car alist)
|
||||
dir (car elt)
|
||||
;; use `<=' (not `<') as subdir line is part of subdir
|
||||
alist (if (<= (dired-get-subdir-min elt) here)
|
||||
nil ; found
|
||||
(cdr alist))))
|
||||
;; dired-subdir: modify dir here if we are in a "subtree" view
|
||||
(-when-let (parent (dired-subtree--get-ov))
|
||||
(setq dir (concat (overlay-get parent 'dired-subtree-name) "/")))
|
||||
;; end
|
||||
(if localp
|
||||
(dired-make-relative dir default-directory)
|
||||
dir)))
|
||||
|
||||
;; Since the tree-inserted directory is not in the dired-subdir-alist,
|
||||
;; we need to guard against nil.
|
||||
(defun dired-get-subdir ()
|
||||
;;"Return the subdir name on this line, or nil if not on a headerline."
|
||||
;; Look up in the alist whether this is a headerline.
|
||||
(save-excursion
|
||||
(let ((cur-dir (dired-current-directory)))
|
||||
(beginning-of-line) ; alist stores b-o-l positions
|
||||
(and (zerop (- (point)
|
||||
(or (dired-get-subdir-min
|
||||
(assoc cur-dir
|
||||
dired-subdir-alist))
|
||||
0))) ;; dired-subtree: return zero if current
|
||||
;; dir is not in `dired-subdir-alist'.
|
||||
cur-dir))))
|
||||
|
||||
(provide 'dired-subtree)
|
||||
|
||||
;;; dired-subtree.el ends here
|
126
site-lisp/extensions-local/echo-keys.el
Normal file
126
site-lisp/extensions-local/echo-keys.el
Normal file
@ -0,0 +1,126 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'cl-lib)
|
||||
|
||||
;;; Code:
|
||||
(defcustom echo-keys-last-record nil
|
||||
"Last command processed by 'echo-keys'."
|
||||
:type 'string
|
||||
:group 'echo-keys)
|
||||
|
||||
(defcustom echo-keys-last-record-count 0
|
||||
"Number of times the `echo-keys-last-record` command was repeated."
|
||||
:type 'integer
|
||||
:group 'echo-keys)
|
||||
|
||||
(defcustom echo-key-window-width 40
|
||||
"Default width of the *echo-keys* window."
|
||||
:type 'integer
|
||||
:group 'echo-keys)
|
||||
|
||||
(defcustom echo-key-password-protection nil
|
||||
"Temporarily disable echo key for password input."
|
||||
:type 'boolean
|
||||
:group 'echo-keys)
|
||||
|
||||
(defcustom echo-key-coallesce-repeats t
|
||||
"If 't', show <key> <command> [<echo-keys-last-record-count> times].
|
||||
If 'nil', show <key> <commands> n lines."
|
||||
:type 'boolean
|
||||
:group 'echo-keys)
|
||||
|
||||
(defun echo-keys ()
|
||||
(let ((deactivate-mark deactivate-mark)
|
||||
(keys (this-command-keys)))
|
||||
(when (and keys
|
||||
(not (eq (current-buffer) (get-buffer "*echo-keys*")))
|
||||
(not echo-key-password-protection))
|
||||
(save-excursion
|
||||
(with-current-buffer (get-buffer-create "*echo-keys*")
|
||||
(goto-char (point-max))
|
||||
(if (eql this-command 'self-insert-command)
|
||||
(let ((desc (key-description keys)))
|
||||
(if (= 1 (length desc))
|
||||
(insert desc)
|
||||
(insert " " desc " "))
|
||||
(setf echo-keys-last-record this-command
|
||||
echo-keys-last-record-count 1))
|
||||
(if (and echo-key-coallesce-repeats
|
||||
(eql echo-keys-last-record this-command))
|
||||
(progn
|
||||
(incf echo-keys-last-record-count)
|
||||
;; update the last line
|
||||
(forward-line -1)
|
||||
(if (= 2 echo-keys-last-record-count)
|
||||
(progn
|
||||
(end-of-line)
|
||||
(insert (format " [%d times]" echo-keys-last-record-count)))
|
||||
(save-match-data
|
||||
(when (re-search-forward " \\[\\([0-9]+\\) times\\]" nil t)
|
||||
(delete-region (match-beginning 1) (match-end 1))
|
||||
(goto-char (match-beginning 1))
|
||||
(insert (format "%d" echo-keys-last-record-count)))))
|
||||
(forward-line 1))
|
||||
(progn
|
||||
(insert (if (eq 'self-insert-command echo-keys-last-record)
|
||||
"\n"
|
||||
"")
|
||||
(format "%-12s %s\n"
|
||||
(key-description keys)
|
||||
this-command))
|
||||
(setf echo-keys-last-record this-command
|
||||
echo-keys-last-record-count 1))))
|
||||
(dolist (window (window-list))
|
||||
(when (eq (window-buffer window) (current-buffer))
|
||||
(with-selected-window window
|
||||
;; We need to use both to get the effect.
|
||||
(set-window-point window (point))
|
||||
(end-of-buffer)))))))))
|
||||
|
||||
(defun toggle-echo-keys ()
|
||||
"Toggle displaying the *echo-key* buffer."
|
||||
(interactive)
|
||||
(if (member 'echo-keys (default-value 'pre-command-hook))
|
||||
(let ((echo-buffer (get-buffer "*echo-keys*")))
|
||||
(remove-hook 'pre-command-hook 'echo-keys)
|
||||
(dolist (window (window-list))
|
||||
(when (eq (window-buffer window) echo-buffer)
|
||||
(delete-window window))))
|
||||
(progn
|
||||
(delete-other-windows)
|
||||
(split-window nil (- (window-width) echo-key-window-width) t)
|
||||
(other-window 1)
|
||||
(switch-to-buffer (get-buffer-create "*echo-keys*"))
|
||||
(unless (eq major-mode 'echo-keys-mode)
|
||||
(echo-keys-mode))
|
||||
(toggle-truncate-lines +1)
|
||||
(set-window-dedicated-p (selected-window) t)
|
||||
(other-window 1)
|
||||
(add-hook 'pre-command-hook 'echo-keys))))
|
||||
|
||||
(defadvice echo-key--read-passwd--disable (before read-passwd)
|
||||
(message "echo-key--read-passwd--disable")
|
||||
(setf echo-key-password-protection t))
|
||||
|
||||
(defadvice echo-key--read-passwd--enable (after read-passwd)
|
||||
(message "echo-key--read-passwd--enable")
|
||||
(setf echo-key-password-protection nil))
|
||||
|
||||
(defun echo-keys-clean ()
|
||||
"Erase the `*echo-keys*' buffer."
|
||||
(interactive)
|
||||
(with-current-buffer "*echo-keys*"
|
||||
(erase-buffer)))
|
||||
|
||||
(defvar echo-keys-mode-map
|
||||
(let ((ek-mode-map (make-sparse-keymap)))
|
||||
(define-key ek-mode-map (kbd "C-c e e") #'toggle-echo-keys)
|
||||
(define-key ek-mode-map (kbd "C-c e c") #'echo-keys-clean)
|
||||
ek-mode-map))
|
||||
|
||||
(define-derived-mode echo-keys-mode fundamental-mode "Echo-keys"
|
||||
"Major mode for echo-keys.")
|
||||
|
||||
(provide 'echo-keys)
|
||||
|
||||
;;; echo-keys.el ends here.
|
21
site-lisp/extensions-local/evals.el
Normal file
21
site-lisp/extensions-local/evals.el
Normal file
@ -0,0 +1,21 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun ld-eval-elisp-to-next-line ()
|
||||
"Replace the preceding sexp with its value."
|
||||
(interactive)
|
||||
(let ((value (eval (elisp--preceding-sexp))))
|
||||
(newline-and-indent)
|
||||
(insert (format "%S" value))))
|
||||
|
||||
(defun ld-eval-elisp-and-replace ()
|
||||
"Replace the preceding sexp with its value."
|
||||
(interactive)
|
||||
(let ((value (eval (elisp--preceding-sexp))))
|
||||
(backward-kill-sexp)
|
||||
(insert (format "%S" value))))
|
||||
|
||||
(provide 'evals)
|
||||
|
||||
;;; evals.el ends here
|
81
site-lisp/extensions-local/force-indent.el
Normal file
81
site-lisp/extensions-local/force-indent.el
Normal file
@ -0,0 +1,81 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
|
||||
;; use variable 'tab-width' value as indent size
|
||||
|
||||
(defun force-indent-line ()
|
||||
(let (col)
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(setq col (+ (current-column) tab-width))
|
||||
(indent-line-to col))
|
||||
(when (< (current-column) col)
|
||||
(back-to-indentation))))
|
||||
|
||||
(defun indent-line ()
|
||||
(interactive)
|
||||
(let ((bt (save-excursion
|
||||
(back-to-indentation)
|
||||
(current-column))))
|
||||
(cond
|
||||
((< (current-column) bt)
|
||||
(back-to-indentation))
|
||||
((looking-at "\\s-*\n")
|
||||
(let ((col (save-excursion
|
||||
(forward-line -1)
|
||||
(back-to-indentation)
|
||||
(current-column))))
|
||||
(if (< (current-column) col)
|
||||
(indent-line-to col)
|
||||
(force-indent-line))))
|
||||
(t
|
||||
(force-indent-line)))))
|
||||
|
||||
(defun un-indent-line ()
|
||||
(interactive)
|
||||
(let (col)
|
||||
(save-excursion
|
||||
(back-to-indentation)
|
||||
(setq col (- (current-column) tab-width))
|
||||
(when (>= col 0)
|
||||
(indent-line-to col)))))
|
||||
|
||||
(defun indent-region (start stop)
|
||||
(interactive "r")
|
||||
(setq stop (copy-marker stop))
|
||||
(goto-char start)
|
||||
(while (< (point) stop)
|
||||
(unless (and (bolp) (eolp))
|
||||
(force-indent-line))
|
||||
(forward-line 1)))
|
||||
|
||||
(defun un-indent-region (start stop)
|
||||
(interactive "r")
|
||||
(setq stop (copy-marker stop))
|
||||
(goto-char start)
|
||||
(while (< (point) stop)
|
||||
(unless (and (bolp) (eolp))
|
||||
(un-indent-line))
|
||||
(forward-line 1)))
|
||||
|
||||
(defun ld-indent ()
|
||||
(interactive)
|
||||
(if (use-region-p)
|
||||
(save-excursion
|
||||
(indent-region (region-beginning) (region-end))
|
||||
(setq deactivate-mark nil))
|
||||
(indent-line)))
|
||||
|
||||
(defun ld-un-indent ()
|
||||
(interactive)
|
||||
(if (use-region-p)
|
||||
(save-excursion
|
||||
(un-indent-region (region-beginning) (region-end))
|
||||
(setq deactivate-mark nil))
|
||||
(un-indent-line)))
|
||||
|
||||
(provide 'force-indent)
|
||||
|
||||
;;; force-indent.el ends here
|
93
site-lisp/extensions-local/frame-restore.el
Normal file
93
site-lisp/extensions-local/frame-restore.el
Normal file
@ -0,0 +1,93 @@
|
||||
;;; frame-restore.el --- save/restore frame size&position at shutdown/startup
|
||||
|
||||
;; Copyright (C) 2002 by Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Patrick Anderson
|
||||
;; Version: 1.3
|
||||
|
||||
;; This file is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation; either version 2, or (at your option)
|
||||
;; any later version.
|
||||
|
||||
;; This file is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with GNU Emacs; see the file COPYING. If not, write to
|
||||
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
;; Boston, MA 02111-1307, USA.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; ChangeLog
|
||||
;; 1.3: simplified install (now just copy one line to .emacs, and eval the next)
|
||||
;; 1.3: added checks for running in terminal
|
||||
;; 1.3: added checks for running on non-w32
|
||||
;; 1.2: added font save/restore
|
||||
;; 1.1: added more descriptive, correct installation docs
|
||||
|
||||
;;;installation:
|
||||
;;1. put this file in your load path and add to your .emacs file (as the last thing) (without the semicolon):
|
||||
;;(require 'frame-restore)
|
||||
;;2. now evaluate the next line (don't uncomment it) [by putting the cursor at the end and pressing C-xC-e]
|
||||
;;(progn (require 'desktop) (customize-set-variable 'desktop-enable t) (desktop-save "~/") (require 'frame-restore))
|
||||
;;3. now change your font using S-down-mouse-1, adjust your frame size, then shutdown/restart emacs to test.
|
||||
;;once installed, i never have problems, but before that, it seems possible to get into strange states. if that happens try:
|
||||
;;1. shutdown emacs
|
||||
;;2. delete .emacs.desktop
|
||||
;;3. restart
|
||||
;;4. follow normal install
|
||||
;;since the font is stored here, don't also store it through a customization of the 'default' face. you may customize that face, just make sure the "Font Family" attribute box is unchecked.
|
||||
|
||||
;;;Code:
|
||||
(require 'cl-lib)
|
||||
|
||||
;this must be global - as that is how desktop-globals-to-save works
|
||||
;(defvar final-frame-params '((frame-parameter (selected-frame) 'font) 50 50 150 50 nil)) ;font, left, top, width, height, maximized
|
||||
(defvar final-frame-params '("-adobe-courier-medium-r-normal--*-120-*-*-m-*-iso8859-1" 50 50 150 50 nil)) ;font, left, top, width, height, maximized
|
||||
|
||||
(if window-system
|
||||
(add-hook 'after-init-hook
|
||||
'(lambda()
|
||||
"this is executed as emacs is coming up - _after_ final-frame-params have been read from `.emacs.desktop'."
|
||||
(when desktop-enable
|
||||
(desktop-load-default)
|
||||
(desktop-read)
|
||||
;;now size and position frame according to the values read from disk
|
||||
(set-default-font (first final-frame-params)) ;do font first - as it will goof with the frame size
|
||||
(set-frame-size (selected-frame) (fourth final-frame-params) (fifth final-frame-params))
|
||||
(set-frame-position (selected-frame) (max (eval (second final-frame-params)) 0) (max (eval (third final-frame-params)) 0))
|
||||
(if (sixth final-frame-params)
|
||||
(if (eq window-system 'w32)
|
||||
(w32-send-sys-command ?\xf030)
|
||||
;else, do X something
|
||||
))))))
|
||||
|
||||
(if window-system
|
||||
(add-hook 'desktop-save-hook
|
||||
'(lambda()
|
||||
(let ((maximized (listp (frame-parameter (selected-frame) 'left))))
|
||||
"this hook sets the fram size/pos vars before `desktop.el' writes them out to disk"
|
||||
(if (eq window-system 'w32)
|
||||
(w32-send-sys-command ?\xf120) ;restore the frame (so we can save the 'restored' size/pos)
|
||||
;else, do X something
|
||||
)
|
||||
;;prepend our vars to the save list so `desktop.el' will save them out to disk
|
||||
(setq desktop-globals-to-save (cons 'final-frame-params
|
||||
desktop-globals-to-save))
|
||||
|
||||
(setq final-frame-params
|
||||
(list
|
||||
(frame-parameter (selected-frame) 'font)
|
||||
(frame-parameter (selected-frame) 'left) ;x
|
||||
(frame-parameter (selected-frame) 'top) ;y
|
||||
(frame-width) ;width
|
||||
(frame-height) ;height
|
||||
maximized))))) ;if this frame param is a list, we're probably maximized (not guaranteed)
|
||||
)
|
||||
|
||||
(provide 'frame-restore)
|
||||
;;; frame-restore.el ends here
|
141
site-lisp/extensions-local/goto-last-change.el
Normal file
141
site-lisp/extensions-local/goto-last-change.el
Normal file
@ -0,0 +1,141 @@
|
||||
;;; goto-last-change.el --- Move point through buffer-undo-list positions
|
||||
|
||||
;; Copyright © 2003 Kevin Rodgers
|
||||
|
||||
;; Author: Kevin Rodgers <ihs_4664@yahoo.com>
|
||||
;; Created: 17 Jun 2003
|
||||
;; Version: $Revision: 1.2 $
|
||||
;; Keywords: convenience
|
||||
;; RCS: $Id: goto-last-change.el,v 1.2 2003/07/30 17:43:47 kevinr Exp kevinr $
|
||||
|
||||
;; Contributors:
|
||||
;; Attila Lendvai <attila.lendvai@gmail.com> (line distance and auto marks)
|
||||
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License as
|
||||
;; published by the Free Software Foundation; either version 2 of
|
||||
;; the License, or (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be
|
||||
;; useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
;; PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public
|
||||
;; License along with this program; if not, write to the Free
|
||||
;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
|
||||
;; MA 02111-1307 USA
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; After installing goto-last-change.el in a `load-path' directory and
|
||||
;; compiling it with `M-x byte-compile-file', load it with
|
||||
;; (require 'goto-last-change)
|
||||
;; or autoload it with
|
||||
;; (autoload 'goto-last-change "goto-last-change"
|
||||
;; "Set point to the position of the last change." t)
|
||||
;;
|
||||
;; You may also want to bind a key to `M-x goto-last-change', e.g.
|
||||
;; (global-set-key "\C-x\C-\\" 'goto-last-change)
|
||||
|
||||
;; goto-last-change.el was written in response to to the following:
|
||||
;;
|
||||
;; From: Dan Jacobson <jidanni@jidanni.org>
|
||||
;; Newsgroups: gnu.emacs.bug
|
||||
;; Subject: function to go to spot of last change
|
||||
;; Date: Sun, 15 Jun 2003 00:15:08 +0000 (UTC)
|
||||
;; Sender: news <news@main.gmane.org>
|
||||
;; Message-ID: <mailman.7910.1055637181.21513.bug-gnu-emacs@gnu.org>
|
||||
;; NNTP-Posting-Host: monty-python.gnu.org
|
||||
;;
|
||||
;;
|
||||
;; Why of course, a function to get the user to the spot of last changes
|
||||
;; in the current buffer(s?), that's what emacs must lack.
|
||||
;;
|
||||
;; How many times have you found yourself mosying [<-not in spell
|
||||
;; checker!?] thru a file when you wonder, where the heck was I just
|
||||
;; editing? Well, the best you can do is hit undo, ^F, and undo again,
|
||||
;; to get back. Hence the "burning need" for the additional function,
|
||||
;; which you might name the-jacobson-memorial-function, due to its brilliance.
|
||||
;; --
|
||||
;; http://jidanni.org/ Taiwan(04)25854780
|
||||
|
||||
;;; Code:
|
||||
(provide 'goto-last-change)
|
||||
|
||||
(or (fboundp 'last) ; Emacs 20
|
||||
(require 'cl)) ; Emacs 19
|
||||
|
||||
(defvar goto-last-change-undo nil
|
||||
"The `buffer-undo-list' entry of the previous \\[goto-last-change] command.")
|
||||
(make-variable-buffer-local 'goto-last-change-undo)
|
||||
|
||||
;;;###autoload
|
||||
(defun goto-last-change (&optional mark-point minimal-line-distance)
|
||||
"Set point to the position of the last change.
|
||||
Consecutive calls set point to the position of the previous change.
|
||||
With a prefix arg (optional arg MARK-POINT non-nil), set mark so \
|
||||
\\[exchange-point-and-mark]
|
||||
will return point to the current position."
|
||||
(interactive "P")
|
||||
;; (unless (buffer-modified-p)
|
||||
;; (error "Buffer not modified"))
|
||||
(when (eq buffer-undo-list t)
|
||||
(error "No undo information in this buffer"))
|
||||
(when mark-point
|
||||
(push-mark))
|
||||
(unless minimal-line-distance
|
||||
(setq minimal-line-distance 10))
|
||||
(let ((position nil)
|
||||
(undo-list (if (and (eq this-command last-command)
|
||||
goto-last-change-undo)
|
||||
(cdr (memq goto-last-change-undo buffer-undo-list))
|
||||
buffer-undo-list))
|
||||
undo)
|
||||
(while (and undo-list
|
||||
(or (not position)
|
||||
(eql position (point))
|
||||
(and minimal-line-distance
|
||||
;; The first invocation always goes to the last change, subsequent ones skip
|
||||
;; changes closer to (point) then minimal-line-distance.
|
||||
(memq last-command '(goto-last-change
|
||||
goto-last-change-with-auto-marks))
|
||||
(< (count-lines (min position (point-max)) (point))
|
||||
minimal-line-distance))))
|
||||
(setq undo (car undo-list))
|
||||
(cond ((and (consp undo) (integerp (car undo)) (integerp (cdr undo)))
|
||||
;; (BEG . END)
|
||||
(setq position (cdr undo)))
|
||||
((and (consp undo) (stringp (car undo))) ; (TEXT . POSITION)
|
||||
(setq position (abs (cdr undo))))
|
||||
((and (consp undo) (eq (car undo) t))) ; (t HIGH . LOW)
|
||||
((and (consp undo) (null (car undo)))
|
||||
;; (nil PROPERTY VALUE BEG . END)
|
||||
(setq position (cdr (last undo))))
|
||||
((and (consp undo) (markerp (car undo)))) ; (MARKER . DISTANCE)
|
||||
((integerp undo)) ; POSITION
|
||||
((null undo)) ; nil
|
||||
(t (error "Invalid undo entry: %s" undo)))
|
||||
(setq undo-list (cdr undo-list)))
|
||||
(cond (position
|
||||
(setq goto-last-change-undo undo)
|
||||
(goto-char (min position (point-max))))
|
||||
((and (eq this-command last-command)
|
||||
goto-last-change-undo)
|
||||
(setq goto-last-change-undo nil)
|
||||
(error "No further undo information"))
|
||||
(t
|
||||
(setq goto-last-change-undo nil)
|
||||
(error "Buffer not modified")))))
|
||||
|
||||
(defun goto-last-change-with-auto-marks (&optional minimal-line-distance)
|
||||
"Calls goto-last-change and sets the mark at only the first invocations
|
||||
in a sequence of invocations."
|
||||
(interactive "P")
|
||||
(goto-last-change (not (or (eq last-command 'goto-last-change-with-auto-marks)
|
||||
(eq last-command t)))
|
||||
minimal-line-distance))
|
||||
|
||||
;; (global-set-key "\C-x\C-\\" 'goto-last-change)
|
||||
|
||||
;;; goto-last-change.el ends here
|
124
site-lisp/extensions-local/goto-line-preview.el
Normal file
124
site-lisp/extensions-local/goto-line-preview.el
Normal file
@ -0,0 +1,124 @@
|
||||
;;; goto-line-preview.el --- Preview line when executing `goto-line` command -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2019-2023 Shen, Jen-Chieh
|
||||
;; Created date 2019-03-01 14:53:00
|
||||
|
||||
;; Author: Shen, Jen-Chieh <jcs090218@gmail.com>
|
||||
;; URL: https://github.com/emacs-vs/goto-line-preview
|
||||
;; Version: 0.1.1
|
||||
;; Package-Requires: ((emacs "25"))
|
||||
;; Keywords: convenience line navigation
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
;; This program is free software; you can redistribute it and/or modify
|
||||
;; it under the terms of the GNU General Public License as published by
|
||||
;; the Free Software Foundation, either version 3 of the License, or
|
||||
;; (at your option) any later version.
|
||||
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Preview line when executing `goto-line` command.
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defgroup goto-line-preview nil
|
||||
"Preview line when executing `goto-line` command."
|
||||
:prefix "goto-line-preview-"
|
||||
:group 'convenience
|
||||
:group 'tools
|
||||
:link '(url-link :tag "Repository" "https://github.com/emacs-vs/goto-line-preview"))
|
||||
|
||||
(defcustom goto-line-preview-before-hook nil
|
||||
"Hooks run before `goto-line-preview' is run."
|
||||
:group 'goto-line-preview
|
||||
:type 'hook)
|
||||
|
||||
(defcustom goto-line-preview-after-hook nil
|
||||
"Hooks run after `goto-line-preview' is run."
|
||||
:group 'goto-line-preview
|
||||
:type 'hook)
|
||||
|
||||
(defvar goto-line-preview--prev-window nil
|
||||
"Record down the previous window before we do preivew display.")
|
||||
|
||||
(defvar goto-line-preview--prev-line-num nil
|
||||
"Record down the previous line number before we do preivew display.")
|
||||
|
||||
(defvar goto-line-preview--relative-p nil
|
||||
"Flag to see if this command relative.")
|
||||
|
||||
(defun goto-line-preview--do (line-num)
|
||||
"Do goto LINE-NUM."
|
||||
(save-selected-window
|
||||
(select-window goto-line-preview--prev-window)
|
||||
(goto-char (point-min))
|
||||
(forward-line (1- line-num))))
|
||||
|
||||
(defun goto-line-preview--do-preview ()
|
||||
"Do the goto line preview action."
|
||||
(save-selected-window
|
||||
(when goto-line-preview--prev-window
|
||||
(let ((line-num-str (thing-at-point 'line)))
|
||||
(select-window goto-line-preview--prev-window)
|
||||
(if line-num-str
|
||||
(let ((line-num (string-to-number line-num-str)))
|
||||
(when goto-line-preview--relative-p
|
||||
(setq line-num (+ goto-line-preview--prev-line-num line-num)))
|
||||
(unless (zerop line-num) (goto-line-preview--do line-num)))
|
||||
(goto-line-preview--do goto-line-preview--prev-line-num))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun goto-line-preview ()
|
||||
"Preview goto line."
|
||||
(interactive)
|
||||
(let ((goto-line-preview--prev-window (selected-window))
|
||||
(window-point (window-point))
|
||||
(goto-line-preview--prev-line-num (line-number-at-pos))
|
||||
jumped)
|
||||
(run-hooks 'goto-line-preview-before-hook)
|
||||
(unwind-protect
|
||||
(setq jumped (read-number
|
||||
(let ((lines (line-number-at-pos (point-max))))
|
||||
(format (if goto-line-preview--relative-p
|
||||
"[%d] Goto line relative: (%d to %d) "
|
||||
"[%d] Goto line: (%d to %d) ")
|
||||
goto-line-preview--prev-line-num
|
||||
(max 0 (min 1 lines))
|
||||
lines))))
|
||||
(if jumped
|
||||
(with-current-buffer (window-buffer goto-line-preview--prev-window)
|
||||
(unless (region-active-p) (push-mark window-point)))
|
||||
(set-window-point goto-line-preview--prev-window window-point))
|
||||
(run-hooks 'goto-line-preview-after-hook))))
|
||||
|
||||
;;;###autoload
|
||||
(defun goto-line-preview-relative ()
|
||||
"Preview goto line relative."
|
||||
(interactive)
|
||||
(let ((goto-line-preview--relative-p t))
|
||||
(goto-line-preview)))
|
||||
|
||||
;;;###autoload
|
||||
(define-obsolete-function-alias 'goto-line-preview-goto-line 'goto-line-preview "0.1.1")
|
||||
|
||||
(defun goto-line-preview--minibuffer-setup ()
|
||||
"Locally set up preview hooks for this minibuffer command."
|
||||
(when (memq this-command '(goto-line-preview
|
||||
goto-line-preview-goto-line
|
||||
goto-line-preview-relative))
|
||||
(add-hook 'post-command-hook #'goto-line-preview--do-preview nil t)))
|
||||
|
||||
(add-hook 'minibuffer-setup-hook 'goto-line-preview--minibuffer-setup)
|
||||
|
||||
(provide 'goto-line-preview)
|
||||
;;; goto-line-preview.el ends here
|
312
site-lisp/extensions-local/highlight-indentation.el
Normal file
312
site-lisp/extensions-local/highlight-indentation.el
Normal file
@ -0,0 +1,312 @@
|
||||
;;; highlight-indentation.el --- Minor modes for highlighting indentation
|
||||
;; Author: Anton Johansson <anton.johansson@gmail.com> - http://antonj.se
|
||||
;; Created: Dec 15 23:42:04 2010
|
||||
;; Version: 0.7.0
|
||||
;; URL: https://github.com/antonj/Highlight-Indentation-for-Emacs
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License as
|
||||
;; published by the Free Software Foundation; either version 2 of
|
||||
;; the License, or (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be
|
||||
;; useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
;; PURPOSE. See the GNU General Public License for more details.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;; Customize `highlight-indentation-face', and
|
||||
;; `highlight-indentation-current-column-face' to suit your theme.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(defgroup highlight-indentation nil
|
||||
"Highlight Indentation"
|
||||
:prefix "highlight-indentation-"
|
||||
:group 'basic-faces)
|
||||
|
||||
(defface highlight-indentation-face
|
||||
;; Fringe has non intrusive color in most color-themes
|
||||
'((t :inherit fringe))
|
||||
"Basic face for highlighting indentation guides."
|
||||
:group 'highlight-indentation)
|
||||
|
||||
(defcustom highlight-indentation-offset
|
||||
(if (and (boundp 'standard-indent) standard-indent) standard-indent 2)
|
||||
"Default indentation offset, used if no other can be found from
|
||||
major mode. This value is always used by
|
||||
`highlight-indentation-mode' if set buffer local. Set buffer
|
||||
local with `highlight-indentation-set-offset'"
|
||||
:type 'integer
|
||||
:group 'highlight-indentation)
|
||||
|
||||
(defcustom highlight-indentation-blank-lines nil
|
||||
"Show indentation guides on blank lines. Experimental.
|
||||
Known issues:
|
||||
- Doesn't work well with completion popups that use overlays
|
||||
- Overlays on blank lines sometimes aren't cleaned up or updated perfectly
|
||||
Can be refreshed by scrolling
|
||||
- Not yet implemented for highlight-indentation-current-column-mode
|
||||
- May not work perfectly near the bottom of the screen
|
||||
- Point appears after indent guides on blank lines"
|
||||
:type 'boolean
|
||||
:group 'highlight-indentation)
|
||||
|
||||
(defvar highlight-indentation-overlay-priority 1)
|
||||
(defvar highlight-indentation-current-column-overlay-priority 2)
|
||||
|
||||
(defconst highlight-indentation-hooks
|
||||
'((after-change-functions (lambda (start end length)
|
||||
(highlight-indentation-redraw-region
|
||||
start end
|
||||
'highlight-indentation-overlay
|
||||
'highlight-indentation-put-overlays-region))
|
||||
t t)
|
||||
(window-scroll-functions (lambda (win start)
|
||||
(highlight-indentation-redraw-window
|
||||
win
|
||||
'highlight-indentation-overlay
|
||||
'highlight-indentation-put-overlays-region
|
||||
start))
|
||||
nil t)))
|
||||
|
||||
(defun highlight-indentation-get-buffer-windows (&optional all-frames)
|
||||
"Return a list of windows displaying the current buffer."
|
||||
(get-buffer-window-list (current-buffer) 'no-minibuf all-frames))
|
||||
|
||||
(defun highlight-indentation-delete-overlays-buffer (overlay)
|
||||
"Delete all overlays in the current buffer."
|
||||
(save-restriction
|
||||
(widen)
|
||||
(highlight-indentation-delete-overlays-region (point-min) (point-max) overlay)))
|
||||
|
||||
(defun highlight-indentation-delete-overlays-region (start end overlay)
|
||||
"Delete overlays between START and END."
|
||||
(mapc #'(lambda (o)
|
||||
(if (overlay-get o overlay) (delete-overlay o)))
|
||||
(overlays-in start end)))
|
||||
|
||||
(defun highlight-indentation-redraw-window (win overlay func &optional start)
|
||||
"Redraw win starting from START."
|
||||
(highlight-indentation-redraw-region (or start (window-start win)) (window-end win t) overlay func))
|
||||
|
||||
(defun highlight-indentation-redraw-region (start end overlay func)
|
||||
"Erase and read overlays between START and END."
|
||||
(save-match-data
|
||||
(save-excursion
|
||||
(let ((inhibit-point-motion-hooks t)
|
||||
(start (save-excursion (goto-char start) (beginning-of-line) (point)))
|
||||
|
||||
(end (save-excursion (goto-char end) (line-beginning-position 2))))
|
||||
(highlight-indentation-delete-overlays-region start end overlay)
|
||||
(funcall func start end overlay)))))
|
||||
|
||||
(defun highlight-indentation-redraw-all-windows (overlay func &optional all-frames)
|
||||
"Redraw the all windows showing the current buffer."
|
||||
(dolist (win (highlight-indentation-get-buffer-windows all-frames))
|
||||
(highlight-indentation-redraw-window win overlay func)))
|
||||
|
||||
(defun highlight-indentation-put-overlays-region (start end overlay)
|
||||
"Place overlays between START and END."
|
||||
(goto-char end)
|
||||
(let (o ;; overlay
|
||||
(last-indent 0)
|
||||
(last-char 0)
|
||||
(pos (point))
|
||||
(loop t))
|
||||
(while (and loop
|
||||
(>= pos start))
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let ((c 0)
|
||||
(cur-column (current-column)))
|
||||
(while (and (setq c (char-after))
|
||||
(integerp c)
|
||||
(not (= 10 c)) ;; newline
|
||||
(= 32 c)) ;; space
|
||||
(when (= 0 (% cur-column highlight-indentation-offset))
|
||||
(let ((p (point)))
|
||||
(setq o (make-overlay p (+ p 1))))
|
||||
(overlay-put o overlay t)
|
||||
(overlay-put o 'priority highlight-indentation-overlay-priority)
|
||||
(overlay-put o 'face 'highlight-indentation-face))
|
||||
(forward-char)
|
||||
(setq cur-column (current-column)))
|
||||
(when (and highlight-indentation-blank-lines
|
||||
(integerp c)
|
||||
(or (= 10 c)
|
||||
(= 13 c)))
|
||||
(when (< cur-column last-indent)
|
||||
(let ((column cur-column)
|
||||
(s nil)
|
||||
(show t)
|
||||
num-spaces)
|
||||
(while (< column last-indent)
|
||||
(if (>= 0
|
||||
(setq num-spaces
|
||||
(%
|
||||
(- last-indent column)
|
||||
highlight-indentation-offset)))
|
||||
(progn
|
||||
(setq num-spaces (1- highlight-indentation-offset))
|
||||
(setq show t))
|
||||
(setq show nil))
|
||||
(setq s (cons (concat
|
||||
(if show
|
||||
(propertize " "
|
||||
'face
|
||||
'highlight-indentation-face)
|
||||
"")
|
||||
(make-string num-spaces 32))
|
||||
s))
|
||||
(setq column (+ column num-spaces (if show 1 0))))
|
||||
(setq s (apply 'concat (reverse s)))
|
||||
(let ((p (point)))
|
||||
(setq o (make-overlay p p)))
|
||||
(overlay-put o overlay t)
|
||||
(overlay-put o 'priority highlight-indentation-overlay-priority)
|
||||
(overlay-put o 'after-string s))
|
||||
(setq cur-column last-indent)))
|
||||
(setq last-indent (* highlight-indentation-offset
|
||||
(ceiling (/ (float cur-column)
|
||||
highlight-indentation-offset))))))
|
||||
(when (= pos start)
|
||||
(setq loop nil))
|
||||
(forward-line -1) ;; previous line
|
||||
(setq pos (point)))))
|
||||
|
||||
(defun highlight-indentation-guess-offset ()
|
||||
"Get indentation offset of current buffer."
|
||||
(cond ((and (eq major-mode 'python-mode) (boundp 'python-indent))
|
||||
python-indent)
|
||||
((and (eq major-mode 'python-mode) (boundp 'py-indent-offset))
|
||||
py-indent-offset)
|
||||
((and (eq major-mode 'python-mode) (boundp 'python-indent-offset))
|
||||
python-indent-offset)
|
||||
((and (eq major-mode 'ruby-mode) (boundp 'ruby-indent-level))
|
||||
ruby-indent-level)
|
||||
((and (eq major-mode 'scala-mode) (boundp 'scala-indent:step))
|
||||
scala-indent:step)
|
||||
((and (eq major-mode 'scala-mode) (boundp 'scala-mode-indent:step))
|
||||
scala-mode-indent:step)
|
||||
((and (or (eq major-mode 'scss-mode) (eq major-mode 'css-mode)) (boundp 'css-indent-offset))
|
||||
css-indent-offset)
|
||||
((and (eq major-mode 'nxml-mode) (boundp 'nxml-child-indent))
|
||||
nxml-child-indent)
|
||||
((and (eq major-mode 'coffee-mode) (boundp 'coffee-tab-width))
|
||||
coffee-tab-width)
|
||||
((and (eq major-mode 'js-mode) (boundp 'js-indent-level))
|
||||
js-indent-level)
|
||||
((and (eq major-mode 'js2-mode) (boundp 'js2-basic-offset))
|
||||
js2-basic-offset)
|
||||
((and (fboundp 'derived-mode-class) (eq (derived-mode-class major-mode) 'sws-mode) (boundp 'sws-tab-width))
|
||||
sws-tab-width)
|
||||
((and (eq major-mode 'web-mode) (boundp 'web-mode-markup-indent-offset))
|
||||
web-mode-markup-indent-offset) ; other similar vars: web-mode-{css-indent,scripts}-offset
|
||||
((and (eq major-mode 'web-mode) (boundp 'web-mode-html-offset)) ; old var
|
||||
web-mode-html-offset)
|
||||
((and (local-variable-p 'c-basic-offset) (boundp 'c-basic-offset))
|
||||
c-basic-offset)
|
||||
((and (eq major-mode 'yaml-mode) (boundp 'yaml-indent-offset))
|
||||
yaml-indent-offset)
|
||||
((and (eq major-mode 'elixir-mode) (boundp 'elixir-smie-indent-basic))
|
||||
elixir-smie-indent-basic)
|
||||
(t
|
||||
(default-value 'highlight-indentation-offset))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode highlight-indentation-mode
|
||||
"Highlight indentation minor mode highlights indentation based on spaces"
|
||||
:lighter " ||"
|
||||
(when (not highlight-indentation-mode) ;; OFF
|
||||
(highlight-indentation-delete-overlays-buffer 'highlight-indentation-overlay)
|
||||
(dolist (hook highlight-indentation-hooks)
|
||||
(remove-hook (car hook) (nth 1 hook) (nth 3 hook))))
|
||||
|
||||
(when highlight-indentation-mode ;; ON
|
||||
(when (not (local-variable-p 'highlight-indentation-offset))
|
||||
(set (make-local-variable 'highlight-indentation-offset)
|
||||
(highlight-indentation-guess-offset)))
|
||||
|
||||
;; Setup hooks
|
||||
(dolist (hook highlight-indentation-hooks)
|
||||
(apply 'add-hook hook))
|
||||
(highlight-indentation-redraw-all-windows 'highlight-indentation-overlay
|
||||
'highlight-indentation-put-overlays-region)))
|
||||
|
||||
;;;###autoload
|
||||
(defun highlight-indentation-set-offset (offset)
|
||||
"Set indentation offset locally in buffer, will prevent
|
||||
highlight-indentation from trying to guess indentation offset
|
||||
from major mode"
|
||||
(interactive
|
||||
(if (and current-prefix-arg (not (consp current-prefix-arg)))
|
||||
(list (prefix-numeric-value current-prefix-arg))
|
||||
(list (read-number "Indentation offset: "))))
|
||||
(set (make-local-variable 'highlight-indentation-offset) offset)
|
||||
(when highlight-indentation-mode
|
||||
(highlight-indentation-mode)))
|
||||
|
||||
;;; This minor mode will highlight the indentation of the current line
|
||||
;;; as a vertical bar (grey background color) aligned with the column of the
|
||||
;;; first character of the current line.
|
||||
(defface highlight-indentation-current-column-face
|
||||
;; Fringe has non intrusive color in most color-themes
|
||||
'((t (:background "black")))
|
||||
"Basic face for highlighting indentation guides."
|
||||
:group 'highlight-indentation)
|
||||
|
||||
(defconst highlight-indentation-current-column-hooks
|
||||
'((post-command-hook (lambda ()
|
||||
(highlight-indentation-redraw-all-windows 'highlight-indentation-current-column-overlay
|
||||
'highlight-indentation-current-column-put-overlays-region)) nil t)))
|
||||
|
||||
(defun highlight-indentation-current-column-put-overlays-region (start end overlay)
|
||||
"Place overlays between START and END."
|
||||
(let (o ;; overlay
|
||||
(last-indent 0)
|
||||
(indent (save-excursion (back-to-indentation) (current-column)))
|
||||
(pos start))
|
||||
(goto-char start)
|
||||
;; (message "doing it %d" indent)
|
||||
(while (< pos end)
|
||||
(beginning-of-line)
|
||||
(while (and (integerp (char-after))
|
||||
(not (= 10 (char-after))) ;; newline
|
||||
(= 32 (char-after))) ;; space
|
||||
(when (= (current-column) indent)
|
||||
(setq pos (point)
|
||||
last-indent pos
|
||||
o (make-overlay pos (+ pos 1)))
|
||||
(overlay-put o overlay t)
|
||||
(overlay-put o 'priority highlight-indentation-current-column-overlay-priority)
|
||||
(overlay-put o 'face 'highlight-indentation-current-column-face))
|
||||
(forward-char))
|
||||
(forward-line) ;; Next line
|
||||
(setq pos (point)))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode highlight-indentation-current-column-mode
|
||||
"Highlight Indentation minor mode displays a vertical bar
|
||||
corresponding to the indentation of the current line"
|
||||
:lighter " |"
|
||||
|
||||
(when (not highlight-indentation-current-column-mode) ;; OFF
|
||||
(highlight-indentation-delete-overlays-buffer 'highlight-indentation-current-column-overlay)
|
||||
(dolist (hook highlight-indentation-current-column-hooks)
|
||||
(remove-hook (car hook) (nth 1 hook) (nth 3 hook))))
|
||||
|
||||
(when highlight-indentation-current-column-mode ;; ON
|
||||
(when (not (local-variable-p 'highlight-indentation-offset))
|
||||
(set (make-local-variable 'highlight-indentation-offset)
|
||||
(highlight-indentation-guess-offset)))
|
||||
|
||||
;; Setup hooks
|
||||
(dolist (hook highlight-indentation-current-column-hooks)
|
||||
(apply 'add-hook hook))
|
||||
(highlight-indentation-redraw-all-windows 'highlight-indentation-current-column-overlay
|
||||
'highlight-indentation-current-column-put-overlays-region)))
|
||||
|
||||
(provide 'highlight-indentation)
|
||||
|
||||
;;; highlight-indentation.el ends here
|
157
site-lisp/extensions-local/highlight-parentheses.el
Normal file
157
site-lisp/extensions-local/highlight-parentheses.el
Normal file
@ -0,0 +1,157 @@
|
||||
;;; highlight-parentheses.el --- highlight surrounding parentheses
|
||||
;;
|
||||
;; Copyright (C) 2007 Nikolaj Schumacher
|
||||
;;
|
||||
;; Author: Nikolaj Schumacher <bugs * nschum de>
|
||||
;; Version: 1.0
|
||||
;; Keywords: faces, matching
|
||||
;; URL: http://nschum.de/src/emacs/highlight-parentheses/
|
||||
;; Compatibility: GNU Emacs 22.x
|
||||
;;
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
;;
|
||||
;; This program is free software; you can redistribute it and/or
|
||||
;; modify it under the terms of the GNU General Public License
|
||||
;; as published by the Free Software Foundation; either version 2
|
||||
;; of the License, or (at your option) any later version.
|
||||
;;
|
||||
;; This program is distributed in the hope that it will be useful,
|
||||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;; GNU General Public License for more details.
|
||||
;;
|
||||
;; You should have received a copy of the GNU General Public License
|
||||
;; along with this program; if not, write to the Free Software
|
||||
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
;;
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; Add the following to your .emacs file:
|
||||
;; (require 'highlight-parentheses)
|
||||
;;
|
||||
;; Enable `highlight-symbol-mode'.
|
||||
;;
|
||||
;;; Changes Log:
|
||||
;;
|
||||
;; 2007-07-30 (1.0)
|
||||
;; Added background highlighting and faces.
|
||||
;;
|
||||
;; 2007-05-15 (0.9.1)
|
||||
;; Support for defcustom. Changed from vector to list.
|
||||
;;
|
||||
;; 2007-04-26 (0.9)
|
||||
;; Initial Release.
|
||||
;;
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile (require 'cl))
|
||||
|
||||
(defgroup highlight-parentheses nil
|
||||
"Highlight surrounding parentheses"
|
||||
:group 'faces
|
||||
:group 'matching)
|
||||
|
||||
(defvar hl-paren-overlays nil
|
||||
"This buffers currently active overlays.")
|
||||
(make-variable-buffer-local 'hl-paren-overlays)
|
||||
|
||||
(defcustom hl-paren-colors
|
||||
'("firebrick1" "IndianRed4" "IndianRed")
|
||||
"*List of colors for the highlighted parentheses.
|
||||
The list starts with the the inside parentheses and moves outwards."
|
||||
:type '(repeat color)
|
||||
:group 'highlight-parentheses)
|
||||
|
||||
(defcustom hl-paren-background-colors nil
|
||||
"*List of colors for the background highlighted parentheses.
|
||||
The list starts with the the inside parentheses and moves outwards."
|
||||
:type '(repeat color)
|
||||
:group 'highlight-parentheses)
|
||||
|
||||
(defface hl-paren-face nil
|
||||
"*Face used for highlighting parentheses.
|
||||
Color attributes might be overriden by `hl-paren-colors' and
|
||||
`hl-paren-background-colors'."
|
||||
:group 'highlight-parentheses)
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defvar hl-paren-last-point 0
|
||||
"The last point for which parentheses were highlighted.
|
||||
This is used to prevent analyzing the same context over and over.")
|
||||
(make-variable-buffer-local 'hl-paren-last-point)
|
||||
|
||||
(defun hl-paren-highlight ()
|
||||
"Highlight the parentheses around point."
|
||||
(unless (= (point) hl-paren-last-point)
|
||||
(save-excursion
|
||||
(let ((pos (point))
|
||||
(match-pos (point))
|
||||
(level -1)
|
||||
(max (1- (length hl-paren-overlays))))
|
||||
(while (and match-pos (< level max))
|
||||
(setq match-pos
|
||||
(when (setq pos (cadr (syntax-ppss pos)))
|
||||
(ignore-errors (scan-sexps pos 1))))
|
||||
(when match-pos
|
||||
(hl-paren-put-overlay (cl-incf level) pos 'hl-paren-face)
|
||||
(hl-paren-put-overlay (cl-incf level) (1- match-pos) 'hl-paren-face)))
|
||||
(while (< level max)
|
||||
(hl-paren-put-overlay (cl-incf level) nil nil))))
|
||||
(setq hl-paren-last-point (point))))
|
||||
|
||||
(defun hl-paren-put-overlay (n pos face)
|
||||
"Move or create the N'th overlay so its shown at POS."
|
||||
(let ((ov (elt hl-paren-overlays n)) end)
|
||||
(if (null pos)
|
||||
(when ov
|
||||
(delete-overlay ov)
|
||||
(aset hl-paren-overlays n nil))
|
||||
(if (atom pos)
|
||||
(setq end (1+ pos))
|
||||
(setq end (cdr pos))
|
||||
(setq pos (car pos)))
|
||||
(if ov
|
||||
(move-overlay ov pos end)
|
||||
(let ((face-attributes (face-attr-construct face))
|
||||
(color-value (nth (/ n 2) hl-paren-colors))
|
||||
(background-value (nth (/ n 2) hl-paren-background-colors)))
|
||||
(when color-value
|
||||
(let ((attribute (memq :foreground face-attributes)))
|
||||
(if attribute
|
||||
(setcar (cdr attribute) color-value)
|
||||
(push color-value face-attributes)
|
||||
(push :foreground face-attributes))))
|
||||
(when background-value
|
||||
(let ((attribute (memq :background face-attributes)))
|
||||
(if attribute
|
||||
(setcar (cdr attribute) background-value)
|
||||
(push background-value face-attributes)
|
||||
(push :background face-attributes))))
|
||||
(setq ov (make-overlay pos end))
|
||||
(aset hl-paren-overlays n ov)
|
||||
(overlay-put ov 'face face-attributes))))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode highlight-parentheses-mode
|
||||
"Minor mode to highlight the surrounding parentheses."
|
||||
:init-value nil
|
||||
:lighter " hl-p"
|
||||
:keymap nil
|
||||
(if highlight-parentheses-mode
|
||||
(progn
|
||||
(setq hl-paren-overlays
|
||||
(make-vector (* 2 (max (length hl-paren-colors)
|
||||
(length hl-paren-background-colors))) nil))
|
||||
(add-hook 'post-command-hook 'hl-paren-highlight nil t))
|
||||
(let (ov)
|
||||
(dotimes (i (length hl-paren-overlays))
|
||||
(when (setq ov (elt hl-paren-overlays i))
|
||||
(delete-overlay ov))))
|
||||
(kill-local-variable 'hl-paren-overlays)
|
||||
(kill-local-variable 'hl-paren-point)
|
||||
(remove-hook 'post-command-hook 'hl-paren-highlight t)))
|
||||
|
||||
(provide 'highlight-parentheses)
|
||||
|
||||
;;; highlight-parentheses.el ends here
|
49
site-lisp/extensions-local/lazy-load.el
Normal file
49
site-lisp/extensions-local/lazy-load.el
Normal file
@ -0,0 +1,49 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun lazy-load-global-keys (key-alist filename &optional key-prefix)
|
||||
(lazy-load-set-keys key-alist nil key-prefix)
|
||||
(dolist (element key-alist)
|
||||
(setq fun (cdr element))
|
||||
(autoload fun filename nil t)))
|
||||
|
||||
(defun lazy-load-local-keys (key-alist keymap filename &optional key-prefix)
|
||||
(lazy-load-set-keys key-alist keymap key-prefix)
|
||||
(dolist (element key-alist)
|
||||
(setq fun (cdr element))
|
||||
(autoload fun filename nil t)))
|
||||
|
||||
(defun lazy-load-set-keys (key-alist &optional keymap key-prefix)
|
||||
"This function is to little type when define key binding.
|
||||
`KEYMAP' is a add keymap for some binding, default is `current-global-map'.
|
||||
`KEY-ALIST' is a alist contain main-key and command.
|
||||
`KEY-PREFIX' is a add prefix for some binding, default is nil."
|
||||
(let (key def)
|
||||
(or keymap (setq keymap (current-global-map)))
|
||||
(if key-prefix
|
||||
(setq key-prefix (concat key-prefix " "))
|
||||
(setq key-prefix ""))
|
||||
(dolist (element key-alist)
|
||||
(setq key (car element))
|
||||
(setq def (cdr element))
|
||||
(cond ((stringp key) (setq key (read-kbd-macro (concat key-prefix key))))
|
||||
((vectorp key) nil)
|
||||
(t (signal 'wrong-type-argument (list 'array key))))
|
||||
(define-key keymap key def))))
|
||||
|
||||
(defun lazy-load-unset-keys (key-list &optional keymap)
|
||||
"This function is to little type when unset key binding.
|
||||
`KEYMAP' is add keymap for some binding, default is `current-global-map'
|
||||
`KEY-LIST' is list contain key."
|
||||
(let (key)
|
||||
(or keymap (setq keymap (current-global-map)))
|
||||
(dolist (key key-list)
|
||||
(cond ((stringp key) (setq key (read-kbd-macro (concat key))))
|
||||
((vectorp key) nil)
|
||||
(t (signal 'wrong-type-argument (list 'array key))))
|
||||
(define-key keymap key nil))))
|
||||
|
||||
(provide 'lazy-load)
|
||||
|
||||
;;; lazy-load.el ends here
|
72
site-lisp/extensions-local/ld-buffer-operations.el
Normal file
72
site-lisp/extensions-local/ld-buffer-operations.el
Normal file
@ -0,0 +1,72 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun ld-indent-buffer ()
|
||||
"Automatic format current buffer."
|
||||
(interactive)
|
||||
(cond
|
||||
((derived-mode-p 'python-mode)
|
||||
(message "Don't indent python buffer. It will mess up the code syntax."))
|
||||
((derived-mode-p 'yaml-mode)
|
||||
(message "Don't indent yaml buffer. It will mess up the code syntax."))
|
||||
(t
|
||||
(save-excursion
|
||||
(indent-region (point-min) (point-max) nil)
|
||||
(delete-trailing-whitespace)
|
||||
(untabify (point-min) (point-max))))))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-rename-file-and-buffer ()
|
||||
"Rename current buffer and if the buffer is visiting a file, rename it too."
|
||||
(interactive)
|
||||
(let ((filename (buffer-file-name)))
|
||||
(if (not (and filename (file-exists-p filename)))
|
||||
(rename-buffer (read-from-minibuffer "New name: " (buffer-name)))
|
||||
(let* ((new-name (read-file-name "New name: " (file-name-directory filename)))
|
||||
(containing-dir (file-name-directory new-name)))
|
||||
(make-directory containing-dir t)
|
||||
(cond
|
||||
((vc-backend filename) (vc-rename-file filename new-name))
|
||||
(t
|
||||
(rename-file filename new-name t)
|
||||
(set-visited-file-name new-name t t)))))))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-delete-file-and-buffer ()
|
||||
"Kill the current buffer and deletes the file it is visiting."
|
||||
(interactive)
|
||||
(let ((filename (buffer-file-name)))
|
||||
(when filename
|
||||
(if (vc-backend filename)
|
||||
(vc-delete-file filename)
|
||||
(when (y-or-n-p (format "Sure to delete %s? " filename))
|
||||
(delete-file filename delete-by-moving-to-trash)
|
||||
(message "Deleted file %s" filename)
|
||||
(kill-buffer))))))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-revert-buffer-no-confirm ()
|
||||
"Revert buffer without confirmation."
|
||||
(interactive)
|
||||
(revert-buffer :ignore-auto :noconfirm))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-unmark-all-buffers ()
|
||||
"Unmark all have marked buffers."
|
||||
(interactive)
|
||||
(let ((current-element (current-buffer)))
|
||||
(save-excursion
|
||||
(dolist (element (buffer-list))
|
||||
(set-buffer element)
|
||||
(deactivate-mark)))
|
||||
(switch-to-buffer current-element)
|
||||
(deactivate-mark)))
|
||||
|
||||
(provide 'ld-buffer-operations)
|
||||
|
||||
;;; ld-buffer-operations.el ends here
|
38
site-lisp/extensions-local/ld-delete-block.el
Normal file
38
site-lisp/extensions-local/ld-delete-block.el
Normal file
@ -0,0 +1,38 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'subword)
|
||||
|
||||
;;; Code:
|
||||
(defun ld-delete-one-block-forward ()
|
||||
(interactive)
|
||||
(if (eobp)
|
||||
(message "End of buffer")
|
||||
(let* ((syntax-move-point
|
||||
(save-excursion
|
||||
(skip-syntax-forward (string (char-syntax (char-after))))
|
||||
(point)
|
||||
))
|
||||
(subword-move-point
|
||||
(save-excursion
|
||||
(subword-forward)
|
||||
(point))))
|
||||
(kill-region (point) (min syntax-move-point subword-move-point)))))
|
||||
|
||||
(defun ld-delete-one-block-backward ()
|
||||
(interactive)
|
||||
(if (bobp)
|
||||
(message "Beginning of buffer")
|
||||
(let* ((syntax-move-point
|
||||
(save-excursion
|
||||
(skip-syntax-backward (string (char-syntax (char-before))))
|
||||
(point)
|
||||
))
|
||||
(subword-move-point
|
||||
(save-excursion
|
||||
(subword-backward)
|
||||
(point))))
|
||||
(kill-region (point) (max syntax-move-point subword-move-point)))))
|
||||
|
||||
(provide 'ld-delete-block)
|
||||
|
||||
;;; ld-delete-block.el ends here
|
14
site-lisp/extensions-local/ld-file-operations.el
Normal file
14
site-lisp/extensions-local/ld-file-operations.el
Normal file
@ -0,0 +1,14 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun ld-find-file-in-root (file)
|
||||
"Find file with root."
|
||||
(interactive "fFind file as sudo: ")
|
||||
(require 'tramp)
|
||||
(tramp-cleanup-all-connections)
|
||||
(find-file (concat "/sudo:root@localhost:" file)))
|
||||
|
||||
(provide 'ld-file-operations)
|
||||
|
||||
;;; ld-file-operations.el ends here
|
39
site-lisp/extensions-local/ld-goto-cursor-stack.el
Normal file
39
site-lisp/extensions-local/ld-goto-cursor-stack.el
Normal file
@ -0,0 +1,39 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defvar ld-cursor-position-stack nil
|
||||
"Cursor position stack.")
|
||||
|
||||
(defun ld-cursor-position-1-store ()
|
||||
"Remember current position and setup."
|
||||
(interactive)
|
||||
(point-to-register 8)
|
||||
(message "Have remember one position"))
|
||||
|
||||
(defun ld-cursor-position-1-jump ()
|
||||
"Jump to latest position and setup."
|
||||
(interactive)
|
||||
(let ((tmp (point-marker)))
|
||||
(jump-to-register 8)
|
||||
(set-register 8 tmp))
|
||||
(message "Have back to remember position"))
|
||||
|
||||
(defun ld-cursor-position-stack-push ()
|
||||
"Push current point in stack."
|
||||
(interactive)
|
||||
(message "Location marked.")
|
||||
(setq ld-cursor-position-stack (cons (list (current-buffer) (point)) ld-cursor-position-stack)))
|
||||
|
||||
(defun ld-cursor-position-stack-pop ()
|
||||
"Pop point from stack."
|
||||
(interactive)
|
||||
(if (null ld-cursor-position-stack)
|
||||
(message "Stack is empty.")
|
||||
(switch-to-buffer (caar ld-cursor-position-stack))
|
||||
(goto-char (cadar ld-cursor-position-stack))
|
||||
(setq ld-cursor-position-stack (cdr ld-cursor-position-stack))))
|
||||
|
||||
(provide 'ld-goto-cursor-stack)
|
||||
|
||||
;;; ld-goto-cursor-stack.el ends here
|
30
site-lisp/extensions-local/ld-goto-simple.el
Normal file
30
site-lisp/extensions-local/ld-goto-simple.el
Normal file
@ -0,0 +1,30 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun ld-goto-column (number)
|
||||
"Untabify, and go to a column NUMBER within the current line (0 is beginning of the line)."
|
||||
(interactive "nColumn number: ")
|
||||
(move-to-column number t))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-goto-percent-text (percent)
|
||||
"Move the cursor to the character,
|
||||
which is <percent>% far from the top character."
|
||||
(interactive "n(text) Goto percent: ")
|
||||
(goto-char (/ (* percent (point-max)) 100)))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-goto-percent-line (percent)
|
||||
"Move the cursor to the line,
|
||||
which is <percent>% far from the top line."
|
||||
(interactive "n(line) Goto percent: ")
|
||||
(goto-line (/ (* percent (count-lines (point-min) (point-max)))
|
||||
100)))
|
||||
|
||||
(provide 'ld-goto-simple)
|
||||
|
||||
;;; ld-goto-simple.el ends here
|
||||
|
106
site-lisp/extensions-local/ld-org-publish-project-desc.el
Normal file
106
site-lisp/extensions-local/ld-org-publish-project-desc.el
Normal file
@ -0,0 +1,106 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(setq
|
||||
org-publish-project-alist
|
||||
(let* ((ld-site-path "~/Documents/ld_org_article/")
|
||||
(ld-site-pub-path "~/Public/ld_org_article_publish/")
|
||||
(get-content (lambda (x)
|
||||
(with-temp-buffer
|
||||
(insert-file-contents (concat ld-site-path x))
|
||||
(buffer-string))))
|
||||
(ld-site-postamble (funcall get-content "template/postamble.html"))
|
||||
(ld-site-preamble (funcall get-content "template/preamble.html"))
|
||||
(ld-site-head (funcall get-content "template/head.html")))
|
||||
`(
|
||||
("blog"
|
||||
:base-directory ,(concat ld-site-path "article/blog/")
|
||||
:base-extension "org"
|
||||
:publishing-directory ,(concat ld-site-pub-path "article/blog/")
|
||||
:publishing-function org-html-publish-to-html
|
||||
:recursive t
|
||||
:headline-levels 4
|
||||
|
||||
:auto-sitemap t
|
||||
:sitemap-filename "sitemap-index.org"
|
||||
:sitemap-title "blog"
|
||||
|
||||
:html-doctype "html5"
|
||||
:html-head ,ld-site-head
|
||||
:html-preamble ,ld-site-preamble
|
||||
:html-postamble ,ld-site-postamble
|
||||
;; :htmlized-source t
|
||||
|
||||
:with-toc t
|
||||
)
|
||||
("wiki"
|
||||
:base-directory ,(concat ld-site-path "article/wiki/")
|
||||
:base-extension "org"
|
||||
:publishing-directory ,(concat ld-site-pub-path "article/wiki/")
|
||||
:publishing-function org-html-publish-to-html
|
||||
:recursive t
|
||||
:headline-levels 4
|
||||
|
||||
:auto-sitemap t
|
||||
:sitemap-filename "sitemap-index.org"
|
||||
:sitemap-title "wiki"
|
||||
|
||||
:html-doctype "html5"
|
||||
:html-head ,ld-site-head
|
||||
:html-preamble ,ld-site-preamble
|
||||
:html-postamble ,ld-site-postamble
|
||||
;; :htmlized-source t
|
||||
|
||||
:with-toc t
|
||||
)
|
||||
("translation"
|
||||
:base-directory ,(concat ld-site-path "article/translation/")
|
||||
:base-extension "org"
|
||||
:publishing-directory ,(concat ld-site-pub-path "article/translation/")
|
||||
:publishing-function org-html-publish-to-html
|
||||
:recursive t
|
||||
:headline-levels 4
|
||||
|
||||
:auto-sitemap t
|
||||
:sitemap-filename "sitemap-index.org"
|
||||
:sitemap-title "translation"
|
||||
|
||||
:html-doctype "html5"
|
||||
:html-head ,ld-site-head
|
||||
:html-preamble ,ld-site-preamble
|
||||
:html-postamble ,ld-site-postamble
|
||||
;; :htmlized-source t
|
||||
|
||||
:with-toc t
|
||||
)
|
||||
("site"
|
||||
:base-directory ,(concat ld-site-path "article/site/")
|
||||
:base-extension "org"
|
||||
:publishing-directory ,(concat ld-site-pub-path "article/site/")
|
||||
:publishing-function org-html-publish-to-html
|
||||
:recursive t
|
||||
:headline-levels 4
|
||||
|
||||
:html-doctype "html5"
|
||||
:html-head ,ld-site-head
|
||||
:html-preamble ,ld-site-preamble
|
||||
:html-postamble ,ld-site-postamble
|
||||
;; :htmlized-source t
|
||||
|
||||
:with-toc nil
|
||||
)
|
||||
("static"
|
||||
:base-directory ,(concat ld-site-path "article_static/")
|
||||
;; :base-extension "css\\|js\\|ico\\|png\\|jpg\\|gif\\|zip\\|7z\\|rar\\|pdf"
|
||||
:base-extension ".*"
|
||||
:publishing-directory ,(concat ld-site-pub-path "/article_static")
|
||||
:publishing-function org-publish-attachment
|
||||
:recursive t
|
||||
)
|
||||
("all" :components ("blog" "wiki" "site" "translation" "static"))
|
||||
)))
|
||||
|
||||
(provide 'ld-org-publish-project-desc)
|
||||
|
||||
;;; ld-org-publish-project-desc.el ends here
|
109
site-lisp/extensions-local/ld-text-operations.el
Normal file
109
site-lisp/extensions-local/ld-text-operations.el
Normal file
@ -0,0 +1,109 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
; --- move lines
|
||||
(defun ld-move-text-internal (arg)
|
||||
(cond
|
||||
((and mark-active transient-mark-mode)
|
||||
(if (> (point) (mark))
|
||||
(exchange-point-and-mark))
|
||||
(let ((column (current-column))
|
||||
(text (delete-and-extract-region (point) (mark))))
|
||||
(forward-line arg)
|
||||
(move-to-column column t)
|
||||
(set-mark (point))
|
||||
(insert text)
|
||||
(exchange-point-and-mark)
|
||||
(setq deactivate-mark nil)))
|
||||
(t
|
||||
(beginning-of-line)
|
||||
(when (or (> arg 0) (not (bobp)))
|
||||
(forward-line)
|
||||
(when (or (< arg 0) (not (eobp)))
|
||||
(transpose-lines arg))
|
||||
(forward-line -1)))))
|
||||
|
||||
(defun ld-move-text-down (arg)
|
||||
"Move region (transient-mark-mode active) or current line
|
||||
arg lines down."
|
||||
(interactive "*p")
|
||||
(ld-move-text-internal arg))
|
||||
|
||||
(defun ld-move-text-up (arg)
|
||||
"Move region (transient-mark-mode active) or current line
|
||||
arg lines up."
|
||||
(interactive "*p")
|
||||
(ld-move-text-internal (- arg)))
|
||||
|
||||
; --- duplicate line
|
||||
(defun ld-get-positions-of-line-or-region ()
|
||||
"Return positions (beg . end) of the current line or region."
|
||||
(let (beg end)
|
||||
(if (and mark-active (> (point) (mark)))
|
||||
(exchange-point-and-mark))
|
||||
(setq beg (line-beginning-position))
|
||||
(if mark-active
|
||||
(exchange-point-and-mark))
|
||||
(setq end (line-end-position))
|
||||
(cons beg end)))
|
||||
|
||||
(defun ld-duplicate-current-line-or-region (arg)
|
||||
"Duplicates the current line or region ARG times.
|
||||
If there's no region, the current line will be duplicated. However, if
|
||||
there's a region, all lines that region covers will be duplicated."
|
||||
(interactive "p")
|
||||
(pcase-let* ((origin (point))
|
||||
(`(,beg . ,end) (ld-get-positions-of-line-or-region))
|
||||
(region (buffer-substring-no-properties beg end)))
|
||||
(dotimes (_i arg)
|
||||
(goto-char end)
|
||||
(unless (use-region-p)
|
||||
(newline))
|
||||
(insert region)
|
||||
(setq end (point)))
|
||||
(goto-char (+ origin (* (length region) arg) arg))))
|
||||
|
||||
(defun ld-duplicate-and-comment-current-line-or-region (arg)
|
||||
"Duplicates and comments the current line or region ARG times.
|
||||
If there's no region, the current line will be duplicated. However, if
|
||||
there's a region, all lines that region covers will be duplicated."
|
||||
(interactive "p")
|
||||
(pcase-let* ((origin (point))
|
||||
(`(,beg . ,end) (ld-get-positions-of-line-or-region))
|
||||
(region (buffer-substring-no-properties beg end)))
|
||||
(comment-or-uncomment-region beg end)
|
||||
(setq end (line-end-position))
|
||||
(dotimes (_ arg)
|
||||
(goto-char end)
|
||||
(unless (use-region-p)
|
||||
(newline))
|
||||
(insert region)
|
||||
(setq end (point)))
|
||||
(goto-char (+ origin (* (length region) arg) arg))))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-delete-current-line ()
|
||||
"Delete (not kill) the current line."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(delete-region
|
||||
(progn (forward-visible-line 0) (point))
|
||||
(progn (forward-visible-line 1) (point)))))
|
||||
|
||||
; ---
|
||||
|
||||
(defun ld-mark-line ()
|
||||
"Mark one whole line, similar to `mark-paragraph'."
|
||||
(interactive)
|
||||
(beginning-of-line)
|
||||
(if mark-active
|
||||
(exchange-point-and-mark)
|
||||
(push-mark nil nil t))
|
||||
(forward-line)
|
||||
(exchange-point-and-mark))
|
||||
|
||||
(provide 'ld-text-operations)
|
||||
|
||||
;;; ld-text-operations.el ends here
|
22
site-lisp/extensions-local/ld-toggle-one-window.el
Normal file
22
site-lisp/extensions-local/ld-toggle-one-window.el
Normal file
@ -0,0 +1,22 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defvar ld-toggle-one-window-config-of-window nil
|
||||
"The window configuration used for `toggle-one-window'.")
|
||||
|
||||
(defun ld-toggle-one-window ()
|
||||
"Toggle between window layout and one window."
|
||||
(interactive)
|
||||
(if (equal (length (cl-remove-if #'window-dedicated-p (window-list))) 1)
|
||||
(if toggle-one-window-config-of-window
|
||||
(progn
|
||||
(set-window-configuration toggle-one-window-config-of-window)
|
||||
(setq toggle-one-window-config-of-window nil))
|
||||
(message "No other windows exist."))
|
||||
(setq toggle-one-window-config-of-window (current-window-configuration))
|
||||
(delete-other-windows)))
|
||||
|
||||
(provide 'ld-toggle-one-window)
|
||||
|
||||
;;; ld-toggle-one-window.el ends here
|
167
site-lisp/extensions-local/ld-tools.el
Normal file
167
site-lisp/extensions-local/ld-tools.el
Normal file
@ -0,0 +1,167 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(defun insert-line-number (beg end &optional start-line)
|
||||
"Insert line numbers into buffer."
|
||||
(interactive "r")
|
||||
(save-excursion
|
||||
(let ((max (count-lines beg end))
|
||||
(line (or start-line 1))
|
||||
(counter 1))
|
||||
(goto-char beg)
|
||||
(while (<= counter max)
|
||||
(insert (format "%0d " line))
|
||||
(beginning-of-line 2)
|
||||
(cl-incf line)
|
||||
(cl-incf counter)))))
|
||||
|
||||
(defun insert-line-number+ ()
|
||||
"Insert line number into buffer."
|
||||
(interactive)
|
||||
(if mark-active
|
||||
(insert-line-number (region-beginning) (region-end) (read-number "Start line: "))
|
||||
(insert-line-number (point-min) (point-max))))
|
||||
|
||||
(defun strip-blank-lines()
|
||||
"Strip all blank lines in select area of buffer,
|
||||
if not select any area, then strip all blank lines of buffer."
|
||||
(interactive)
|
||||
(strip-regular-expression-string "^[ \t]*\n")
|
||||
(message "Blanks line striped. ^_^"))
|
||||
|
||||
(defun strip-line-number()
|
||||
"Strip all line number in select area of buffer,
|
||||
if not select any area, then strip all line number of buffer."
|
||||
(interactive)
|
||||
(strip-regular-expression-string "^[0-9]+ ")
|
||||
(message "Line number striped. ^_^"))
|
||||
|
||||
(defun strip-regular-expression-string (regular-expression)
|
||||
"Strip all string that match REGULAR-EXPRESSION in select area of buffer.
|
||||
If not select any area, then strip current buffer"
|
||||
(interactive)
|
||||
(let ((begin (point-min))
|
||||
(end (point-max)))
|
||||
(if mark-active
|
||||
(setq begin (region-beginning)
|
||||
end (region-end)))
|
||||
(save-excursion
|
||||
(goto-char end)
|
||||
(while (and (> (point) begin)
|
||||
(re-search-backward regular-expression nil t))
|
||||
(replace-match "" t t)))))
|
||||
|
||||
(defun indent-comment-buffer ()
|
||||
"Indent comment of buffer."
|
||||
(interactive)
|
||||
(indent-comment-region (point-min) (point-max)))
|
||||
|
||||
(defun indent-comment-region (start end)
|
||||
"Indent region."
|
||||
(interactive "r")
|
||||
(save-excursion
|
||||
(setq end (copy-marker end))
|
||||
(goto-char start)
|
||||
(while (< (point) end)
|
||||
(if (comment-search-forward end t)
|
||||
(comment-indent)
|
||||
(goto-char end)))))
|
||||
|
||||
(defun capitalize-one-char (arg)
|
||||
"Change the letter pointed by the cursor to uppercase."
|
||||
(interactive "P")
|
||||
(upcase-region (point) (+ (point) (or arg 1)))
|
||||
(forward-char (or arg 1)))
|
||||
|
||||
(defun lowercase-one-char (arg)
|
||||
"Change the letter pointed by the cursor to lowercase."
|
||||
(interactive "P")
|
||||
(downcase-region (point) (+ (point) (or arg 1)))
|
||||
(forward-char (or arg 1)))
|
||||
|
||||
(defun delete-chars-hungry-forward (&optional reverse)
|
||||
"Delete chars forward use `hungry' style.
|
||||
Optional argument REVERSE default is delete forward, if reverse is non-nil delete backward."
|
||||
(delete-region
|
||||
(point)
|
||||
(progn
|
||||
(if reverse
|
||||
(skip-chars-backward " \t\n\r")
|
||||
(skip-chars-forward " \t\n\r"))
|
||||
(point))))
|
||||
|
||||
(defun delete-chars-hungry-backward ()
|
||||
"Delete chars backward use `hungry' style."
|
||||
(delete-chars-hungry-forward t))
|
||||
|
||||
(defun reverse-chars-in-region (start end)
|
||||
"Reverse the region character by character without reversing lines."
|
||||
(interactive "r")
|
||||
(let ((str (buffer-substring start end)))
|
||||
(delete-region start end)
|
||||
(dolist (line (split-string str "\n"))
|
||||
(let ((chars (mapcar (lambda (c)
|
||||
(or (matching-paren c)
|
||||
c))
|
||||
(reverse (append line nil)))))
|
||||
(when chars
|
||||
(apply 'insert chars))
|
||||
(newline)))))
|
||||
|
||||
(defun underline-line-with (char)
|
||||
"Insert some char below at current line."
|
||||
(interactive "cType one char: ")
|
||||
(save-excursion
|
||||
(let ((length (- (point-at-eol) (point-at-bol))))
|
||||
(end-of-line)
|
||||
(insert "\n")
|
||||
(insert (make-string length char)))))
|
||||
|
||||
(defun prettyfy-string (string &optional after)
|
||||
"Strip starting and ending whitespace and pretty `STRING'.
|
||||
Replace any chars after AFTER with '...'.
|
||||
Argument STRING the string that need pretty."
|
||||
(let ((replace-map (list
|
||||
(cons "^[ \t]*" "")
|
||||
(cons "[ \t]*$" "")
|
||||
(cons (concat "^\\(.\\{"
|
||||
(or (number-to-string after) "10")
|
||||
"\\}\\).*")
|
||||
"\\1..."))))
|
||||
(dolist (replace replace-map)
|
||||
(when (string-match (car replace) string)
|
||||
(setq string (replace-match (cdr replace) nil nil string))))
|
||||
string))
|
||||
|
||||
(defun forward-button-with-line-begin ()
|
||||
"Move to next button with line begin."
|
||||
(interactive)
|
||||
(call-interactively 'forward-button)
|
||||
(while (not (bolp))
|
||||
(call-interactively 'forward-button)))
|
||||
|
||||
(defun backward-button-with-line-begin ()
|
||||
"Move to previous button with line begin."
|
||||
(interactive)
|
||||
(call-interactively 'backward-button)
|
||||
(while (not (bolp))
|
||||
(call-interactively 'backward-button)))
|
||||
|
||||
(defun only-comment-p ()
|
||||
"Return t if current line only contains comment. Otherwise return nil."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(if (search-forward comment-start (line-end-position) t)
|
||||
(progn
|
||||
(backward-char (length comment-start))
|
||||
(equal (point)
|
||||
(progn
|
||||
(back-to-indentation)
|
||||
(point))))
|
||||
nil)))
|
||||
|
||||
(provide 'ld-tools)
|
||||
|
||||
;;; ld-tools.el ends here
|
2228
site-lisp/extensions-local/neotree.el
Normal file
2228
site-lisp/extensions-local/neotree.el
Normal file
File diff suppressed because it is too large
Load Diff
42
site-lisp/extensions-local/scroll-next-window.el
Normal file
42
site-lisp/extensions-local/scroll-next-window.el
Normal file
@ -0,0 +1,42 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
;'up' to see previous content
|
||||
;'down' to see further content
|
||||
(defun scroll-next-window-up ()
|
||||
(interactive)
|
||||
(scroll-next-window-internal "up"))
|
||||
|
||||
(defun scroll-next-window-down ()
|
||||
(interactive)
|
||||
(scroll-next-window-internal "down"))
|
||||
|
||||
(defun scroll-next-window-up-line ()
|
||||
(interactive)
|
||||
(scroll-next-window-internal "up" 1))
|
||||
|
||||
(defun scroll-next-window-down-line ()
|
||||
(interactive)
|
||||
(scroll-next-window-internal "down" 1))
|
||||
|
||||
(defun scroll-next-window-internal (direction &optional line)
|
||||
(save-excursion
|
||||
;; Switch to next window.
|
||||
(other-window 1)
|
||||
;; Do scroll operation.
|
||||
(ignore-errors
|
||||
(if (string-equal direction "up")
|
||||
(if line
|
||||
(scroll-up line)
|
||||
(scroll-up))
|
||||
(if line
|
||||
(scroll-down line)
|
||||
(scroll-down))))
|
||||
;; Switch back to current window.
|
||||
(other-window -1)
|
||||
))
|
||||
|
||||
(provide 'scroll-next-window)
|
||||
|
||||
;;; scroll-next-window.el ends here
|
4653
site-lisp/extensions-local/undo-tree.el
Normal file
4653
site-lisp/extensions-local/undo-tree.el
Normal file
File diff suppressed because it is too large
Load Diff
1
site-lisp/extensions-submodule/ace-window
Submodule
1
site-lisp/extensions-submodule/ace-window
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 77115afc1b0b9f633084cf7479c767988106c196
|
1
site-lisp/extensions-submodule/avy
Submodule
1
site-lisp/extensions-submodule/avy
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit be612110cb116a38b8603df367942e2bb3d9bdbe
|
1
site-lisp/extensions-submodule/citre
Submodule
1
site-lisp/extensions-submodule/citre
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit c617acef3dc2a88aaffa42a515ce7dbaba98228a
|
1
site-lisp/extensions-submodule/company-mode
Submodule
1
site-lisp/extensions-submodule/company-mode
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 9c12b02620ed8a7ae5369fc90217f1c730e48fa6
|
1
site-lisp/extensions-submodule/dash.el
Submodule
1
site-lisp/extensions-submodule/dash.el
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 6db80c711ce947f6c6fa11e5c2257fff2c79d139
|
1
site-lisp/extensions-submodule/emacs-which-key
Submodule
1
site-lisp/extensions-submodule/emacs-which-key
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 4d20bc852545a2e602f59084a630f888542052b1
|
1
site-lisp/extensions-submodule/go-mode.el
Submodule
1
site-lisp/extensions-submodule/go-mode.el
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8dce1e3ba1cdc34a856ad53c8421413cfe33660e
|
1
site-lisp/extensions-submodule/jsonian
Submodule
1
site-lisp/extensions-submodule/jsonian
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 22bd5e20a653595b901ccfdc8780a0038755984d
|
1
site-lisp/extensions-submodule/lua-mode
Submodule
1
site-lisp/extensions-submodule/lua-mode
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d074e4134b1beae9ed4c9b512af741ca0d852ba3
|
1
site-lisp/extensions-submodule/markdown-mode
Submodule
1
site-lisp/extensions-submodule/markdown-mode
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 141f9a05d121f60fe5e411c0ad114e3d3216c9ad
|
1
site-lisp/extensions-submodule/modus-themes
Submodule
1
site-lisp/extensions-submodule/modus-themes
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 642cc5f8358fd1f2911792a4bbed160d24e9b01b
|
@ -0,0 +1 @@
|
||||
Subproject commit 234806c832994cadedb42596fe235e91bbd59e8c
|
1
site-lisp/extensions-submodule/swiper
Submodule
1
site-lisp/extensions-submodule/swiper
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 8c30f4cab5948aa8d942a3b2bbf5fb6a94d9441d
|
1
site-lisp/extensions-submodule/web-mode
Submodule
1
site-lisp/extensions-submodule/web-mode
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit df57cd0beea9c6bdc64259bd11bde0c076a64cc9
|
1
site-lisp/extensions-submodule/yasnippet
Submodule
1
site-lisp/extensions-submodule/yasnippet
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 52a1c5031912243c791c55e0fe345d04f219b507
|
10
site-lisp/init-config/init-ace-window.el
Normal file
10
site-lisp/init-config/init-ace-window.el
Normal file
@ -0,0 +1,10 @@
|
||||
;;; Require
|
||||
(require 'ace-window)
|
||||
|
||||
;;; Code:
|
||||
;; 0-9 by default
|
||||
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
|
||||
|
||||
(provide 'init-ace-window)
|
||||
|
||||
;;; init-ace-window.el ends here
|
14
site-lisp/init-config/init-auto-save.el
Normal file
14
site-lisp/init-config/init-auto-save.el
Normal file
@ -0,0 +1,14 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'auto-save)
|
||||
|
||||
;;; Code:
|
||||
;; auto save after n second(s)
|
||||
;; (setq auto-save-idle 1)
|
||||
(setq auto-save-delete-trailing-whitespace t)
|
||||
(setq auto-save-silent t)
|
||||
(auto-save-enable)
|
||||
|
||||
(provide 'init-auto-save)
|
||||
|
||||
;;; init-auto-save.el ends here
|
19
site-lisp/init-config/init-avy.el
Normal file
19
site-lisp/init-config/init-avy.el
Normal file
@ -0,0 +1,19 @@
|
||||
;;; Require
|
||||
(require 'avy)
|
||||
|
||||
;;; Code:
|
||||
;; Home row only (the default).
|
||||
(setq avy-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
|
||||
|
||||
;; Any lower-case letter a-z.
|
||||
; (setq avy-keys (number-sequence ?a ?z))
|
||||
|
||||
;; Any lower-case letter or number. Numbers are specified in the keyboard
|
||||
;; number-row order, so that the candidate following '9' will be '0'.
|
||||
; (setq avy-keys (nconc (number-sequence ?a ?z)
|
||||
; (number-sequence ?1 ?9)
|
||||
; '(?0)))
|
||||
|
||||
(provide 'init-avy)
|
||||
|
||||
;;; init-avy.el ends here
|
10
site-lisp/init-config/init-citre.el
Normal file
10
site-lisp/init-config/init-citre.el
Normal file
@ -0,0 +1,10 @@
|
||||
;;; Require
|
||||
(require 'citre)
|
||||
(require 'citre-config)
|
||||
|
||||
;;; Code:
|
||||
;; (remove-hook 'find-file-hook #'citre-auto-enable-citre-mode)
|
||||
|
||||
(provide 'init-citre)
|
||||
|
||||
;;; init-citre.el ends here
|
34
site-lisp/init-config/init-coding-system.el
Normal file
34
site-lisp/init-config/init-coding-system.el
Normal file
@ -0,0 +1,34 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(set-language-environment 'UTF-8)
|
||||
|
||||
(set-default-coding-systems 'utf-8)
|
||||
(set-buffer-file-coding-system 'utf-8)
|
||||
(set-file-name-coding-system 'utf-8)
|
||||
(set-keyboard-coding-system 'utf-8)
|
||||
(set-next-selection-coding-system 'utf-8)
|
||||
(set-terminal-coding-system 'utf-8)
|
||||
|
||||
(when *win64*
|
||||
(set-next-selection-coding-system 'utf-16-le)
|
||||
(set-selection-coding-system 'utf-16-le)
|
||||
(set-clipboard-coding-system 'utf-16-le))
|
||||
|
||||
(when (or *linux* *unix* *is-a-mac*)
|
||||
(set-clipboard-coding-system 'utf-8)
|
||||
(set-selection-coding-system 'utf-8))
|
||||
|
||||
;; the final one will be selected first
|
||||
(prefer-coding-system 'cp950)
|
||||
(prefer-coding-system 'gb2312)
|
||||
(prefer-coding-system 'cp936)
|
||||
(prefer-coding-system 'gb18030)
|
||||
(prefer-coding-system 'utf-16)
|
||||
(prefer-coding-system 'utf-8-dos)
|
||||
(prefer-coding-system 'utf-8-unix)
|
||||
|
||||
(provide 'init-coding-system)
|
||||
|
||||
;;; init-coding-system ends here
|
13
site-lisp/init-config/init-company-mode.el
Normal file
13
site-lisp/init-config/init-company-mode.el
Normal file
@ -0,0 +1,13 @@
|
||||
;;; Require
|
||||
(require 'company)
|
||||
(require 'company-ctags)
|
||||
|
||||
;;; Code:
|
||||
(global-company-mode)
|
||||
|
||||
(with-eval-after-load 'company
|
||||
(company-ctags-auto-setup))
|
||||
|
||||
(provide 'init-company-mode)
|
||||
|
||||
;;; init-company-mode.el ends here
|
23
site-lisp/init-config/init-dired.el
Normal file
23
site-lisp/init-config/init-dired.el
Normal file
@ -0,0 +1,23 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'dired-display-buffer)
|
||||
(require 'dired-narrow)
|
||||
(require 'dired-subtree)
|
||||
|
||||
;;; Code:
|
||||
(setq dired-listing-switches "-alh1v --group-directories-first")
|
||||
|
||||
;; dired-subtree
|
||||
(setq dired-subtree-line-prefix " ")
|
||||
(setq dired-subtree-cycle-depth 3) ;; default `3'
|
||||
(setq dired-subtree-use-backgrounds nil) ;; default `t'
|
||||
;; (set-face-attribute 'dired-subtree-depth-1-face nil :background "#ced9db")
|
||||
;; (set-face-attribute 'dired-subtree-depth-2-face nil :background "#bbc9cc")
|
||||
;; (set-face-attribute 'dired-subtree-depth-3-face nil :background "#a7babe")
|
||||
;; (set-face-attribute 'dired-subtree-depth-4-face nil :background "#94aaaf")
|
||||
;; (set-face-attribute 'dired-subtree-depth-5-face nil :background "#809ba2")
|
||||
;; (set-face-attribute 'dired-subtree-depth-6-face nil :background "#6c8b93")
|
||||
|
||||
(provide 'init-dired)
|
||||
|
||||
;;; init-dired.el ends here
|
149
site-lisp/init-config/init-generic.el
Normal file
149
site-lisp/init-config/init-generic.el
Normal file
@ -0,0 +1,149 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(setq package-archives
|
||||
'(("gnu" . "http://elpa.emacs-china.org/gnu/")
|
||||
("melpa" . "http://elpa.emacs-china.org/melpa/")))
|
||||
|
||||
;; disable some bars
|
||||
(if window-system
|
||||
(progn
|
||||
(tool-bar-mode -1)
|
||||
(menu-bar-mode -1)
|
||||
(scroll-bar-mode -1))
|
||||
(menu-bar-mode -1))
|
||||
|
||||
;; map Win key and Hyper key to Super and Hyper for emacs on Windows.
|
||||
(when *win64*
|
||||
(setq w32-pass-lwindow-to-system nil)
|
||||
(setq w32-lwindow-modifier 'super) ; Left Windows key
|
||||
(setq w32-pass-rwindow-to-system nil)
|
||||
(setq w32-rwindow-modifier 'super) ; Right Windows key
|
||||
(w32-register-hot-key [s-])
|
||||
;; (setq w32-pass-apps-to-system nil)
|
||||
(setq w32-apps-modifier 'hyper) ; Menu/App key
|
||||
(w32-register-hot-key [H-]))
|
||||
|
||||
;; Restore emacs session.
|
||||
;(setq initial-buffer-choice t)
|
||||
;(run-with-timer 1 nil #'(lambda () (bury-buffer)))
|
||||
|
||||
;; turn on word-wrap in all buffers
|
||||
(global-visual-line-mode t)
|
||||
(setq word-wrap-by-category t) ;; enhanced CJK word wrap since Emacs28
|
||||
|
||||
;; line number and column number
|
||||
(global-display-line-numbers-mode t) ;; show line numbers in every mode
|
||||
(column-number-mode t) ;; show column number
|
||||
; Line numbers are not displayed when large files are used.
|
||||
(setq line-number-display-limit large-file-warning-threshold)
|
||||
(setq line-number-display-limit-width 1000)
|
||||
|
||||
;; parentheses config
|
||||
(show-paren-mode t) ;; show bracket pairing
|
||||
(electric-pair-mode t) ;; automatic completion of parentheses
|
||||
|
||||
;; highlight current line
|
||||
(global-hl-line-mode t)
|
||||
|
||||
;; auto reload file content
|
||||
(global-auto-revert-mode t)
|
||||
|
||||
;; delete selected text when input on it
|
||||
(delete-selection-mode t)
|
||||
|
||||
;; record recently opened files
|
||||
(recentf-mode 1)
|
||||
(setq recentf-max-menu-items 25)
|
||||
(setq recentf-max-saved-items 25)
|
||||
|
||||
;; treat OneWord or one_word as one word
|
||||
(global-subword-mode t)
|
||||
|
||||
;; disable cursor blink
|
||||
(blink-cursor-mode -1)
|
||||
|
||||
;; decompress a file when open it
|
||||
(auto-compression-mode t)
|
||||
|
||||
;; disable the ring bell
|
||||
(setq ring-bell-function 'ignore)
|
||||
|
||||
;; set `text-mode' as default major-mode
|
||||
(setq default-major-mode 'text-mode)
|
||||
|
||||
;; use Posix format for time string
|
||||
(setq system-time-locale "C")
|
||||
|
||||
;; replace yes/no with y/n
|
||||
;; but since emacs 28 user can use (use-short-answers t) to do it
|
||||
(fset 'yes-or-no-p 'y-or-n-p)
|
||||
|
||||
;; do not show welcome page
|
||||
(setq inhibit-startup-screen t)
|
||||
|
||||
;; use single space as sentence end, default is two
|
||||
(setq sentence-end-double-space nil)
|
||||
|
||||
;; make key prompt faster
|
||||
(setq echo-keystrokes 0.1)
|
||||
|
||||
;; increase IO performance
|
||||
(setq process-adaptive-read-buffering nil)
|
||||
(setq read-process-output-max (* 1024 1024))
|
||||
|
||||
;; scrolling config
|
||||
(setq scroll-margin 3
|
||||
scroll-conservatively 101
|
||||
auto-window-vscroll nil)
|
||||
|
||||
;; clean scratch buffer content
|
||||
; a non-clean scratch buffer will disturb session restore
|
||||
(setq initial-scratch-message "")
|
||||
|
||||
;; exit emacs without confirmation to kill running processes
|
||||
(setq confirm-kill-processes nil)
|
||||
|
||||
;; resize frame in pixel
|
||||
(setq frame-resize-pixelwise t)
|
||||
|
||||
;; show a big square when cursor is on 'tab'
|
||||
(setq x-stretch-cursor t)
|
||||
|
||||
;; delete duplicate minibuffer history
|
||||
(setq history-delete-duplicates t)
|
||||
|
||||
;; allow scroll in isearch
|
||||
(setq isearch-allow-scroll t)
|
||||
|
||||
;; don't ask me when close emacs with running process
|
||||
(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
|
||||
"Prevent annoying \"Active processes exist\" query when you quit Emacs."
|
||||
(cl-flet ((process-list ())) ad-do-it))
|
||||
|
||||
;; don't ask when kill process buffer
|
||||
(setq kill-buffer-query-functions
|
||||
(remq 'process-kill-buffer-query-function
|
||||
kill-buffer-query-functions))
|
||||
|
||||
;; (setq byte-compile-warnings
|
||||
;; (quote (
|
||||
;; ;; 显示的警告
|
||||
;; free-vars ;不在当前范围的引用变量
|
||||
;; unresolved ;不知道的函数
|
||||
;; callargs ;函数调用的参数和定义的不匹配
|
||||
;; obsolete ;荒废的变量和函数
|
||||
;; noruntime ;函数没有定义在运行时期
|
||||
;; interactive-only ;正常不被调用的命令
|
||||
;; make-local ;调用 `make-variable-buffer-local' 可能会不正确的
|
||||
;; mapcar ;`mapcar' 调用
|
||||
;; ;;
|
||||
;; ;; 抑制的警告
|
||||
;; (not redefine) ;重新定义的函数 (比如参数数量改变)
|
||||
;; (not cl-functions) ;`CL' 包中的运行时调用的函数
|
||||
;; )))
|
||||
|
||||
(provide 'init-generic)
|
||||
|
||||
;;; init-generic.el ends here
|
11
site-lisp/init-config/init-highlight-parentheses.el
Normal file
11
site-lisp/init-config/init-highlight-parentheses.el
Normal file
@ -0,0 +1,11 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'highlight-parentheses)
|
||||
|
||||
;;; Code:
|
||||
(setq hl-paren-colors '("DarkOrange" "DeepSkyBlue" "DarkRed"))
|
||||
(add-hook 'find-file-hook 'highlight-parentheses-mode t)
|
||||
|
||||
(provide 'init-highlight-parentheses)
|
||||
|
||||
;;; init-highlight-parentheses.el ends here
|
59
site-lisp/init-config/init-indent.el
Normal file
59
site-lisp/init-config/init-indent.el
Normal file
@ -0,0 +1,59 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
(setq-default indent-tabs-mode nil)
|
||||
(setq-default tab-width 4)
|
||||
|
||||
(defun adjust-languages-indent (n)
|
||||
(setq-local tab-width n)
|
||||
|
||||
(when (or (derived-mode-p 'c-mode))
|
||||
(setq-local c-basic-offset n))
|
||||
|
||||
(when (or (derived-mode-p 'js-mode)
|
||||
(derived-mode-p 'js2-mode)
|
||||
(derived-mode-p 'web-mode))
|
||||
(setq-local javascript-indent-level n)
|
||||
(setq-local js-indent-level n)
|
||||
(setq-local js2-basic-offset n)
|
||||
|
||||
(setq-local css-indent-offset n)
|
||||
|
||||
(setq-local web-mode-attr-indent-offset n)
|
||||
(setq-local web-mode-attr-value-indent-offset n)
|
||||
(setq-local web-mode-code-indent-offset n)
|
||||
(setq-local web-mode-css-indent-offset n)
|
||||
(setq-local web-mode-markup-indent-offset n)
|
||||
(setq-local web-mode-sql-indent-offset n)
|
||||
))
|
||||
|
||||
(dolist (hook (list 'c-mode-hook
|
||||
'c++-mode-hook
|
||||
'java-mode-hook
|
||||
'haskell-mode-hook
|
||||
'asm-mode-hook
|
||||
'sh-mode-hook
|
||||
'haskell-cabal-mode-hook
|
||||
'ruby-mode-hook
|
||||
'qml-mode-hook
|
||||
'scss-mode-hook
|
||||
'python-mode-hook
|
||||
))
|
||||
(add-hook hook #'(lambda ()
|
||||
(adjust-languages-indent 4)
|
||||
)))
|
||||
|
||||
(dolist (hook (list 'lua-mode-hook
|
||||
'org-mode-hook
|
||||
'js-mode-hook
|
||||
'web-mode-hook
|
||||
'yaml-mode-hook
|
||||
))
|
||||
(add-hook hook #'(lambda ()
|
||||
(adjust-languages-indent 2)
|
||||
)))
|
||||
|
||||
(provide 'init-indent)
|
||||
|
||||
;;; init-indent.el ends here
|
92
site-lisp/init-config/init-mode.el
Normal file
92
site-lisp/init-config/init-mode.el
Normal file
@ -0,0 +1,92 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'jsonian)
|
||||
(require 'lua-mode)
|
||||
|
||||
;;; Code:
|
||||
;; bind ext to a specific mode
|
||||
(defun add-to-alist (alist-var elt-cons &optional no-replace)
|
||||
"Add to the value of ALIST-VAR an element ELT-CONS if it isn't there yet.
|
||||
If an element with the same car as the car of ELT-CONS is already present,
|
||||
replace it with ELT-CONS unless NO-REPLACE is non-nil; if a matching
|
||||
element is not already present, add ELT-CONS to the front of the alist.
|
||||
The test for presence of the car of ELT-CONS is done with `equal'."
|
||||
(let ((existing-element (assoc (car elt-cons) (symbol-value alist-var))))
|
||||
(if existing-element
|
||||
(or no-replace
|
||||
(rplacd existing-element (cdr elt-cons)))
|
||||
(set alist-var (cons elt-cons (symbol-value alist-var)))))
|
||||
(symbol-value alist-var))
|
||||
|
||||
(dolist (elt-cons '(
|
||||
("\\.org\\'" . org-mode)
|
||||
("\\.stumpwmrc\\'" . lisp-mode)
|
||||
("\\.jl\\'" . lisp-mode)
|
||||
("\\.asdf\\'" . lisp-mode)
|
||||
|
||||
("\\.markdown" . markdown-mode)
|
||||
("\\.md" . markdown-mode)
|
||||
|
||||
("\\.inc\\'" . asm-mode)
|
||||
|
||||
("\\.py\\'" . python-mode)
|
||||
("SConstruct". python-mode)
|
||||
|
||||
("\\.lua\\'" . lua-mode)
|
||||
|
||||
("\\.json\\'" . jsonian-mode)
|
||||
|
||||
("\\.go\\'" . go-mode)
|
||||
|
||||
("\\.css\\'" . css-mode)
|
||||
("\\.wxss\\'" . css-mode)
|
||||
|
||||
("\\.pdf\\'" . pdf-view-mode)
|
||||
|
||||
("\\.ts\\'" . typescript-mode)
|
||||
("\\.tsx\\'" . typescript-mode)
|
||||
|
||||
("\\.js.erb\\'" . web-mode)
|
||||
("\\.js\\'" . web-mode)
|
||||
("\\.wxs\\'" . web-mode)
|
||||
|
||||
("\\.vue" . web-mode)
|
||||
("\\.wxml" . web-mode)
|
||||
("\\.blade\\.php\\'" . web-mode)
|
||||
("\\.phtml\\'" . web-mode)
|
||||
("\\.tpl\\.php\\'" . web-mode)
|
||||
("\\.jsp\\'" . web-mode)
|
||||
("\\.mustache\\'" . web-mode)
|
||||
("\\.djhtml\\'" . web-mode)
|
||||
("\\.html?\\'" . web-mode)
|
||||
("\\.jsx\\'" . web-mode)
|
||||
|
||||
;; ("\\.rs$" . rust-mode)
|
||||
("CMakeLists\\.txt\\'" . cmake-mode)
|
||||
("\\.cmake\\'" . cmake-mode)
|
||||
))
|
||||
(add-to-alist 'auto-mode-alist elt-cons))
|
||||
|
||||
;;; Mode load.
|
||||
(autoload 'cmake-mode "cmake-mode")
|
||||
|
||||
(autoload 'css-mode "css-mode")
|
||||
|
||||
(autoload 'go-mode "go-mode")
|
||||
|
||||
(autoload 'jsonian-mode "jsonian-mode")
|
||||
|
||||
(autoload 'lua-mode "lua-mode")
|
||||
(setq lua-indent-level 2)
|
||||
|
||||
(autoload 'markdown-mode "markdown-mode")
|
||||
|
||||
(autoload 'python-mode "init-python")
|
||||
|
||||
(autoload 'web-mode "web-mode")
|
||||
|
||||
;; (autoload 'rust-mode "rust-mode")
|
||||
|
||||
(provide 'init-mode)
|
||||
|
||||
;;; init-mode.el ends here
|
12
site-lisp/init-config/init-neotree.el
Normal file
12
site-lisp/init-config/init-neotree.el
Normal file
@ -0,0 +1,12 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'neotree)
|
||||
|
||||
;;; Code:
|
||||
(setq neo-theme 'ascii)
|
||||
(setq neo-show-hidden-files t)
|
||||
(setq neo-window-width 40)
|
||||
|
||||
(provide 'init-neotree)
|
||||
|
||||
;;; init-neotree.el ends here
|
37
site-lisp/init-config/init-org-todo.el
Normal file
37
site-lisp/init-config/init-org-todo.el
Normal file
@ -0,0 +1,37 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'org)
|
||||
|
||||
;;; Code:
|
||||
(setq org-agenda-files '("~/Documents/ld_org_todo"))
|
||||
|
||||
(setq org-capture-templates
|
||||
'(
|
||||
("t" "todo" entry
|
||||
(file+datetree "~/Documents/ld_org_todo/todo.org")
|
||||
"* TODO [#C] %?\n\n%i"
|
||||
:empty-lines 1 :tree-type month)
|
||||
("w" "waiting" entry
|
||||
(file+datetree "~/Documents/ld_org_todo/waiting.org")
|
||||
"* TODO [#C] %?"
|
||||
:empty-lines 1 :tree-type month)
|
||||
))
|
||||
|
||||
(setq org-refile-targets
|
||||
'(
|
||||
("~/Documents/ld_org_todo/todo.org" :maxlevel . 4)
|
||||
("~/Documents/ld_org_todo/waiting.org" :maxlevel . 4)
|
||||
(nil :maxlevel . 4)
|
||||
))
|
||||
|
||||
(setq org-use-fast-todo-selection t)
|
||||
(setq org-todo-keywords '((sequence "TODO(t)" "DOING(i)"
|
||||
"|" "DONE(d)" "ABORTED(a)")))
|
||||
(setq org-todo-keyword-faces '(("TODO" . "red")
|
||||
("DOING" . "blue")
|
||||
("DONE" . "forest green")
|
||||
("ABORTED" . "gray")))
|
||||
|
||||
(provide 'init-org-todo)
|
||||
|
||||
;;; init-org-todo.el ends here.
|
233
site-lisp/init-config/init-org.el
Normal file
233
site-lisp/init-config/init-org.el
Normal file
@ -0,0 +1,233 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'org)
|
||||
(require 'ox-publish)
|
||||
|
||||
;;; Code:
|
||||
(defun ld-org-update-lastupdate-property ()
|
||||
"If '#+LASTUPDATE' is in org file, update it to the current date/time."
|
||||
(when (eq major-mode 'org-mode)
|
||||
(save-excursion
|
||||
(widen)
|
||||
(goto-char (point-min))
|
||||
(when (re-search-forward "^#\\+LASTUPDATE:" (point-max) t)
|
||||
(progn
|
||||
(setq lastupdate-point (point))
|
||||
(if (not (equal lastupdate-point (line-end-position)))
|
||||
(delete-region lastupdate-point (line-end-position)))
|
||||
(insert (format-time-string " %Y/%m/%d %H:%M")))))))
|
||||
|
||||
(add-hook 'before-save-hook #'ld-org-update-lastupdate-property)
|
||||
|
||||
(setq org-startup-indented nil) ;; enable org-indent-mode at start, default nil.
|
||||
|
||||
(setq org-goto-auto-isearch nil)
|
||||
(setq org-support-shift-select t)
|
||||
|
||||
(setq org-use-sub-superscripts '{})
|
||||
(setq org-export-with-sub-superscripts '{})
|
||||
|
||||
;; If it is not nil, strings below will be interpreted in exporting as
|
||||
;; Org HTML LaTeX UTF-8
|
||||
;; -----+----------+--------+-------
|
||||
;; \- ­ \-
|
||||
;; -- – -- –
|
||||
;; --- — --- —
|
||||
;; ... … \ldots …
|
||||
(setq org-export-with-special-strings nil)
|
||||
|
||||
;; (set-face-attribute 'org-level-1 nil
|
||||
;; :background "#fdf0ff"
|
||||
;; :foreground "#000000"
|
||||
;; :overline "#bcbcbc"
|
||||
;; :bold t
|
||||
;; :height 1.3)
|
||||
;; (set-face-attribute 'org-level-2 nil
|
||||
;; :foreground "#8f0075"
|
||||
;; :overline "#bcbcbc"
|
||||
;; :bold t
|
||||
;; :height 1.1)
|
||||
;; (set-face-attribute 'org-level-3 nil
|
||||
;; :foreground "#093060"
|
||||
;; :weight 'semi-bold)
|
||||
;; (set-face-attribute 'org-level-4 nil
|
||||
;; :foreground "#184034"
|
||||
;; :weight 'semi-bold)
|
||||
;; (set-face-attribute 'org-level-5 nil
|
||||
;; :foreground "#61284f"
|
||||
;; :weight 'semi-bold)
|
||||
;; (set-face-attribute 'org-level-6 nil
|
||||
;; :foreground "#3f3000"
|
||||
;; :weight 'semi-bold)
|
||||
;; (set-face-attribute 'org-level-7 nil
|
||||
;; :foreground "#5f0000"
|
||||
;; :weight 'semi-bold)
|
||||
;; (set-face-attribute 'org-level-8 nil
|
||||
;; :foreground "#541f4f"
|
||||
;; :weight 'semi-bold)
|
||||
|
||||
;; (set-face-attribute 'org-block-begin-line nil
|
||||
;; :background "#f0f0f0"
|
||||
;; :foreground "#505050"
|
||||
;; :extend t)
|
||||
;; (set-face-attribute 'org-block nil
|
||||
;; :background "#f8f8f8"
|
||||
;; :foreground "#000000"
|
||||
;; :extend t
|
||||
;; )
|
||||
;; (set-face-attribute 'org-block-end-line nil
|
||||
;; :background "#f0f0f0"
|
||||
;; :foreground "#505050"
|
||||
;; :extend t)
|
||||
|
||||
;; (set-face-attribute 'org-code nil
|
||||
;; :background "#f0f0f0"
|
||||
;; :foreground "#005a5f"
|
||||
;; :extend t)
|
||||
|
||||
;; (set-face-attribute 'org-verbatim nil
|
||||
;; :background "#f0f0f0"
|
||||
;; :foreground "#8f0075"
|
||||
;; :extend t)
|
||||
|
||||
(defun ld-org-custom-html-src-block (src-block _contents info)
|
||||
"Transcode a SRC-BLOCK element from Org to HTML.
|
||||
CONTENTS holds the contents of the item. INFO is a plist holding
|
||||
contextual information.
|
||||
MAKE FINAL HTML TO BE COMPATIBLE WITH highlight.js"
|
||||
(if (org-export-read-attribute :attr_html src-block :textarea)
|
||||
(org-html--textarea-block src-block)
|
||||
(let ((lang (org-element-property :language src-block))
|
||||
(caption (org-export-get-caption src-block))
|
||||
(code (org-html-format-code src-block info))
|
||||
(label (let ((lbl (and (org-element-property :name src-block)
|
||||
(org-export-get-reference src-block info))))
|
||||
(if lbl (format " id=\"%s\"" lbl) ""))))
|
||||
(if (not lang) (format "<pre class=\"example\"%s>\n%s</pre>" label code)
|
||||
(format
|
||||
"<div class=\"org-src-container\">\n%s%s\n</div>"
|
||||
(if (not caption) ""
|
||||
(format "<label class=\"org-src-name\">%s</label>"
|
||||
(org-export-data caption info)))
|
||||
(format "\n<pre class=\"src src-%s\"%s><code class=\"language-%s\">%s</code></pre>"
|
||||
lang label lang code))))))
|
||||
|
||||
(advice-add 'org-html-src-block :override 'ld-org-custom-html-src-block)
|
||||
|
||||
(defun ld-org-custom-html-format-list-item (contents type checkbox info
|
||||
&optional term-counter-id
|
||||
headline)
|
||||
"Format a list item into HTML."
|
||||
(let ((class (if checkbox
|
||||
(format " class=\"%s\""
|
||||
(symbol-name checkbox)) ""))
|
||||
(checkbox (concat (org-html-checkbox checkbox info)
|
||||
(and checkbox " ")))
|
||||
(br (org-html-close-tag "br" nil info))
|
||||
(extra-newline (if (and (org-string-nw-p contents) headline) "\n" "")))
|
||||
(concat
|
||||
(pcase type
|
||||
(`ordered
|
||||
(let* ((counter term-counter-id)
|
||||
(extra (if counter (format " value=\"%s\"" counter) "")))
|
||||
(concat
|
||||
(format "<li%s%s>" class extra)
|
||||
(when headline (concat headline br)))))
|
||||
(`unordered
|
||||
(let* ((id term-counter-id)
|
||||
(extra (if id (format " id=\"%s\"" id) "")))
|
||||
(concat
|
||||
(format "<li%s%s>" class extra)
|
||||
(when headline (concat headline br)))))
|
||||
(`descriptive
|
||||
(let* ((term term-counter-id))
|
||||
(setq term (or term "(no term)"))
|
||||
;; Check-boxes in descriptive lists are associated to tag.
|
||||
(concat (format "<dt%s>%s</dt>"
|
||||
class (concat checkbox term))
|
||||
"<dd><p>"))))
|
||||
(unless (eq type 'descriptive) checkbox)
|
||||
extra-newline
|
||||
(and (org-string-nw-p contents) (org-trim contents))
|
||||
extra-newline
|
||||
(pcase type
|
||||
(`ordered "</li>")
|
||||
(`unordered "</li>")
|
||||
(`descriptive "</p></dd>")))))
|
||||
|
||||
(advice-add 'org-html-format-list-item :override 'ld-org-custom-html-format-list-item)
|
||||
|
||||
(defun ld-org-export-publish()
|
||||
"Publish org and then generate sitemap.xml file."
|
||||
(interactive)
|
||||
;; import project settings
|
||||
(require 'ld-org-publish-project-desc)
|
||||
;; publish site
|
||||
(org-publish-all)
|
||||
;; create sitemap for search engine
|
||||
(let (
|
||||
;; FULL PATH to doc root. MUST end with a slash.
|
||||
(ld-site-pub-path-article-root "~/Public/ld_org_article_publish/article/")
|
||||
;; file name of sitemap file, relative to webroot.
|
||||
;; file name format: <sitemap-file-name>.xml
|
||||
(ld-site-sitemap-file-name "sitemap.xml")
|
||||
;; site domain name
|
||||
(ld-site-domain-name "lishouzhong.com")
|
||||
;; gzip it or not. t for true, nil for false.
|
||||
(ld-site-sitemap-gzip-it-p nil))
|
||||
|
||||
(print (concat "begin: " (format-time-string "%Y-%m-%dT%T")))
|
||||
|
||||
;; rename file to backup ~ if already exist
|
||||
(let (f1 f2)
|
||||
(setq f1 (concat ld-site-pub-path-article-root ld-site-sitemap-file-name))
|
||||
(setq f2 (concat f1 ".gz"))
|
||||
(when (file-exists-p f1)
|
||||
(rename-file f1 (concat f1 "~") t))
|
||||
(when (file-exists-p f2)
|
||||
(rename-file f2 (concat f2 "~") t)))
|
||||
|
||||
;; create sitemap buffer
|
||||
(let (article-file-path sitemap-buffer)
|
||||
(setq article-file-path
|
||||
(concat ld-site-pub-path-article-root ld-site-sitemap-file-name))
|
||||
(setq sitemap-buffer (find-file article-file-path))
|
||||
(erase-buffer)
|
||||
(set-buffer-file-coding-system 'unix)
|
||||
(insert "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||
<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">")
|
||||
|
||||
(require 'find-lisp)
|
||||
|
||||
(let ((process-sitemap-content
|
||||
(lambda (article-file-path dest-buffer)
|
||||
(when (not (string-match "/zzz" article-file-path)) ; dir/file starting with zzz are not public
|
||||
(with-temp-buffer
|
||||
(insert-file-contents article-file-path nil nil nil t)
|
||||
(goto-char 1)
|
||||
(when (not (search-forward "<meta http-equiv=\"refresh\"" nil "noerror"))
|
||||
(with-current-buffer dest-buffer
|
||||
(insert "<url><loc>")
|
||||
(insert (concat
|
||||
"http://"
|
||||
ld-site-domain-name
|
||||
"/"
|
||||
(substring article-file-path
|
||||
(length (expand-file-name ld-site-pub-path-article-root)))))
|
||||
(insert "</loc></url>\n"))))))))
|
||||
(mapc
|
||||
(lambda (x) (funcall process-sitemap-content x sitemap-buffer))
|
||||
(find-lisp-find-files ld-site-pub-path-article-root "\\.html$")))
|
||||
|
||||
(insert "</urlset>")
|
||||
|
||||
(save-buffer)
|
||||
|
||||
(when ld-site-sitemap-gzip-it-p
|
||||
(shell-command (concat "gzip " article-file-path))))
|
||||
|
||||
(print (concat "finished: " (format-time-string "%Y-%m-%dT%T")))))
|
||||
|
||||
(provide 'init-org)
|
||||
|
||||
;;; init-org.el ends here
|
45
site-lisp/init-config/init-proxy.el
Normal file
45
site-lisp/init-config/init-proxy.el
Normal file
@ -0,0 +1,45 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require
|
||||
|
||||
;;; Code:
|
||||
(defun proxy-socks-show ()
|
||||
"Show SOCKS proxy."
|
||||
(interactive)
|
||||
(when (fboundp 'cadddr)
|
||||
(if (bound-and-true-p socks-noproxy)
|
||||
(message "Current SOCKS%d proxy is %s:%d"
|
||||
(cadddr socks-server) (cadr socks-server) (caddr socks-server))
|
||||
(message "No SOCKS proxy"))))
|
||||
|
||||
(defun proxy-socks-enable ()
|
||||
"Enable SOCKS proxy."
|
||||
(interactive)
|
||||
(require 'socks)
|
||||
(setq url-gateway-method 'socks
|
||||
socks-noproxy '("localhost")
|
||||
socks-server '("Default server" "127.0.0.1" 10800 5))
|
||||
(setenv "all_proxy" "socks5://127.0.0.1:10800")
|
||||
(proxy-socks-show))
|
||||
|
||||
(defun proxy-socks-disable ()
|
||||
"Disable SOCKS proxy."
|
||||
(interactive)
|
||||
(require 'socks)
|
||||
(setq url-gateway-method 'native
|
||||
socks-noproxy nil)
|
||||
(setenv "all_proxy" "")
|
||||
(proxy-socks-show))
|
||||
|
||||
(defun proxy-socks-toggle ()
|
||||
"Toggle SOCKS proxy."
|
||||
(interactive)
|
||||
(require 'socks)
|
||||
(if (bound-and-true-p socks-noproxy)
|
||||
(proxy-socks-disable)
|
||||
(proxy-socks-enable)))
|
||||
|
||||
;; (proxy-socks-enable)
|
||||
|
||||
(provide 'init-proxy)
|
||||
|
||||
;;; init-proxy.el ends here
|
51
site-lisp/init-config/init-session.el
Normal file
51
site-lisp/init-config/init-session.el
Normal file
@ -0,0 +1,51 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'auto-save)
|
||||
|
||||
;;; Code:
|
||||
|
||||
(setq desktop-load-locked-desktop t) ; don't popup dialog ask user, load anyway
|
||||
(setq desktop-restore-frames nil) ; don't restore any frame
|
||||
|
||||
(defun kill-unused-buffers ()
|
||||
(interactive)
|
||||
(ignore-errors
|
||||
(save-excursion
|
||||
(dolist (buf (buffer-list))
|
||||
(set-buffer buf)
|
||||
(when (and (string-prefix-p "*" (buffer-name)) (string-suffix-p "*" (buffer-name)))
|
||||
(kill-buffer buf))
|
||||
))))
|
||||
|
||||
(defun emacs-session-restore ()
|
||||
"Restore emacs session."
|
||||
(interactive)
|
||||
(ignore-errors
|
||||
;; Kill other windows.
|
||||
(delete-other-windows)
|
||||
;; Kill unused buffers.
|
||||
(kill-unused-buffers)
|
||||
;; Restore session.
|
||||
(desktop-read "~/.emacs.d/")
|
||||
))
|
||||
|
||||
(defun emacs-session-save (&optional arg)
|
||||
"Save emacs session."
|
||||
(interactive "p")
|
||||
(ignore-errors
|
||||
(if (equal arg 4)
|
||||
;; Kill all buffers if with prefix argument.
|
||||
(mapc 'kill-buffer (buffer-list))
|
||||
;; Kill unused buffers.
|
||||
(kill-unused-buffers)
|
||||
;; Save all buffers before exit.
|
||||
(auto-save-buffers))
|
||||
;; Save session.
|
||||
(make-directory "~/.emacs.d/" t)
|
||||
(desktop-save "~/.emacs.d/")
|
||||
;; Exit emacs.
|
||||
(kill-emacs)))
|
||||
|
||||
(provide 'init-session)
|
||||
|
||||
;;; init-session.el ends here
|
256
site-lisp/init-config/init-shortcut.el
Normal file
256
site-lisp/init-config/init-shortcut.el
Normal file
@ -0,0 +1,256 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
|
||||
;;; There are 3 sections:
|
||||
;;; - unset keys
|
||||
;;; - extensions
|
||||
;;; - extensions-local
|
||||
;;; - shortcut on built-in function
|
||||
|
||||
;;; ------------ unset keys
|
||||
|
||||
; originally
|
||||
; 'C-i' is TAB
|
||||
; 'C-r' is isearch-backward
|
||||
(lazy-load-unset-keys
|
||||
'("C-z" "C-\\" "C-'" "C-i" "C-r"))
|
||||
|
||||
|
||||
|
||||
;;; ------------ extensions
|
||||
|
||||
;; ------ ace-window
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-o" . ace-window)
|
||||
)
|
||||
"init-ace-window")
|
||||
|
||||
;; ------ avy
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-g c" . avy-goto-char)
|
||||
("M-g w" . avy-goto-word-1)
|
||||
("M-g s" . avy-goto-word-0)
|
||||
("M-g l l" . avy-goto-line)
|
||||
("M-g j" . avy-next)
|
||||
("M-g k" . avy-prev)
|
||||
)
|
||||
"init-avy")
|
||||
|
||||
;; ------ citre
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-x c c" . citre-mode)
|
||||
("C-x c j" . citre-jump)
|
||||
("C-x c J" . citre-jump-back)
|
||||
("C-x c p" . citre-ace-peek)
|
||||
("C-x c u" . citre-update-this-tags-file)
|
||||
)
|
||||
"init-citre")
|
||||
|
||||
;; ------ theme
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("<f5>" . ld-modus-themes-toggle)
|
||||
)
|
||||
"init-theme")
|
||||
|
||||
;; ------ multiple cursors
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-M-." . mc/mark-next-like-this)
|
||||
("C-M-," . mc/unmark-next-like-this)
|
||||
("M-<" . mc/mark-previous-like-this)
|
||||
("M->" . mc/unmark-previous-like-this)
|
||||
("C-M-<" . mc/edit-beginnings-of-lines)
|
||||
("M-<mouse-1>" . mc/add-cursor-on-click)
|
||||
)
|
||||
"multiple-cursors")
|
||||
|
||||
;; ------ swiper
|
||||
(lazy-load-set-keys
|
||||
'(
|
||||
("C-s" . swiper-isearch)
|
||||
("C-c s" . counsel-rg)
|
||||
))
|
||||
|
||||
|
||||
|
||||
;;; ------------ extensions-local
|
||||
|
||||
(lazy-load-set-keys
|
||||
'(
|
||||
;; dired-display-buffer
|
||||
("o" . dired-display-buffer)
|
||||
;; dired-narrow
|
||||
("/" . dired-narrow)
|
||||
;; dired-subtree
|
||||
("<tab>" . dired-subtree-cycle)
|
||||
("SPC" . dired-subtree-toggle)
|
||||
("C-p" . dired-subtree-previous-sibling)
|
||||
("C-n" . dired-subtree-next-sibling)
|
||||
("r" . dired-subtree-revert)
|
||||
)
|
||||
dired-mode-map)
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-c e e" . toggle-echo-keys)
|
||||
("C-c e c" . echo-keys-clean)
|
||||
)
|
||||
"echo-keys") ;show every pressed keys
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-c x e" . ld-eval-elisp-to-next-line)
|
||||
)
|
||||
"evals") ;execute code
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-<" . ld-un-indent)
|
||||
("C->" . ld-indent)
|
||||
)
|
||||
"force-indent") ;control 4 spaces indent manually
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-c \\" . goto-last-change)
|
||||
)
|
||||
"goto-last-change")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-g l p" . goto-line-preview)
|
||||
)
|
||||
"goto-line-preview")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-c m h a" . highlight-indentation-mode)
|
||||
("C-c m h c" . highlight-indentation-current-column-mode)
|
||||
)
|
||||
"highlight-indentation")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-r i" . ld-indent-buffer)
|
||||
("C-r r" . ld-rename-file-and-buffer)
|
||||
("C-r d" . ld-delete-file-and-buffer)
|
||||
("C-r e" . ld-revert-buffer-no-confirm)
|
||||
("C-i r" . ld-find-file-in-root) ; open file with root by sudo
|
||||
)
|
||||
"ld-buffer-operations")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-;" . ld-cursor-position-1-store) ;store cursor position
|
||||
("C-'" . ld-cursor-position-1-jump) ;jump to cursor position
|
||||
("C-c ," . ld-cursor-position-stack-push) ;push cursor position to stack
|
||||
("C-c ." . ld-cursor-position-stack-pop) ;pop corsor position from stack
|
||||
)
|
||||
"ld-goto-cursor-stack")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-N" . ld-delete-one-block-backward)
|
||||
("M-M" . ld-delete-one-block-forward)
|
||||
)
|
||||
"ld-delete-block") ;delete a block (eg. a word) forward and backward
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-i r" . ld-find-file-in-root) ; open file with root by sudo
|
||||
)
|
||||
"ld-file-operations")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-g l p" . ld-goto-percent-line)
|
||||
("M-g t p" . ld-goto-percent-text)
|
||||
("M-g t c" . ld-goto-column)
|
||||
)
|
||||
"ld-goto-simple")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-p" . ld-move-text-up)
|
||||
("M-n" . ld-move-text-down)
|
||||
("C-c l d" . ld-duplicate-current-line-or-region)
|
||||
("C-c l D" . ld-duplicate-and-comment-current-line-or-region)
|
||||
("C-c l k" . ld-delete-current-line)
|
||||
("C-c m l" . ld-mark-line)
|
||||
)
|
||||
"ld-text-operations")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("C-c w t" . ld-toggle-one-window)
|
||||
)
|
||||
"ld-toggle-one-window") ;maxmize current window and size back
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(("C-x j" . neotree-toggle))
|
||||
"init-neotree")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("M-j" . watch-next-window-up-line) ; 'up' to see previous content
|
||||
("M-k" . watch-next-window-down-line) ; 'down' to see further content
|
||||
("M-J" . watch-next-window-up)
|
||||
("M-K" . watch-next-window-down)
|
||||
)
|
||||
"scroll-next-window")
|
||||
|
||||
(lazy-load-global-keys
|
||||
'(
|
||||
("<f4>" . emacs-session-save)
|
||||
)
|
||||
"init-session")
|
||||
|
||||
|
||||
|
||||
;;; ------------ shortcut on built-in function
|
||||
|
||||
;; ------ org related
|
||||
(lazy-load-set-keys
|
||||
'(
|
||||
("C-c o c" . org-capture)
|
||||
("C-c o a" . org-agenda)
|
||||
("C-c o l r" . org-list-repair)
|
||||
))
|
||||
|
||||
;; ------ move cursors in current buffer
|
||||
(lazy-load-set-keys
|
||||
'(
|
||||
("M-g b k" . beginning-of-buffer)
|
||||
("M-g b j" . end-of-buffer)
|
||||
("M-g h j" . forward-paragraph)
|
||||
("M-g h k" . backward-paragraph)
|
||||
("M-g l y" . backward-up-list) ;向左跳出 LIST
|
||||
("M-g l o" . up-list) ;向右跳出 LIST
|
||||
("M-g l u" . backward-down-list) ;向左跳进 LIST
|
||||
("M-g l i" . down-list) ;向右跳进 LIST
|
||||
("M-g f a" . beginning-of-defun) ;函数开头
|
||||
("M-g f e" . end-of-defun) ;函数末尾
|
||||
))
|
||||
|
||||
;; ------ other
|
||||
(lazy-load-set-keys
|
||||
'(
|
||||
("C-z r" . global-hl-line-mode)
|
||||
("C-z l" . display-line-numbers-mode)
|
||||
("M--" . text-scale-decrease)
|
||||
("M-=" . text-scale-increase)
|
||||
("M-," . bury-buffer)
|
||||
("M-." . unbury-buffer)
|
||||
("C-c m m" . set-mark-command) ; replace C-Space for Chinese input method
|
||||
("M-;" . comment-dwim)
|
||||
("C-c r" . recentf-open-files)
|
||||
))
|
||||
|
||||
|
||||
|
||||
(provide 'init-shortcut)
|
||||
|
||||
;;; init-shortcut.el ends here
|
34
site-lisp/init-config/init-swiper.el
Normal file
34
site-lisp/init-config/init-swiper.el
Normal file
@ -0,0 +1,34 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'ivy)
|
||||
(require 'counsel)
|
||||
(require 'swiper)
|
||||
|
||||
;;; Code:
|
||||
(setq ivy-use-virtual-buffers t)
|
||||
(setq ivy-initial-inputs-alist nil)
|
||||
(setq ivy-count-format "(%d/%d) ")
|
||||
|
||||
;; Map commands to their minimum required input length.
|
||||
;; That is the number of characters prompted for before fetching
|
||||
;; candidates. The special key t is used as a fallback.
|
||||
(setq ivy-more-chars-alist '((t . 2)))
|
||||
|
||||
(ivy-mode 1)
|
||||
|
||||
(setq counsel-rg-base-command
|
||||
`("rg"
|
||||
"--max-columns" "0"
|
||||
"--with-filename"
|
||||
"--no-heading"
|
||||
"--line-number"
|
||||
"--color" "never"
|
||||
"%s"
|
||||
,@(and (memq system-type '(ms-dos windows-nt))
|
||||
(list "--path-separator" "/" "."))))
|
||||
|
||||
(counsel-mode 1)
|
||||
|
||||
(provide 'init-swiper)
|
||||
|
||||
;; init-swiper.el ends here
|
82
site-lisp/init-config/init-theme.el
Normal file
82
site-lisp/init-config/init-theme.el
Normal file
@ -0,0 +1,82 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'modus-themes)
|
||||
|
||||
;;; Code:
|
||||
;; font
|
||||
(when (and window-system *win64*)
|
||||
(let ((default-font (font-spec :name "Sarasa Fixed SC"))
|
||||
(cn-font (font-spec :name "Sarasa Fixed SC")))
|
||||
(set-face-attribute 'default nil :font default-font :height 116)
|
||||
(dolist (charset '(kana han symbol cjk-misc bopomofo))
|
||||
(set-fontset-font t charset cn-font)))
|
||||
(set-face-font 'fixed-pitch "Sarasa Fixed SC"))
|
||||
|
||||
;; theme
|
||||
;; In all of the following, WEIGHT is a symbol such as `semibold',
|
||||
;; `light', `bold', or anything mentioned in `modus-themes-weights'.
|
||||
(setq modus-themes-italic-constructs t
|
||||
modus-themes-bold-constructs nil
|
||||
modus-themes-mixed-fonts t
|
||||
modus-themes-variable-pitch-ui nil
|
||||
modus-themes-custom-auto-reload t
|
||||
modus-themes-disable-other-themes t
|
||||
|
||||
;; Options for `modus-themes-prompts' are either nil (the
|
||||
;; default), or a list of properties that may include any of those
|
||||
;; symbols: `italic', `WEIGHT'
|
||||
modus-themes-prompts '(italic bold)
|
||||
|
||||
;; The `modus-themes-completions' is an alist that reads two
|
||||
;; keys: `matches', `selection'. Each accepts a nil value (or
|
||||
;; empty list) or a list of properties that can include any of
|
||||
;; the following (for WEIGHT read further below):
|
||||
;;
|
||||
;; `matches' :: `underline', `italic', `WEIGHT'
|
||||
;; `selection' :: `underline', `italic', `WEIGHT'
|
||||
modus-themes-completions
|
||||
'((matches . (extrabold))
|
||||
(selection . (semibold italic text-also)))
|
||||
|
||||
modus-themes-org-blocks 'gray-background ; {nil,'gray-background,'tinted-background}
|
||||
|
||||
;; The `modus-themes-headings' is an alist: read the manual's
|
||||
;; node about it or its doc string. Basically, it supports
|
||||
;; per-level configurations for the optional use of
|
||||
;; `variable-pitch' typography, a height value as a multiple of
|
||||
;; the base font size (e.g. 1.5), and a `WEIGHT'.
|
||||
modus-themes-headings
|
||||
'((1 . (variable-pitch 1.5))
|
||||
(2 . (1.3))
|
||||
(agenda-date . (1.3))
|
||||
(agenda-structure . (variable-pitch light 1.8))
|
||||
(t . (1.1))))
|
||||
|
||||
(defun ld-modus-operandi ()
|
||||
"Light theme."
|
||||
(interactive)
|
||||
;; load theme firstly and then do user customization
|
||||
;; otherwise modus-themes will override the face user had assigned
|
||||
(load-theme 'modus-operandi :no-confirm))
|
||||
|
||||
(defun ld-modus-vivendi-tinted ()
|
||||
"Dark theme."
|
||||
(interactive)
|
||||
;; load theme firstly and then do user customization
|
||||
;; otherwise modus-themes will override the face user had assigned
|
||||
(load-theme 'modus-vivendi-tinted :no-confirm))
|
||||
|
||||
(defun ld-modus-themes-toggle ()
|
||||
(interactive)
|
||||
(if (eq (car custom-enabled-themes) 'modus-operandi)
|
||||
(ld-modus-vivendi-tinted)
|
||||
(ld-modus-operandi)))
|
||||
|
||||
;; active light theme
|
||||
(if window-system
|
||||
(ld-modus-operandi)
|
||||
(ld-modus-vivendi-tinted))
|
||||
|
||||
(provide 'init-theme)
|
||||
|
||||
;;; init-theme.el ends here
|
14
site-lisp/init-config/init-time.el
Normal file
14
site-lisp/init-config/init-time.el
Normal file
@ -0,0 +1,14 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(setq display-time-day-and-date t)
|
||||
(setq display-time-format "%Y/%m/%d %H:%M")
|
||||
(setq display-time-24hr-format t)
|
||||
(display-time-mode 1)
|
||||
(display-time)
|
||||
|
||||
(provide 'init-time)
|
||||
|
||||
;;; init-time.el ends here
|
19
site-lisp/init-config/init-undo-tree.el
Normal file
19
site-lisp/init-config/init-undo-tree.el
Normal file
@ -0,0 +1,19 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'undo-tree)
|
||||
|
||||
;;; Code:
|
||||
(global-undo-tree-mode)
|
||||
|
||||
;; ;; --- undo-tree
|
||||
;; (lazy-load-local-keys
|
||||
;; '(
|
||||
;; ("C-/" . undo-tree-undo)
|
||||
;; ("C-?" . undo-tree-redo)
|
||||
;; )
|
||||
;; undo-tree-map
|
||||
;; "undo-tree")
|
||||
|
||||
(provide 'init-undo-tree)
|
||||
|
||||
;;; init-undo-tree.el ends here
|
17
site-lisp/init-config/init-which-key.el
Normal file
17
site-lisp/init-config/init-which-key.el
Normal file
@ -0,0 +1,17 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'which-key)
|
||||
|
||||
;;; Code:
|
||||
(setq which-key-show-early-on-C-h t)
|
||||
(setq which-key-idle-delay 10000)
|
||||
(setq which-key-idle-secondary-delay 0.05)
|
||||
(setq which-key-max-description-length nil) ;; show entire key name
|
||||
|
||||
(which-key-mode)
|
||||
|
||||
(which-key-setup-side-window-bottom)
|
||||
|
||||
(provide 'init-which-key)
|
||||
|
||||
;;; init-which-key.el ends here
|
17
site-lisp/init-config/init-yasnippet.el
Normal file
17
site-lisp/init-config/init-yasnippet.el
Normal file
@ -0,0 +1,17 @@
|
||||
;; -*- coding: utf-8; -*-
|
||||
;;; Require:
|
||||
(require 'yasnippet)
|
||||
|
||||
;;; Code:
|
||||
(setq yas-snippet-dirs (list (concat ld-emacs-root-dir "/snippets")))
|
||||
(yas-global-mode 1)
|
||||
|
||||
;; Disable yasnippet mode on some mode.
|
||||
(dolist (hooks (list
|
||||
'term-mode-hook
|
||||
))
|
||||
(add-hook hooks #'(lambda () (yas-minor-mode -1))))
|
||||
|
||||
(provide 'init-yasnippet)
|
||||
|
||||
;;; init-yasnippet.el ends here
|
46
site-lisp/init-config/init.el
Normal file
46
site-lisp/init-config/init.el
Normal file
@ -0,0 +1,46 @@
|
||||
;;; -*- coding: utf-8-unix; lexical-binding: t; -*-
|
||||
|
||||
(let (
|
||||
;; Make startup faster by reducing the frequency of garbage collection.
|
||||
;; default (* 800 1000) bytes
|
||||
(gc-cons-threshold most-positive-fixnum)
|
||||
;; default 0.1
|
||||
(gc-cons-percentage 0.6))
|
||||
|
||||
;; keep frame size
|
||||
(setq frame-inhibit-implied-resize t)
|
||||
|
||||
;; from local extensions
|
||||
;; firstly loaded part
|
||||
(require 'init-theme)
|
||||
(require 'lazy-load)
|
||||
(require 'init-generic)
|
||||
(require 'ld-tools)
|
||||
|
||||
(require 'init-auto-save)
|
||||
(require 'init-coding-system)
|
||||
(require 'init-company-mode)
|
||||
(require 'init-dired)
|
||||
(require 'init-highlight-parentheses)
|
||||
(require 'init-indent)
|
||||
(require 'init-mode)
|
||||
(require 'init-org-todo)
|
||||
(require 'init-org)
|
||||
(require 'init-proxy)
|
||||
(require 'init-swiper)
|
||||
(require 'init-time)
|
||||
(require 'init-undo-tree)
|
||||
(require 'init-which-key)
|
||||
(require 'init-yasnippet)
|
||||
|
||||
;; restore session
|
||||
(require 'init-session)
|
||||
(emacs-session-restore)
|
||||
|
||||
;; finally load other plugins dynamically
|
||||
(require 'init-shortcut)
|
||||
)
|
||||
|
||||
(provide 'init)
|
||||
|
||||
;;; init.el ends here
|
6
site-lisp/snippets/lua-mode/function
Normal file
6
site-lisp/snippets/lua-mode/function
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: function
|
||||
# key: fun
|
||||
# --
|
||||
function ${1: fun_name}()
|
||||
end
|
8
site-lisp/snippets/org-mode/bloghead
Normal file
8
site-lisp/snippets/org-mode/bloghead
Normal file
@ -0,0 +1,8 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: bloghead
|
||||
# key: bh
|
||||
# --
|
||||
|
||||
#+TITLE:
|
||||
#+DATE:
|
||||
#+LASTUPDATE:
|
7
site-lisp/snippets/org-mode/notehead
Normal file
7
site-lisp/snippets/org-mode/notehead
Normal file
@ -0,0 +1,7 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: notehead
|
||||
# key: nh
|
||||
# --
|
||||
|
||||
#+TITLE:
|
||||
#+LASTUPDATE:
|
6
site-lisp/snippets/sh-mode/bang
Normal file
6
site-lisp/snippets/sh-mode/bang
Normal file
@ -0,0 +1,6 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: bang
|
||||
# key: !
|
||||
# --
|
||||
#!/usr/bin/env bash
|
||||
$0
|
5
site-lisp/snippets/snippet-mode/cont
Normal file
5
site-lisp/snippets/snippet-mode/cont
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: cont
|
||||
# key: cont
|
||||
# --
|
||||
# contributor: `user-full-name`
|
5
site-lisp/snippets/snippet-mode/elisp
Normal file
5
site-lisp/snippets/snippet-mode/elisp
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: elisp
|
||||
# key: `
|
||||
# --
|
||||
\`$0\`
|
6
site-lisp/snippets/snippet-mode/field
Normal file
6
site-lisp/snippets/snippet-mode/field
Normal file
@ -0,0 +1,6 @@
|
||||
# name : ${ ... } field
|
||||
# contributor : joaotavora
|
||||
# key : $f
|
||||
# key: field
|
||||
# --
|
||||
\${${1:${2:n}:}$3${4:\$(${5:lisp-fn})}\}$0
|
5
site-lisp/snippets/snippet-mode/group
Normal file
5
site-lisp/snippets/snippet-mode/group
Normal file
@ -0,0 +1,5 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name: group
|
||||
# key: group
|
||||
# --
|
||||
# group : ${1:group}
|
6
site-lisp/snippets/snippet-mode/mirror
Normal file
6
site-lisp/snippets/snippet-mode/mirror
Normal file
@ -0,0 +1,6 @@
|
||||
# name : ${n:$(...)} mirror
|
||||
# key : $m
|
||||
# contributor : joaotavora
|
||||
# key: mirror
|
||||
# --
|
||||
\${${2:n}:${4:\$(${5:reflection-fn})}\}$0
|
13
site-lisp/snippets/snippet-mode/vars
Normal file
13
site-lisp/snippets/snippet-mode/vars
Normal file
@ -0,0 +1,13 @@
|
||||
# -*- mode: snippet -*-
|
||||
# name : Snippet header
|
||||
# contributor : joaotavora
|
||||
# key: vars
|
||||
# --
|
||||
# name : $1${2:
|
||||
# key : ${3:trigger-key}}${4:
|
||||
# keybinding : ${5:keybinding}}${6:
|
||||
# expand-env : (${7:})}
|
||||
# contributor : $6
|
||||
# key: vars
|
||||
# --
|
||||
$0
|
51
site-start.el
Normal file
51
site-start.el
Normal file
@ -0,0 +1,51 @@
|
||||
(require 'cl-lib)
|
||||
|
||||
(defun add-subdirs-to-load-path (search-dir)
|
||||
(interactive)
|
||||
(let* ((dir (file-name-as-directory search-dir)))
|
||||
(dolist (subdir
|
||||
;; 过滤出不必要的目录,提升Emacs启动速度
|
||||
(cl-remove-if
|
||||
#'(lambda (subdir)
|
||||
(or
|
||||
;; 不是目录的文件都移除
|
||||
(not (file-directory-p (concat dir subdir)))
|
||||
;; 父目录、 语言相关和版本控制目录都移除
|
||||
(member subdir '("." ".."
|
||||
"dist" "node_modules" "__pycache__"
|
||||
"RCS" "CVS" "rcs" "cvs" ".git" ".github"))))
|
||||
(directory-files dir)))
|
||||
(let ((subdir-path (concat dir (file-name-as-directory subdir))))
|
||||
;; 目录下有 .el .so .dll 文件的路径才添加到 `load-path' 中,提升Emacs启动速度
|
||||
(when (cl-some #'(lambda (subdir-file)
|
||||
(and (file-regular-p (concat subdir-path subdir-file))
|
||||
;; .so .dll 文件指非Elisp语言编写的Emacs动态库
|
||||
(member (file-name-extension subdir-file) '("el" "so" "dll"))))
|
||||
(directory-files subdir-path))
|
||||
|
||||
;; 注意:add-to-list 函数的第三个参数必须为 t ,表示加到列表末尾
|
||||
;; 这样Emacs会从父目录到子目录的顺序搜索Elisp插件,顺序反过来会导致Emacs无法正常启动
|
||||
(add-to-list 'load-path subdir-path t))
|
||||
|
||||
;; 继续递归搜索子目录
|
||||
(add-subdirs-to-load-path subdir-path)))))
|
||||
|
||||
;; get emacs version and operating system type
|
||||
(defvar *emacs27* (>= emacs-major-version 27))
|
||||
(defvar *is-a-mac* (eq system-type 'darwin))
|
||||
(defvar *win64* (eq system-type 'windows-nt))
|
||||
(defvar *cygwin* (eq system-type 'cygwin))
|
||||
(defvar *linux* (or (eq system-type 'gnu/linux) (eq system-type 'linux)))
|
||||
(defvar *unix* (or *linux*
|
||||
(eq system-type 'usg-unix-v)
|
||||
(eq system-type 'berkeley-unix)))
|
||||
|
||||
(defvar ld-emacs-root-dir (file-truename "~/ld-emacs/site-lisp"))
|
||||
|
||||
(if *win64*
|
||||
(add-subdirs-to-load-path ld-emacs-root-dir))
|
||||
|
||||
(if *linux*
|
||||
(add-subdirs-to-load-path "/usr/share/emacs/ld"))
|
||||
|
||||
(require 'init)
|
Loading…
x
Reference in New Issue
Block a user