├── .gitignore
├── .travis.yml
├── Makefile
├── README.markdown
├── ert-tests
├── examples
│ ├── CVS
│ │ ├── bash-fc-0
│ │ ├── elisp_protpath_localnil.el
│ │ ├── elisp_protpath_localt.el
│ │ ├── text_protpath.txt
│ │ └── text_protpath_editpat.txt
│ ├── editpat-autoloads.el
│ ├── elisp_editpat.el
│ ├── elisp_editpat_localnil.el
│ ├── elisp_editpat_localt.el
│ ├── elisp_editpat_readonlyfile.el
│ ├── elisp_nopat.bak
│ ├── elisp_nopat.el
│ ├── elisp_protpat.el
│ ├── elisp_protpat_editpat.el
│ ├── elisp_protpat_localnil.el
│ ├── elisp_protpat_localt.el
│ ├── perl_endpat.pl
│ ├── perl_endpat_semantic.pl
│ ├── perl_endpat_toofar.pl
│ ├── perl_modepat.pl
│ ├── protected-autoloads.el
│ ├── shell-editpat.sh
│ └── text_perlmodepat.txt
└── hardhat-test.el
└── hardhat.el
/.gitignore:
--------------------------------------------------------------------------------
1 | /ert-tests/ert.el
2 | /ert-tests/ignoramus.el
3 | *-autoloads.el
4 | *.elc
5 | *~
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ###
2 | ### Notes
3 | ###
4 | ### The travis web interface may choke silently and fail to
5 | ### update when there are issues with the .travis.yml file.
6 | ###
7 | ### The "travis-lint" command-line tool does not catch all
8 | ### errors which may lead to silent failure.
9 | ###
10 | ### Shell-style comments must have "#" as the first character
11 | ### of the line.
12 | ###
13 |
14 | ###
15 | ### language
16 | ###
17 |
18 | # travis-lint no longer permits this value
19 | # language: emacs-lisp
20 | language: ruby
21 |
22 | ###
23 | ### defining the build matrix
24 | ###
25 | ### ===> <===
26 | ### ===> each variation in env/matrix will be built and tested <===
27 | ### ===> <===
28 | ###
29 | ### variables under env/global are available to the build process
30 | ### but don't cause the creation of a separate variation
31 | ###
32 |
33 | env:
34 | matrix:
35 | - EMACS=emacs22
36 | - EMACS=emacs23
37 | - EMACS=emacs24
38 | - EMACS=emacs-snapshot
39 | global:
40 | - SOME_TOKEN=some_value
41 |
42 | ###
43 | ### allowing failures
44 | ###
45 |
46 | matrix:
47 | allow_failures:
48 | - env: EMACS=emacs22
49 | - env: EMACS=emacs-snapshot
50 |
51 | ###
52 | ### limit build attempts to defined branches
53 | ###
54 |
55 | # branches:
56 | # only:
57 | # - master
58 |
59 | ###
60 | ### runtime initialization
61 | ###
62 | ### notes
63 | ###
64 | ### emacs22 is extracted manually from Ubuntu Maverick.
65 | ###
66 | ### emacs23 is the stock default, but is updated anyway to
67 | ### a GUI-capable version, which will have certain additional
68 | ### functions compiled in.
69 | ###
70 | ### emacs24 (current stable release) is obtained from the
71 | ### cassou PPA: http://launchpad.net/~cassou/+archive/emacs
72 | ###
73 | ### emacs-snapshot (trunk) is obtained from the Ubuntu Emacs Lisp PPA:
74 | ### https://launchpad.net/~ubuntu-elisp/+archive/ppa
75 | ### For the emacs-snapshot build, bleeding-edge versions
76 | ### of all test dependencies are also used.
77 | ###
78 |
79 | before_install:
80 | - git submodule --quiet update --init --recursive
81 |
82 | install:
83 | - if [ "$EMACS" = 'emacs22' ]; then
84 | curl -Os http://security.ubuntu.com/ubuntu/pool/universe/e/emacs22/emacs22_22.2-0ubuntu9_i386.deb &&
85 | curl -Os http://security.ubuntu.com/ubuntu/pool/universe/e/emacs22/emacs22-bin-common_22.2-0ubuntu9_i386.deb &&
86 | curl -Os http://security.ubuntu.com/ubuntu/pool/universe/e/emacs22/emacs22-common_22.2-0ubuntu9_all.deb &&
87 | curl -Os http://security.ubuntu.com/ubuntu/pool/universe/e/emacs22/emacs22-el_22.2-0ubuntu9_all.deb &&
88 | curl -Os http://security.ubuntu.com/ubuntu/pool/universe/e/emacs22/emacs22-gtk_22.2-0ubuntu9_i386.deb &&
89 | sudo apt-get -qq update &&
90 | sudo apt-get -qq remove emacs emacs23-bin-common emacs23-common emacs23-nox &&
91 | sudo apt-get -qq --fix-missing install install-info emacsen-common libjpeg62:i386 xaw3dg:i386 liblockfile1:i386 libasound2:i386 libgif4:i386 libncurses5:i386 libpng12-0:i386 libtiff4:i386 libxpm4:i386 libxft2:i386 libglib2.0-0:i386 libgtk2.0-0:i386 &&
92 | sudo apt-get -qq -f install &&
93 | sudo dpkg -i emacs22-common_22.2-0ubuntu9_all.deb emacs22-el_22.2-0ubuntu9_all.deb &&
94 | sudo dpkg -i --force-depends emacs22-bin-common_22.2-0ubuntu9_i386.deb &&
95 | sudo dpkg -i emacs22_22.2-0ubuntu9_i386.deb emacs22-gtk_22.2-0ubuntu9_i386.deb &&
96 | sudo update-alternatives --set emacs22 /usr/bin/emacs22-gtk;
97 | fi
98 | - if [ "$EMACS" = 'emacs23' ]; then
99 | sudo apt-get -qq update &&
100 | sudo apt-get -qq -f install &&
101 | sudo apt-get -qq install emacs23-gtk emacs23-el;
102 | fi
103 | - if [ "$EMACS" = 'emacs24' ]; then
104 | sudo add-apt-repository -y ppa:cassou/emacs &&
105 | sudo apt-get -qq update &&
106 | sudo apt-get -qq -f install &&
107 | sudo apt-get -qq install emacs24 emacs24-el;
108 | fi
109 | - if [ "$EMACS" = 'emacs-snapshot' ]; then
110 | sudo add-apt-repository -y ppa:ubuntu-elisp/ppa &&
111 | sudo apt-get -qq update &&
112 | sudo apt-get -qq -f install &&
113 | sudo apt-get -qq install emacs-snapshot &&
114 | sudo apt-get -qq install emacs-snapshot-el;
115 | fi
116 |
117 | before_script:
118 | - if [ "$EMACS" = 'emacs-snapshot' ]; then
119 | make downloads-latest;
120 | else
121 | make downloads;
122 | fi
123 |
124 | ###
125 | ### the actual build/test command
126 | ###
127 |
128 | script:
129 | $EMACS --version && ( test "$EMACS" != "emacs22" && make test EMACS="$EMACS" || make test-batch EMACS="$EMACS" )
130 |
131 | ###
132 | ### settings
133 | ###
134 |
135 | notifications:
136 | email: false
137 |
138 | #
139 | # Emacs
140 | #
141 | # Local Variables:
142 | # indent-tabs-mode: nil
143 | # mangle-whitespace: t
144 | # require-final-newline: t
145 | # coding: utf-8
146 | # End:
147 | #
148 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | EMACS=emacs
2 | # EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
3 | # EMACS=/Applications/Emacs23.app/Contents/MacOS/Emacs
4 | # EMACS=/Applications/Aquamacs.app/Contents/MacOS/Aquamacs
5 | # EMACS=/Applications/Macmacs.app/Contents/MacOS/Emacs
6 | # EMACS=/usr/local/bin/emacs
7 | # EMACS=/opt/local/bin/emacs
8 | # EMACS=/usr/bin/emacs
9 |
10 | INTERACTIVE_EMACS=/usr/local/bin/emacs
11 | # can't find an OS X variant that works correctly for interactive tests:
12 | # INTERACTIVE_EMACS=open -a Emacs.app --new --args
13 | # INTERACTIVE_EMACS=/Applications/Emacs.app/Contents/MacOS/Emacs
14 | # INTERACTIVE_EMACS=/Applications/Emacs.app/Contents/MacOS/bin/emacs
15 |
16 | RESOLVED_EMACS=$(shell readlink `which $(EMACS)` || echo "$(EMACS)")
17 | RESOLVED_INTERACTIVE_EMACS=$(shell readlink `which "$(INTERACTIVE_EMACS)"` || echo "$(INTERACTIVE_EMACS)")
18 |
19 | EMACS_CLEAN=-Q
20 | EMACS_BATCH=$(EMACS_CLEAN) --batch
21 | # TESTS can be overridden to specify a subset of tests
22 | TESTS=
23 | WIKI_USERNAME=roland.walker
24 |
25 | CURL=curl --location --silent
26 | EDITOR=runemacs -no_wait
27 | WORK_DIR=$(shell pwd)
28 | PACKAGE_NAME=$(shell basename $(WORK_DIR))
29 | PACKAGE_VERSION=$(shell perl -ne 'print "$$1\n" if m{^;+ *Version: *(\S+)}' $(PACKAGE_NAME).el)
30 | AUTOLOADS_FILE=$(PACKAGE_NAME)-autoloads.el
31 | TRAVIS_FILE=.travis.yml
32 | TEST_DIR=ert-tests
33 | TEST_DEP_1=ert
34 | TEST_DEP_1_STABLE_URL=http://git.savannah.gnu.org/cgit/emacs.git/plain/lisp/emacs-lisp/ert.el?h=emacs-24.3
35 | TEST_DEP_1_LATEST_URL=http://git.savannah.gnu.org/cgit/emacs.git/plain/lisp/emacs-lisp/ert.el?h=master
36 | TEST_DEP_2=ignoramus
37 | TEST_DEP_2_STABLE_URL=https://raw.githubusercontent.com/rolandwalker/ignoramus/37536286eb1da6d7bb9590e039485c456fdfd245/ignoramus.el
38 | TEST_DEP_2_LATEST_URL=https://raw.githubusercontent.com/rolandwalker/ignoramus/master/ignoramus.el
39 |
40 | .PHONY : build dist not-dirty pkg-version downloads downloads-latest autoloads \
41 | test-autoloads test-travis test test-prep test-batch test-interactive \
42 | test-tests clean edit run-pristine run-pristine-local upload-github \
43 | upload-wiki upload-marmalade test-dep-1 test-dep-2 test-dep-3 test-dep-4 \
44 | test-dep-5 test-dep-6 test-dep-7 test-dep-8 test-dep-9
45 |
46 | build :
47 | $(RESOLVED_EMACS) $(EMACS_BATCH) --eval \
48 | "(progn \
49 | (setq byte-compile-error-on-warn t) \
50 | (batch-byte-compile))" *.el
51 |
52 | not-dirty :
53 | @git diff --quiet '$(PACKAGE_NAME).el' || \
54 | ( git --no-pager diff '$(PACKAGE_NAME).el'; \
55 | echo "Uncommitted edits - do a git stash"; \
56 | false )
57 |
58 | pkg-version :
59 | @test -n '$(PACKAGE_VERSION)' || \
60 | ( echo "No package version"; false )
61 |
62 | test-dep-1 :
63 | @cd '$(TEST_DIR)' && \
64 | $(RESOLVED_EMACS) $(EMACS_BATCH) -L . -L .. -l '$(TEST_DEP_1)' || \
65 | (echo "Can't load test dependency $(TEST_DEP_1).el, run 'make downloads' to fetch it" ; exit 1)
66 |
67 | test-dep-2 :
68 | @cd '$(TEST_DIR)' && \
69 | $(RESOLVED_EMACS) $(EMACS_BATCH) -L . -L .. --eval \
70 | "(progn \
71 | (setq package-load-list '(($(TEST_DEP_2) t))) \
72 | (when (fboundp 'package-initialize) \
73 | (package-initialize)) \
74 | (require '$(TEST_DEP_2)))" || \
75 | (echo "Can't load test dependency $(TEST_DEP_2).el, run 'make downloads' to fetch it" ; exit 1)
76 |
77 | downloads :
78 | $(CURL) '$(TEST_DEP_1_STABLE_URL)' > '$(TEST_DIR)/$(TEST_DEP_1).el'
79 | $(CURL) '$(TEST_DEP_2_STABLE_URL)' > '$(TEST_DIR)/$(TEST_DEP_2).el'
80 |
81 | downloads-latest :
82 | $(CURL) '$(TEST_DEP_1_LATEST_URL)' > '$(TEST_DIR)/$(TEST_DEP_1).el'
83 | $(CURL) '$(TEST_DEP_2_LATEST_URL)' > '$(TEST_DIR)/$(TEST_DEP_2).el'
84 |
85 | autoloads :
86 | $(RESOLVED_EMACS) $(EMACS_BATCH) --eval \
87 | "(progn \
88 | (setq generated-autoload-file \"$(WORK_DIR)/$(AUTOLOADS_FILE)\") \
89 | (update-directory-autoloads \"$(WORK_DIR)\"))"
90 |
91 | test-autoloads : autoloads
92 | @$(RESOLVED_EMACS) $(EMACS_BATCH) -L . -l './$(AUTOLOADS_FILE)' || \
93 | ( echo "failed to load autoloads: $(AUTOLOADS_FILE)" && false )
94 |
95 | test-travis :
96 | @if test -z "$$TRAVIS" && test -e '$(TRAVIS_FILE)'; then travis-lint '$(TRAVIS_FILE)'; fi
97 |
98 | test-tests :
99 | @perl -ne 'if (m/^\s*\(\s*ert-deftest\s*(\S+)/) {die "$$1 test name duplicated in $$ARGV\n" if $$dupes{$$1}++}' '$(TEST_DIR)/'*-test.el
100 |
101 | test-prep : build test-dep-1 test-autoloads test-travis test-tests
102 |
103 | test-batch :
104 | @cd '$(TEST_DIR)' && \
105 | (for test_lib in *-test.el; do \
106 | $(RESOLVED_EMACS) $(EMACS_BATCH) -L . -L .. -l cl \
107 | -l '$(TEST_DEP_1)' -l "$$test_lib" --eval \
108 | "(progn \
109 | (fset 'ert--print-backtrace 'ignore) \
110 | (ert-run-tests-batch-and-exit '(and \"$(TESTS)\" (not (tag :interactive)))))" || exit 1; \
111 | done)
112 |
113 | test-interactive : test-prep
114 | @cd '$(TEST_DIR)' && \
115 | (for test_lib in *-test.el; do \
116 | $(RESOLVED_INTERACTIVE_EMACS) $(EMACS_CLEAN) --eval \
117 | "(progn \
118 | (cd \"$(WORK_DIR)/$(TEST_DIR)\") \
119 | (setq dired-use-ls-dired nil) \
120 | (setq frame-title-format \"TEST SESSION $$test_lib\") \
121 | (setq enable-local-variables :safe))" \
122 | -L . -L .. -l cl -l '$(TEST_DEP_1)' -l "$$test_lib" \
123 | --visit "$$test_lib" --eval \
124 | "(progn \
125 | (when (> (length \"$(TESTS)\") 0) \
126 | (push \"\\\"$(TESTS)\\\"\" ert--selector-history)) \
127 | (setq buffer-read-only t) \
128 | (setq cursor-in-echo-area t) \
129 | (call-interactively 'ert-run-tests-interactively) \
130 | (ding) \
131 | (when (y-or-n-p \"PRESS Y TO QUIT THIS TEST SESSION\") \
132 | (with-current-buffer \"*ert*\" \
133 | (kill-emacs \
134 | (if (re-search-forward \"^Failed:[^\\n]+unexpected\" 500 t) 1 0)))))" || exit 1; \
135 | done)
136 |
137 | test : test-prep test-batch
138 |
139 | run-pristine :
140 | @cd '$(TEST_DIR)' && \
141 | $(RESOLVED_EMACS) $(EMACS_CLEAN) --eval \
142 | "(progn \
143 | (setq package-enable-at-startup nil) \
144 | (setq package-load-list nil) \
145 | (when (fboundp 'package-initialize) \
146 | (package-initialize)) \
147 | (cd \"$(WORK_DIR)/$(TEST_DIR)\") \
148 | (setq dired-use-ls-dired nil) \
149 | (setq frame-title-format \"PRISTINE SESSION $(PACKAGE_NAME)\") \
150 | (setq enable-local-variables :safe))" \
151 | -L .. -l '$(PACKAGE_NAME)' .
152 |
153 | run-pristine-local :
154 | @cd '$(TEST_DIR)' && \
155 | $(RESOLVED_EMACS) $(EMACS_CLEAN) --eval \
156 | "(progn \
157 | (cd \"$(WORK_DIR)/$(TEST_DIR)\") \
158 | (setq dired-use-ls-dired nil) \
159 | (setq frame-title-format \"PRISTINE-LOCAL SESSION $(PACKAGE_NAME)\") \
160 | (setq enable-local-variables :safe))" \
161 | -L . -L .. -l '$(PACKAGE_NAME)' .
162 |
163 | clean :
164 | @rm -f '$(AUTOLOADS_FILE)' *.elc *~ */*.elc */*~ .DS_Store */.DS_Store *.bak */*.bak && \
165 | cd '$(TEST_DIR)' && \
166 | rm -f './$(TEST_DEP_1).el' './$(TEST_DEP_2).el' './$(TEST_DEP_3).el' './$(TEST_DEP_4).el' './$(TEST_DEP_5a).el' \
167 | './$(TEST_DEP_5).el' './$(TEST_DEP_6).el' './$(TEST_DEP_7).el' './$(TEST_DEP_8).el' './$(TEST_DEP_9).el'
168 |
169 | edit :
170 | @$(EDITOR) `git ls-files`
171 |
172 | upload-github :
173 | @git push origin master
174 |
175 | upload-marmalade :
176 | @marmalade-upload roland.walker '$(PACKAGE_NAME).el'
177 |
178 | upload-wiki : not-dirty
179 | @$(RESOLVED_EMACS) $(EMACS_BATCH) --eval \
180 | "(progn \
181 | (setq package-load-list '((yaoddmuse t))) \
182 | (when (fboundp 'package-initialize) \
183 | (package-initialize)) \
184 | (require 'yaoddmuse) \
185 | (setq yaoddmuse-username \"$(WIKI_USERNAME)\") \
186 | (yaoddmuse-post-file \
187 | \"$(PACKAGE_NAME).el\" \
188 | yaoddmuse-default-wiki \
189 | \"$(PACKAGE_NAME).el\" \
190 | \"updated version\") \
191 | (sleep-for 5))"
192 |
--------------------------------------------------------------------------------
/README.markdown:
--------------------------------------------------------------------------------
1 | [](http://travis-ci.org/rolandwalker/hardhat)
2 |
3 | # Overview
4 |
5 | Protect against clobbering user-writable files in Emacs.
6 |
7 | * [Quickstart](#quickstart)
8 | * [Explanation](#explanation)
9 | * [See Also](#see-also)
10 | * [Notes](#notes)
11 | * [Compatibility and Requirements](#compatibility-and-requirements)
12 | * [Prior art](#prior-art)
13 | * [Bugs](#bugs)
14 |
15 | ## Quickstart
16 |
17 | ```elisp
18 | (require 'hardhat)
19 |
20 | (global-hardhat-mode 1)
21 |
22 | ;; now you are protected from editing:
23 | ;;
24 | ;; .git/index
25 | ;; ~/.emacs.d/elpa/hardhat-0.1.0/hardhat.el
26 | ;; ~/.emacs~
27 | ;;
28 | ;; and many others
29 | ```
30 |
31 | ## Explanation
32 |
33 | A recent unwholesome trend is for package managers to install files
34 | in locations such as `~/.cabal/`, `~/.rvm/`, or `~/.emacs.d/elpa/`.
35 | It is rarely meant for such files to be edited; doing so can cause
36 | data loss in some circumstances.
37 |
38 | In addition, many user-writable files created in the course of
39 | ordinary work should never be altered by a text editor, *eg* the
40 | database stored in a `.git` directory.
41 |
42 | `hardhat.el` provides an extra layer of protection in your work. If
43 | you visit a file which looks unsafe to edit, Emacs will make the
44 | buffer read-only -- even when the underlying file is writable.
45 |
46 | The read-only protection can be turned off for a buffer by the
47 | usual methods, or by toggling off buffer-local `hardhat-mode` via
48 | the lighter menu or
49 |
50 | M-x hardhat-mode RET
51 |
52 | If a buffer is not visiting a file, `hardhat-mode` has no effect.
53 | If the visited file is not writable by the user, `hardhat-mode`
54 | has no effect.
55 |
56 | To use hardhat, place the `hardhat.el` library somewhere
57 | Emacs can find it, and add the following to your `~/.emacs` file:
58 |
59 | ```elisp
60 | (require 'hardhat)
61 | (global-hardhat-mode 1)
62 | ```
63 |
64 | To inquire as to why hardhat has set or unset protection in
65 | a buffer, the following interactive command is provided
66 |
67 | hardhat-status
68 |
69 | but not bound to any key.
70 |
71 | ## See Also
72 |
73 | * M-x customize-group RET hardhat RET
74 |
75 | ## Notes
76 |
77 | `hardhat-mode` takes no action until the user attempts an
78 | interactive command in a buffer. This is (out of an abundance
79 | of caution) for compatibility: an Emacs Lisp library may freely
80 | open and write to a file protected by `hardhat-mode`, so long as
81 | it is done programatically.
82 |
83 | For any of the options settable in `customize`, rules making
84 | buffers "editable" override rules making buffers "protected".
85 |
86 | A Boolean file-local variable `hardhat-protect` is provided.
87 | When `hardhat-protect` is set to either t or nil, no other
88 | rules are consulted.
89 |
90 | Regular-expression matches are case-insensitive. A case-
91 | sensitive test can be implemented by adding custom function
92 | to eg `hardhat-buffer-protected-functions`.
93 |
94 | ## Compatibility and Requirements
95 |
96 | GNU Emacs version 25.1-devel : not tested
97 | GNU Emacs version 24.5 : not tested
98 | GNU Emacs version 24.4 : yes
99 | GNU Emacs version 24.3 : yes
100 | GNU Emacs version 23.3 : yes
101 | GNU Emacs version 22.2 : yes, with some limitations
102 | GNU Emacs version 21.x and lower : unknown
103 |
104 | Uses if present: [ignoramus.el](http://github.com/rolandwalker/ignoramus)
105 |
106 | ## Prior art
107 |
108 | * do-not-edit
109 |
110 | Kevin Ryde
111 |
112 | ## Bugs
113 |
114 | More exceptions are certainly needed in `hardhat-fullpath-editable-regexps`.
115 |
116 | Because Emacs can wedge if `file-truename` is called on a
117 | remote file (eg when using TRAMP), some filename tests used in
118 | hardhat are not precisely equivalent between local and remote
119 | files. You can change this behavior by setting
120 | `hardhat-use-unsafe-remote-truename` via `customize`. A better
121 | solution is to set `find-file-visit-truename` globally.
122 |
--------------------------------------------------------------------------------
/ert-tests/examples/CVS/bash-fc-0:
--------------------------------------------------------------------------------
1 | # empty file
2 |
--------------------------------------------------------------------------------
/ert-tests/examples/CVS/elisp_protpath_localnil.el:
--------------------------------------------------------------------------------
1 | ;; Local Variables:
2 | ;; hardhat-protect: nil
3 | ;; End:
4 |
--------------------------------------------------------------------------------
/ert-tests/examples/CVS/elisp_protpath_localt.el:
--------------------------------------------------------------------------------
1 | ;; Local Variables:
2 | ;; hardhat-protect: t
3 | ;; End:
4 |
--------------------------------------------------------------------------------
/ert-tests/examples/CVS/text_protpath.txt:
--------------------------------------------------------------------------------
1 | # empty file
2 |
--------------------------------------------------------------------------------
/ert-tests/examples/CVS/text_protpath_editpat.txt:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
--------------------------------------------------------------------------------
/ert-tests/examples/editpat-autoloads.el:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
3 | (defun tester nil
4 | t)
5 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_editpat.el:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
3 | (defun tester nil
4 | t)
5 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_editpat_localnil.el:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
3 | (defun tester nil
4 | t)
5 |
6 | ;; Local Variables:
7 | ;; hardhat-protect: nil
8 | ;; End:
9 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_editpat_localt.el:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
3 | (defun tester nil
4 | t)
5 |
6 | ;; Local Variables:
7 | ;; hardhat-protect: t
8 | ;; End:
9 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_editpat_readonlyfile.el:
--------------------------------------------------------------------------------
1 | ;; allow editing this file
2 |
3 | (defun tester nil
4 | t)
5 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_nopat.bak:
--------------------------------------------------------------------------------
1 | (defun tester nil
2 | t)
3 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_nopat.el:
--------------------------------------------------------------------------------
1 | (defun tester nil
2 | t)
3 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_protpat.el:
--------------------------------------------------------------------------------
1 | ;; DO NOT EDIT THIS FILE
2 |
3 | (defun tester nil
4 | t)
5 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_protpat_editpat.el:
--------------------------------------------------------------------------------
1 | ;; DO NOT EDIT THIS FILE
2 |
3 | ;; allow editing this file
4 |
5 | (defun tester nil
6 | t)
7 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_protpat_localnil.el:
--------------------------------------------------------------------------------
1 | ;; DO NOT EDIT THIS FILE
2 |
3 | (defun tester nil
4 | t)
5 |
6 | ;; Local Variables:
7 | ;; hardhat-protect: nil
8 | ;; End:
9 |
--------------------------------------------------------------------------------
/ert-tests/examples/elisp_protpat_localt.el:
--------------------------------------------------------------------------------
1 | ;; DO NOT EDIT THIS FILE
2 |
3 | (defun tester nil
4 | t)
5 |
6 | ;; Local Variables:
7 | ;; hardhat-protect: t
8 | ;; End:
9 |
--------------------------------------------------------------------------------
/ert-tests/examples/perl_endpat.pl:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/perl
2 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
3 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
4 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
5 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
6 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
7 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
8 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
9 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
10 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
11 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
12 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
13 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
14 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
15 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
16 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
17 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
18 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
19 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
20 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
21 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
22 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
23 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
24 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
25 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
26 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
27 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
28 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
29 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
30 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
31 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
32 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
33 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
34 | # protect me
35 |
--------------------------------------------------------------------------------
/ert-tests/examples/perl_endpat_semantic.pl:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/perl
2 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
3 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
4 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
5 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
6 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
7 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
8 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
9 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
10 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
11 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
12 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
13 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
14 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
15 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
16 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
17 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
18 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
19 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
20 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
21 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
22 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
23 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
24 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
25 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
26 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
27 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
28 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
29 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
30 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
31 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
32 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
33 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
34 | # protect me
35 |
36 | __DATA__
37 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
38 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
39 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
40 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
41 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
42 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
43 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
44 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
45 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
46 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
47 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
48 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
49 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
50 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
51 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
52 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
53 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
54 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
55 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
56 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
57 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
58 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
59 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
60 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
61 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
62 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
63 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
64 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
65 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
66 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
67 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
68 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
69 |
--------------------------------------------------------------------------------
/ert-tests/examples/perl_endpat_toofar.pl:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/perl
2 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
3 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
4 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
5 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
6 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
7 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
8 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
9 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
10 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
11 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
12 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
13 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
14 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
15 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
16 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
17 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
18 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
19 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
20 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
21 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
22 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
23 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
24 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
25 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
26 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
27 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
28 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
29 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
30 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
31 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
32 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
33 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
34 | # protect me
35 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
36 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
37 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
38 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
39 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
40 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
41 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
42 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
43 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
44 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
45 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
46 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
47 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
48 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
49 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
50 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
51 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
52 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
53 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
54 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
55 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
56 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
57 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
58 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
59 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
60 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
61 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
62 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
63 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
64 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
65 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
66 | # lakjsd flkajs dlfkj asldkjf lkasjd flkj asldkfj laksjd flkja sdlfkj laskdj flkasj dflkj asldkjf lajsd fl
67 |
--------------------------------------------------------------------------------
/ert-tests/examples/perl_modepat.pl:
--------------------------------------------------------------------------------
1 | # Changes made here will be lost when autosplit is run again
2 |
--------------------------------------------------------------------------------
/ert-tests/examples/protected-autoloads.el:
--------------------------------------------------------------------------------
1 | (defun tester nil
2 | t)
3 |
--------------------------------------------------------------------------------
/ert-tests/examples/shell-editpat.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # THIS IS A GENERATED FILE\
3 | #
4 |
--------------------------------------------------------------------------------
/ert-tests/examples/text_perlmodepat.txt:
--------------------------------------------------------------------------------
1 | # Changes made here will be lost when autosplit is run again
2 |
--------------------------------------------------------------------------------
/ert-tests/hardhat-test.el:
--------------------------------------------------------------------------------
1 |
2 | ;;; requires and setup
3 |
4 | (when load-file-name
5 | (setq package-enable-at-startup nil)
6 | (setq package-load-list '((ignoramus t)))
7 | (when (fboundp 'package-initialize)
8 | (package-initialize)))
9 |
10 | (require 'ignoramus)
11 | (require 'hardhat)
12 |
13 |
14 | ;;; working-directory
15 |
16 | (ert-deftest hardhat-aaa-working-directory-01 nil
17 | "Check that we are running from the ert-tests directory"
18 | (should
19 | (file-exists-p "./examples/elisp_nopat.el"))
20 | (should
21 | (string-match-p "/ert-tests/\\'" default-directory)))
22 |
23 |
24 | ;;; example files
25 |
26 | (ert-deftest hardhat-example-file-01 nil
27 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
28 | (find-file "./examples/elisp_nopat.el")
29 | (should-not
30 | (hardhat-buffer-included-p (current-buffer)))
31 | (should
32 | (equal nil
33 | hardhat-reasons))
34 | (kill-buffer (current-buffer))))
35 |
36 | (ert-deftest hardhat-example-file-02 nil
37 | "cover hardhat-protected-by-ignoramus"
38 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
39 | (find-file "./examples/elisp_nopat.bak")
40 | (should
41 | (hardhat-buffer-included-p (current-buffer)))
42 | (should
43 | (equal (list 'protected 'function 'hardhat-protected-by-ignoramus)
44 | hardhat-reasons))
45 | (kill-buffer (current-buffer))))
46 |
47 | (ert-deftest hardhat-example-file-03 nil
48 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
49 | (find-file "./examples/elisp_editpat.el")
50 | (should-not
51 | (hardhat-buffer-included-p (current-buffer)))
52 | (should
53 | (equal (list 'editable 'bof-content ";; allow editing this file")
54 | hardhat-reasons))
55 | (kill-buffer (current-buffer))))
56 |
57 | (ert-deftest hardhat-example-file-04 nil
58 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
59 | (find-file "./examples/elisp_editpat_localnil.el")
60 | (hardhat-local-variables-hook)
61 | (should-not
62 | (hardhat-buffer-included-p (current-buffer)))
63 | (should-not
64 | hardhat-mode)
65 | (should
66 | (equal (list 'editable 'file-local-variable nil)
67 | hardhat-reasons))
68 | (kill-buffer (current-buffer))))
69 |
70 | (ert-deftest hardhat-example-file-05 nil
71 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
72 | (find-file "./examples/elisp_editpat_localt.el")
73 | (hardhat-local-variables-hook)
74 | (should-not
75 | (hardhat-buffer-included-p (current-buffer)))
76 | (should
77 | hardhat-mode)
78 | (should
79 | (equal (list 'protected 'file-local-variable t)
80 | hardhat-reasons))
81 | (kill-buffer (current-buffer))))
82 |
83 | (ert-deftest hardhat-example-file-06 nil
84 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file"))
85 | (file "./examples/elisp_editpat_readonlyfile.el"))
86 | (should
87 | (file-exists-p file))
88 | (set-file-modes file #o444)
89 | (should-not
90 | (file-writable-p file))
91 | (find-file file)
92 | (should-not
93 | (hardhat-buffer-included-p (current-buffer)))
94 | (should
95 | (equal nil
96 | hardhat-reasons))
97 | (kill-buffer (current-buffer))))
98 |
99 | (ert-deftest hardhat-example-file-07 nil
100 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
101 | (find-file "./examples/elisp_protpat.el")
102 | (should
103 | (hardhat-buffer-included-p (current-buffer)))
104 | (should
105 | (equal (list 'protected 'bof-content "DO NOT EDIT")
106 | hardhat-reasons))
107 | (kill-buffer (current-buffer))))
108 |
109 | (ert-deftest hardhat-example-file-08 nil
110 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
111 | (find-file "./examples/elisp_protpat_editpat.el")
112 | (should-not
113 | (hardhat-buffer-included-p (current-buffer)))
114 | (should
115 | (equal (list 'editable 'bof-content ";; allow editing this file")
116 | hardhat-reasons))
117 | (kill-buffer (current-buffer))))
118 |
119 | (ert-deftest hardhat-example-file-09 nil
120 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
121 | (find-file "./examples/elisp_protpat_localnil.el")
122 | (hardhat-local-variables-hook)
123 | (should-not
124 | (hardhat-buffer-included-p (current-buffer)))
125 | (should-not
126 | hardhat-mode)
127 | (should
128 | (equal (list 'editable 'file-local-variable nil)
129 | hardhat-reasons))
130 | (kill-buffer (current-buffer))))
131 |
132 | (ert-deftest hardhat-example-file-10 nil
133 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
134 | (find-file "./examples/elisp_protpat_localt.el")
135 | (hardhat-local-variables-hook)
136 | (should-not
137 | (hardhat-buffer-included-p (current-buffer)))
138 | (should
139 | hardhat-mode)
140 | (should
141 | (equal (list 'protected 'file-local-variable t)
142 | hardhat-reasons))
143 | (kill-buffer (current-buffer))))
144 |
145 | (ert-deftest hardhat-example-file-11 nil
146 | (let ((hardhat-eof-content-protected-regexps '((perl-mode . "protect me")
147 | (cperl-mode . "protect me")))
148 | (hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
149 | (find-file "./examples/perl_endpat.pl")
150 | (should
151 | (hardhat-buffer-included-p (current-buffer)))
152 | (should
153 | (equal (list 'protected 'eof-content "protect me")
154 | hardhat-reasons))
155 | (kill-buffer (current-buffer))))
156 |
157 | (ert-deftest hardhat-example-file-12 nil
158 | "cover hardhat-protected-by-perl-semantic-eof"
159 | (let ((hardhat-eof-content-protected-regexps '((perl-mode . "protect me")
160 | (cperl-mode . "protect me")))
161 | (hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
162 | (find-file "./examples/perl_endpat_semantic.pl")
163 | (should
164 | (hardhat-buffer-included-p (current-buffer)))
165 | (should
166 | (equal (list 'protected 'function 'hardhat-protected-by-perl-semantic-eof)
167 | hardhat-reasons))
168 | (kill-buffer (current-buffer))))
169 |
170 | (ert-deftest hardhat-example-file-13 nil
171 | (let ((hardhat-eof-content-protected-regexps '((perl-mode . "protect me")
172 | (cperl-mode . "protect me")))
173 | (hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
174 | (find-file "./examples/perl_endpat_toofar.pl")
175 | (should-not
176 | (hardhat-buffer-included-p (current-buffer)))
177 | (should
178 | (equal nil
179 | hardhat-reasons))
180 | (kill-buffer (current-buffer))))
181 |
182 | (ert-deftest hardhat-example-file-14 nil
183 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
184 | (find-file "./examples/perl_modepat.pl")
185 | (should
186 | (hardhat-buffer-included-p (current-buffer)))
187 | (should
188 | (equal (list 'protected 'bof-content "# Changes made here will be lost when autosplit is run again")
189 | hardhat-reasons))
190 | (kill-buffer (current-buffer))))
191 |
192 | (ert-deftest hardhat-example-file-15 nil
193 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
194 | (find-file "./examples/text_perlmodepat.txt")
195 | (should-not
196 | (hardhat-buffer-included-p (current-buffer)))
197 | (should
198 | (equal nil
199 | hardhat-reasons))
200 | (kill-buffer (current-buffer))))
201 |
202 | (ert-deftest hardhat-example-file-16 nil
203 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file"))
204 | (hardhat-buffer-protected-functions nil))
205 | (find-file "./examples/protected-autoloads.el")
206 | (should
207 | (hardhat-buffer-included-p (current-buffer)))
208 | (should
209 | (equal (list 'protected 'basename "-autoloads.el")
210 | hardhat-reasons))
211 | (kill-buffer (current-buffer))))
212 |
213 | (ert-deftest hardhat-example-file-17 nil
214 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file"))
215 | (hardhat-buffer-protected-functions nil))
216 | (find-file "./examples/editpat-autoloads.el")
217 | (should-not
218 | (hardhat-buffer-included-p (current-buffer)))
219 | (should
220 | (equal (list 'editable 'bof-content ";; allow editing this file")
221 | hardhat-reasons))
222 | (kill-buffer (current-buffer))))
223 |
224 | (ert-deftest hardhat-example-file-18 nil
225 | (find-file "./examples/shell-editpat.sh")
226 | (should-not
227 | (hardhat-buffer-included-p (current-buffer)))
228 | (should
229 | (equal (list 'editable 'bof-content "THIS IS A GENERATED FILE\\")
230 | hardhat-reasons))
231 | (kill-buffer (current-buffer)))
232 |
233 | (ert-deftest hardhat-example-file-19 nil
234 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
235 | (find-file "./examples/CVS/text_protpath.txt")
236 | (should
237 | (hardhat-buffer-included-p (current-buffer)))
238 | (should
239 | (equal (list 'protected 'fullpath "/CVS/")
240 | hardhat-reasons))
241 | (kill-buffer (current-buffer))))
242 |
243 | (ert-deftest hardhat-example-file-20 nil
244 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
245 | (find-file "./examples/CVS/text_protpath_editpat.txt")
246 | (should-not
247 | (hardhat-buffer-included-p (current-buffer)))
248 | (should
249 | (equal (list 'editable 'bof-content ";; allow editing this file")
250 | hardhat-reasons))
251 | (kill-buffer (current-buffer))))
252 |
253 | (ert-deftest hardhat-example-file-21 nil
254 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
255 | (find-file "./examples/CVS/elisp_protpath_localnil.el")
256 | (hardhat-local-variables-hook)
257 | (should-not
258 | (hardhat-buffer-included-p (current-buffer)))
259 | (should-not
260 | hardhat-mode)
261 | (should
262 | (equal (list 'editable 'file-local-variable nil)
263 | hardhat-reasons))
264 | (kill-buffer (current-buffer))))
265 |
266 | (ert-deftest hardhat-example-file-22 nil
267 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
268 | (find-file "./examples/CVS/elisp_protpath_localt.el")
269 | (hardhat-local-variables-hook)
270 | (should-not
271 | (hardhat-buffer-included-p (current-buffer)))
272 | (should
273 | hardhat-mode)
274 | (should
275 | (equal (list 'protected 'file-local-variable t)
276 | hardhat-reasons))
277 | (kill-buffer (current-buffer))))
278 |
279 | (ert-deftest hardhat-example-file-23 nil
280 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
281 | (find-file "./examples/CVS/bash-fc-0")
282 | (should-not
283 | (hardhat-buffer-included-p (current-buffer)))
284 | (should
285 | (equal (list 'editable 'basename "bash-fc-0")
286 | hardhat-reasons))
287 | (kill-buffer (current-buffer))))
288 |
289 | (ert-deftest hardhat-example-file-24 nil
290 | "cover hardhat-protected-osx-homebrew"
291 | :expected-result (if (and (eq system-type 'darwin)
292 | (file-writable-p "/usr/local/README.md")) :passed :failed)
293 | (let ((hardhat-bof-content-editable-regexps '("^;+ *allow editing this file")))
294 | (find-file "/usr/local/README.md")
295 | (should
296 | (hardhat-buffer-included-p (current-buffer)))
297 | (should
298 | (equal (list 'protected 'function 'hardhat-protected-osx-homebrew)
299 | hardhat-reasons))
300 | (kill-buffer (current-buffer))))
301 |
302 |
303 | ;;; hardhat-customize-set-regexp (symbol value) -- todo
304 |
305 |
306 | ;;; hardhat-local-hook (&rest args) -- todo
307 |
308 |
309 | ;;; hardhat-global-hook (&rest args) -- todo
310 |
311 |
312 | ;;; hardhat-mode -- todo
313 |
314 |
315 | ;;
316 | ;; Emacs
317 | ;;
318 | ;; Local Variables:
319 | ;; indent-tabs-mode: nil
320 | ;; mangle-whitespace: t
321 | ;; require-final-newline: t
322 | ;; coding: utf-8
323 | ;; byte-compile-warnings: (not cl-functions)
324 | ;; End:
325 | ;;
326 |
327 | ;;; hardhat-test.el ends here
328 |
--------------------------------------------------------------------------------
/hardhat.el:
--------------------------------------------------------------------------------
1 | ;;; hardhat.el --- Protect against clobbering user-writable files -*- lexical-binding: t -*-
2 | ;;
3 | ;; Copyright (c) 2012-2015 Roland Walker
4 | ;;
5 | ;; Author: Roland Walker
6 | ;; Homepage: http://github.com/rolandwalker/hardhat
7 | ;; URL: http://raw.githubusercontent.com/rolandwalker/hardhat/master/hardhat.el
8 | ;; Version: 0.4.6
9 | ;; Last-Updated: 14 Apr 2016
10 | ;; EmacsWiki: Hardhat
11 | ;; Package-Requires: ((emacs "24.3") (ignoramus "0.7.0"))
12 | ;; Keywords: convenience
13 | ;;
14 | ;; Simplified BSD License
15 | ;;
16 | ;;; Commentary:
17 | ;;
18 | ;; Quickstart
19 | ;;
20 | ;; (require 'hardhat)
21 | ;;
22 | ;; (global-hardhat-mode 1)
23 | ;;
24 | ;; ;; now you are protected from editing:
25 | ;; ;;
26 | ;; ;; .git/index
27 | ;; ;; ~/.emacs.d/elpa/hardhat-0.1.0/hardhat.el
28 | ;; ;; ~/.emacs~
29 | ;; ;;
30 | ;; ;; and many others
31 | ;;
32 | ;; Explanation
33 | ;;
34 | ;; A recent unwholesome trend is for package managers to install files
35 | ;; in locations such as ~/.cabal/, ~/.rvm/, or ~/.emacs.d/elpa/. It
36 | ;; is rarely meant for such files to be edited; doing so can cause
37 | ;; data loss in some circumstances.
38 | ;;
39 | ;; In addition, many user-writable files created in the course of
40 | ;; ordinary work should never be altered by a text editor, eg the
41 | ;; database stored in a .git directory.
42 | ;;
43 | ;; Hardhat.el provides an extra layer of protection in your work. If
44 | ;; you visit a file which looks unsafe to edit, Emacs will make the
45 | ;; buffer read-only -- even when the underlying file is writable.
46 | ;;
47 | ;; The read-only protection can be turned off for a buffer by the
48 | ;; usual methods, or by toggling off buffer-local hardhat-mode via
49 | ;; the lighter menu or
50 | ;;
51 | ;; M-x hardhat-mode RET
52 | ;;
53 | ;; If a buffer is not visiting a file, `hardhat-mode' has no effect.
54 | ;; If the visited file is not writable by the user, `hardhat-mode'
55 | ;; has no effect.
56 | ;;
57 | ;; To use hardhat, place the hardhat.el library somewhere
58 | ;; Emacs can find it, and add the following to your ~/.emacs file:
59 | ;;
60 | ;; (require 'hardhat)
61 | ;; (global-hardhat-mode 1)
62 | ;;
63 | ;; To inquire as to why hardhat has set or unset protection in
64 | ;; a buffer, the following interactive command is provided
65 | ;;
66 | ;; `hardhat-status'
67 | ;;
68 | ;; but not bound to any key.
69 | ;;
70 | ;; See Also
71 | ;;
72 | ;; M-x customize-group RET hardhat RET
73 | ;;
74 | ;; Notes
75 | ;;
76 | ;; `hardhat-mode' takes no action until the user attempts an
77 | ;; interactive command in a buffer. This is (out of an abundance
78 | ;; of caution) for compatibility: an Emacs Lisp library may freely
79 | ;; open and write to a file protected by `hardhat-mode', so long as
80 | ;; it is done programatically.
81 | ;;
82 | ;; For any of the options settable in customize, rules making
83 | ;; buffers "editable" override rules making buffers "protected".
84 | ;;
85 | ;; A Boolean file-local variable `hardhat-protect' is provided.
86 | ;; When `hardhat-protect' is set to either t or nil, no other
87 | ;; rules are consulted.
88 | ;;
89 | ;; Regular-expression matches are case-insensitive. A case-
90 | ;; sensitive test can be implemented by adding custom function
91 | ;; to eg `hardhat-buffer-protected-functions'.
92 | ;;
93 | ;; Compatibility and Requirements
94 | ;;
95 | ;; GNU Emacs version 25.1-devel : not tested
96 | ;; GNU Emacs version 24.5 : not tested
97 | ;; GNU Emacs version 24.4 : yes
98 | ;; GNU Emacs version 24.3 : yes
99 | ;; GNU Emacs version 23.3 : yes
100 | ;; GNU Emacs version 22.2 : yes, with some limitations
101 | ;; GNU Emacs version 21.x and lower : unknown
102 | ;;
103 | ;; Uses if present: ignoramus.el
104 | ;;
105 | ;; Prior art
106 | ;;
107 | ;; do-not-edit.el
108 | ;; http://user42.tuxfamily.org/do-not-edit/index.html
109 | ;; Kevin Ryde
110 | ;;
111 | ;; Bugs
112 | ;;
113 | ;; More exceptions are certainly needed in `hardhat-fullpath-editable-regexps'
114 | ;;
115 | ;; Because Emacs can wedge if `file-truename' is called on a
116 | ;; remote file (eg when using TRAMP), some filename tests used in
117 | ;; hardhat are not precisely equivalent between local and remote
118 | ;; files. You can change this behavior by setting
119 | ;; `hardhat-use-unsafe-remote-truename' via customize. A better
120 | ;; solution is to set `find-file-visit-truename' globally.
121 | ;;
122 | ;; TODO
123 | ;;
124 | ;;; License
125 | ;;
126 | ;; Simplified BSD License:
127 | ;;
128 | ;; Redistribution and use in source and binary forms, with or
129 | ;; without modification, are permitted provided that the following
130 | ;; conditions are met:
131 | ;;
132 | ;; 1. Redistributions of source code must retain the above
133 | ;; copyright notice, this list of conditions and the following
134 | ;; disclaimer.
135 | ;;
136 | ;; 2. Redistributions in binary form must reproduce the above
137 | ;; copyright notice, this list of conditions and the following
138 | ;; disclaimer in the documentation and/or other materials
139 | ;; provided with the distribution.
140 | ;;
141 | ;; This software is provided by Roland Walker "AS IS" and any express
142 | ;; or implied warranties, including, but not limited to, the implied
143 | ;; warranties of merchantability and fitness for a particular
144 | ;; purpose are disclaimed. In no event shall Roland Walker or
145 | ;; contributors be liable for any direct, indirect, incidental,
146 | ;; special, exemplary, or consequential damages (including, but not
147 | ;; limited to, procurement of substitute goods or services; loss of
148 | ;; use, data, or profits; or business interruption) however caused
149 | ;; and on any theory of liability, whether in contract, strict
150 | ;; liability, or tort (including negligence or otherwise) arising in
151 | ;; any way out of the use of this software, even if advised of the
152 | ;; possibility of such damage.
153 | ;;
154 | ;; The views and conclusions contained in the software and
155 | ;; documentation are those of the authors and should not be
156 | ;; interpreted as representing official policies, either expressed
157 | ;; or implied, of Roland Walker.
158 | ;;
159 | ;;; Code:
160 | ;;
161 |
162 | ;;; requirements
163 |
164 | ;; for callf, setf, callf2, assert, remove-if-not
165 | (require 'cl-lib)
166 |
167 | (require 'ignoramus nil t)
168 |
169 | ;;; declarations
170 |
171 | (eval-when-compile
172 | (defvar ert--running-tests))
173 |
174 | ;;; set-function for customize
175 |
176 | (defvar hardhat-computed-regexps (make-hash-table :test 'eq)
177 | "Per-mode cache for regexps computed from defcustom settings.")
178 |
179 | ;;;###autoload
180 | (defun hardhat-customize-set-regexp (symbol value)
181 | "Set function which clears the computed regexp cache.
182 |
183 | SYMBOL and VALUE are passed to `custom-set-default'."
184 | (custom-set-default symbol value)
185 | (setq hardhat-computed-regexps (make-hash-table :test 'eq)))
186 |
187 | ;;; customizable variables
188 |
189 | ;;;###autoload
190 | (defgroup hardhat nil
191 | "Protect against clobbering user-writable files."
192 | :version "0.4.6"
193 | :link '(emacs-commentary-link :tag "Commentary" "hardhat")
194 | :link '(url-link :tag "GitHub" "http://github.com/rolandwalker/hardhat")
195 | :link '(url-link :tag "EmacsWiki" "http://emacswiki.org/emacs/Hardhat")
196 | :prefix "hardhat-"
197 | :group 'convenience)
198 |
199 | (defcustom hardhat-mode-lighter " hhat"
200 | "This string appears in the mode-line when `hardhat-mode' is active.
201 |
202 | Set to nil or the empty string to disable the mode-line
203 | lighter for `hardhat-mode'."
204 | :type 'string
205 | :group 'hardhat)
206 | (put 'hardhat-mode-lighter 'risky-local-variable t)
207 |
208 | (defcustom hardhat-less-feedback nil
209 | "Give less echo area feedback."
210 | :type 'boolean
211 | :group 'hardhat)
212 |
213 | (defcustom hardhat-bof-content-bound 250
214 | "How far from the start to search for regexps in content.
215 |
216 | See `hardhat-bof-content-protected-regexps' and `hardhat-bof-content-editable-regexps'."
217 | :type 'integer
218 | :group 'hardhat)
219 |
220 | (defcustom hardhat-eof-content-bound 250
221 | "How far from the end to search for regexps in content.
222 |
223 | See `hardhat-eof-content-protected-regexps' and `hardhat-eof-content-editable-regexps'."
224 | :type 'integer
225 | :group 'hardhat)
226 |
227 | (defcustom hardhat-use-unsafe-remote-truename nil
228 | "Unconditionally use `file-truename' on remote files.
229 |
230 | This makes certain checks more accurate, but can wedge Emacs if
231 | your connection to a remote host is lost."
232 | :type 'boolean
233 | :group 'hardhat)
234 |
235 | ;;;###autoload
236 | (defgroup hardhat-protect nil
237 | "Rules for activating `hardhat-mode' protection in a buffer."
238 | :group 'hardhat)
239 |
240 | (defcustom hardhat-bof-content-protected-regexps '(
241 | (emacs-lisp-mode . "\\`;;;;[^\n]*--- automatically extracted\\>")
242 | (perl-mode . "^# Changes made here will be lost when autosplit is run again\\>")
243 | (cperl-mode . "^# Changes made here will be lost when autosplit is run again\\>")
244 | "\\"
245 | "\\"
246 | "\\"
247 | "\\"
248 | "\\"
249 | "\\"
250 | "\\`;+ *Emacs Bookmark Format Version [0-9]"
251 | "^;+ *-+ smex-history -+"
252 | "^;+ *EIEIO PERSISTENT OBJECT\\>"
253 | "^;+ *Tramp connection history\\>"
254 | )
255 | "Protect buffer from editing if these patterns match near beginning-of-file.
256 |
257 | Patterns can be specified on a per-mode basis using a cons cell
258 | in the form \(mode . regexp\). The customization interface can
259 | arrange this for you automatically.
260 |
261 | All patterns are case-insensitive."
262 | :set 'hardhat-customize-set-regexp
263 | :type '(repeat (choice (regexp :tag "Regular expression")
264 | (cons :tag "Mode-specific regular expression"
265 | (symbol :tag "Mode")
266 | (regexp :tag "Mode-specific regular expression"))))
267 | :group 'hardhat-protect)
268 |
269 | (defcustom hardhat-eof-content-protected-regexps '(
270 | )
271 | "Protect buffer from editing if these patterns match near end-of-file.
272 |
273 | Patterns can be specified on a per-mode basis using a cons cell
274 | in the form \(mode . regexp\). The customization interface can
275 | arrange this for you automatically.
276 |
277 | All patterns are case-insensitive."
278 | :set 'hardhat-customize-set-regexp
279 | :type '(repeat (choice (regexp :tag "Regular expression")
280 | (cons :tag "Mode-specific regular expression"
281 | (symbol :tag "Mode")
282 | (regexp :tag "Mode-specific regular expression"))))
283 | :group 'hardhat-protect)
284 |
285 | (defcustom hardhat-basename-protected-regexps '(
286 | "~\\'"
287 | "\\.lock\\'"
288 | "\\.ix\\'"
289 | "\\`test\\.out\\'"
290 | "-autoloads\\.el\\'"
291 | "\\`Desktop\\.ini\\'"
292 | "\\`META\\.yml\\'"
293 | "\\`MYMETA\\.yml\\'"
294 | "\\`TAGS\\'"
295 | "\\`Thumbs\\.db\\'"
296 | "\\`\\.dropbox\\'"
297 | "\\`\\.dropbox\\.cache\\'"
298 | "\\`\\.emacs\\.desktop\\'"
299 | "\\`\\.emacs\\.desktop\\.lock\\'"
300 | "\\.orig\\'"
301 | "\\.rej\\'"
302 | )
303 | "Protect buffer from editing if these patterns match filename (sans directory).
304 |
305 | Patterns can be specified on a per-mode basis using a cons cell
306 | in the form \(mode . regexp\). The customization interface can
307 | arrange this for you automatically.
308 |
309 | All patterns are case-insensitive."
310 | :set 'hardhat-customize-set-regexp
311 | :type '(repeat (choice (regexp :tag "Regular expression")
312 | (cons :tag "Mode-specific regular expression"
313 | (symbol :tag "Mode")
314 | (regexp :tag "Mode-specific regular expression"))))
315 | :group 'hardhat-protect)
316 |
317 | (defcustom hardhat-fullpath-protected-regexps '(
318 | "~/\\.emacs\\.d/elpa/"
319 | "~/\\.cpan/"
320 | "~/\\.cabal/"
321 | "~/perl5/perlbrew/"
322 | "~/\\.npm/"
323 | "~/\\.virtualenv/"
324 | "~/\\.virthualenv/"
325 | "~/\\.rvm/"
326 | "/[._]build/"
327 | "/\\.bzr/"
328 | "/\\.coverage/"
329 | "/\\.git/"
330 | "/\\.hg/"
331 | "/\\.rspec/"
332 | "/\\.sass-cache/"
333 | "/\\.svn/"
334 | "/_MTN/"
335 | "/_darcs/"
336 | "/CVS/"
337 | "/pm_to_blib/"
338 | "/RCS/"
339 | "/SCCS/"
340 | "/blib/"
341 | "/test_output/"
342 | "~/\\.emacs\\.d/\\.cask/"
343 | "~/\\.cask/"
344 | )
345 | "Protect buffer from editing if these patterns match into full path to file.
346 |
347 | A leading \"~/\" expression will be expanded with the user's home
348 | directory. The path this pattern is tested against will be fully
349 | expanded.
350 |
351 | Patterns can be specified on a per-mode basis using a cons cell
352 | in the form \(mode . regexp\). The customization interface can
353 | arrange this for you automatically.
354 |
355 | All patterns are case-insensitive."
356 | :set 'hardhat-customize-set-regexp
357 | :type '(repeat (choice (regexp :tag "Regular expression")
358 | (cons :tag "Mode-specific regular expression"
359 | (symbol :tag "Mode")
360 | (regexp :tag "Mode-specific regular expression"))))
361 | :group 'hardhat-protect)
362 |
363 | (defcustom hardhat-buffer-protected-functions '(
364 | hardhat-protected-by-ignoramus
365 | hardhat-protected-osx-homebrew
366 | (perl-mode . hardhat-protected-by-perl-semantic-eof)
367 | (cperl-mode . hardhat-protected-by-perl-semantic-eof)
368 | )
369 | "Protect buffer from editing if any listed function evaluates non-nil.
370 |
371 | Each function should take two arguments in the form \(buffer
372 | &optional file\).
373 |
374 | Functions can be specified on a per-mode basis using a cons cell
375 | in the form \(mode . function\). The customization interface can
376 | arrange this for you automatically.
377 |
378 | Set this value to nil to disable."
379 | :type '(repeat (choice (function :tag "Function")
380 | (cons :tag "Mode-specific function"
381 | (symbol :tag "Mode")
382 | (regexp :tag "Mode-specific function"))))
383 | :group 'hardhat-protect)
384 |
385 | ;;;###autoload
386 | (defgroup hardhat-editable nil
387 | "Rules for de-activating `hardhat-mode', making text editable."
388 | :group 'hardhat)
389 |
390 | (defcustom hardhat-bof-content-editable-regexps '(
391 | (sh-mode . "\\ " hardhat-lighter-menu-mouse-button)) menu-map)
543 | map) "Keymap for the global `hardhat-mode' lighter.")
544 |
545 | ;;; macros
546 |
547 | (defmacro hardhat-called-interactively-p (&optional kind)
548 | "A backward-compatible version of `called-interactively-p'.
549 |
550 | Optional KIND is as documented at `called-interactively-p'
551 | in GNU Emacs 24.1 or higher."
552 | (cond
553 | ((not (fboundp 'called-interactively-p))
554 | '(interactive-p))
555 | ((condition-case nil
556 | (progn (called-interactively-p 'any) t)
557 | (error nil))
558 | `(called-interactively-p ,kind))
559 | (t
560 | '(called-interactively-p))))
561 |
562 | ;;; compatibility functions
563 |
564 | (unless (fboundp 'string-match-p)
565 | ;; added in 23.x
566 | (defun string-match-p (regexp string &optional start)
567 | "Same as `string-match' except this function does not change the match data."
568 | (let ((inhibit-changing-match-data t))
569 | (string-match regexp string start))))
570 |
571 | (unless (fboundp 'with-demoted-errors)
572 | ;; added in 23.x
573 | (defmacro with-demoted-errors (&rest body)
574 | "Run BODY and demote any errors to simple messages."
575 | (declare (debug t) (indent 0))
576 | (let ((err (make-symbol "err")))
577 | `(condition-case ,err
578 | (progn ,@body)
579 | (error (message "Error: %S" ,err) nil)))))
580 |
581 | ;;; utility functions
582 |
583 | (defun hardhat--propertize-lighter ()
584 | "Add properties to the `hardhat-mode' lighter."
585 | (when (and (stringp hardhat-mode-lighter)
586 | (> (length hardhat-mode-lighter) 0))
587 | (cl-callf propertize hardhat-mode-lighter
588 | hardhat-lighter-keymap-property hardhat-lighter-map
589 | 'help-echo (format "Hardhat: mouse-%s menu" hardhat-lighter-menu-mouse-button))))
590 |
591 | (defun hardhat-compute-regexps ()
592 | "Compute regexps from customizable values."
593 | (unless (gethash major-mode hardhat-computed-regexps)
594 | (puthash major-mode (make-hash-table :test 'eq) hardhat-computed-regexps)
595 | (save-match-data
596 | ;; read variables
597 | (dolist (directive hardhat-directives)
598 | (puthash directive (make-hash-table :test 'eq)
599 | (gethash major-mode hardhat-computed-regexps))
600 | (dolist (criterion (remq 'function hardhat-criteria))
601 | (let ((cust-sym (intern (format "hardhat-%s-%s-regexps" criterion directive)))
602 | (computed nil))
603 | (dolist (elt (symbol-value cust-sym))
604 | (cond
605 | ((null elt)
606 | t)
607 | ((stringp elt)
608 | (push elt computed))
609 | ((and (consp elt)
610 | (stringp (cdr elt))
611 | (symbolp (car elt)))
612 | (when (eq major-mode (car elt))
613 | (push (cdr elt) computed)))
614 | (t
615 | (error "Bad element %s in %s" elt cust-sym)))
616 | ;; tilde expansion
617 | (when (and (eq criterion 'fullpath)
618 | (string-match "\\`\\(~[^~/]*/\\)" (car computed)))
619 | (setf (car computed)
620 | (replace-match
621 | (regexp-quote (expand-file-name (match-string 1 (car computed))))
622 | nil
623 | 'literal
624 | (car computed)
625 | 1))))
626 | ;; sanity check
627 | (when computed
628 | (cl-callf2 cl-remove-if-not 'stringp computed)
629 | (cl-callf2 cl-remove-if-not #'(lambda (str-val)
630 | (> (length str-val) 0)) computed))
631 | ;; construct and store regexp
632 | (when computed
633 | (setq computed (format "\\(%s\\)" (mapconcat 'identity computed "\\|")))
634 | (puthash criterion computed (gethash directive (gethash major-mode hardhat-computed-regexps))))))))))
635 |
636 | (defun hardhat-safe-file-truename (filename)
637 | "Return the truename of FILENAME if it is safe to do so.
638 |
639 | `file-truename' can wedge infinitely for remote files in the case
640 | that the connection to the remote host is lost.
641 |
642 | This is a safer wrapper which employs `file-truename' for local
643 | files only. For remote files, the following is used
644 |
645 | (file-remote-p FILENAME 'localname)
646 |
647 | which, though *not* equivalent to `file-truename', is better than
648 | a wedge.
649 |
650 | This behavior can be overridden by setting customizable variable
651 | `hardhat-use-unsafe-remote-truename' to a non-nil value."
652 | (or (and (not hardhat-use-unsafe-remote-truename)
653 | (file-remote-p filename 'localname))
654 | (file-truename filename)))
655 |
656 | ;;; functions which may de/activate protection
657 |
658 | (defun hardhat-dispatch-generic-check (buf directive criterion &optional file basename)
659 | "Return non-nil if hardhat check is true for BUF.
660 |
661 | DIRECTIVE may be a symbol listed in `hardhat-directives'.
662 |
663 | CRITERION may be a symbol listed in `hardhat-criteria'.
664 |
665 | Optional FILE and BASENAME override the file and basename
666 | associated with BUF for the purpose of optimization."
667 | (when (and (or (not noninteractive) ert--running-tests)
668 | (bufferp buf)
669 | (or file basename (buffer-file-name buf)))
670 | (cl-assert (memq directive hardhat-directives) nil "Bad DIRECTIVE")
671 | (cl-assert (memq criterion hardhat-criteria) nil "Bad CRITERION")
672 | (with-current-buffer buf
673 | (cond
674 | ((eq criterion 'function)
675 | (catch 'hit
676 | (dolist (cell (symbol-value (intern (format "hardhat-buffer-%s-functions" directive))))
677 | (let ((test (cond
678 | ((symbolp cell)
679 | cell)
680 | ((and (consp cell)
681 | (eq major-mode (car cell)))
682 | (cdr cell)))))
683 | (when (and (fboundp test)
684 | (with-demoted-errors (funcall test buf file)))
685 | (throw 'hit test))))))
686 | (t
687 | (hardhat-compute-regexps)
688 | (let ((case-fold-search t)
689 | (regexp (ignore-errors
690 | (gethash criterion
691 | (gethash directive
692 | (gethash major-mode hardhat-computed-regexps))))))
693 | (when (and (stringp regexp)
694 | (> (length regexp) 0))
695 | (save-excursion
696 | (save-restriction
697 | (save-match-data
698 | (unless hardhat--respect-narrowing
699 | (widen))
700 | (cond
701 | ((eq criterion 'basename)
702 | (cl-callf or basename (file-name-nondirectory (hardhat-safe-file-truename (buffer-file-name buf))))
703 | (when (string-match regexp basename)
704 | (match-string 1 basename)))
705 | ((eq criterion 'fullpath)
706 | (cl-callf or file (hardhat-safe-file-truename (buffer-file-name buf)))
707 | (when (string-match regexp file)
708 | (match-string 1 file)))
709 | ((eq criterion 'bof-content)
710 | (goto-char (point-min))
711 | (when (re-search-forward regexp hardhat-bof-content-bound t)
712 | (match-string-no-properties 1)))
713 | ((eq criterion 'eof-content)
714 | (goto-char (point-max))
715 | (when (re-search-backward regexp (- (point-max) hardhat-eof-content-bound) t)
716 | (match-string-no-properties 1)))
717 | (t
718 | (error "Bad DIRECTIVE")))))))))))))
719 |
720 | (defun hardhat-protected-by-ignoramus (buf &optional file)
721 | "Return non-nil if `ignoramus-boring-p' is true for file associated with BUF.
722 |
723 | Optional FILE overrides the file associated with BUF for the
724 | purpose of optimization.
725 |
726 | If ignoramus.el is not present, fails silently.
727 |
728 | This function may be used as a member of `hardhat-buffer-protected-functions'."
729 | (when (and (fboundp 'ignoramus-boring-p)
730 | (bufferp buf))
731 | (cl-callf or file (hardhat-safe-file-truename (expand-file-name (buffer-file-name buf))))
732 | (when (ignoramus-boring-p file)
733 | buf)))
734 |
735 | (defun hardhat-dispatch-perl-check (buf directive &optional file)
736 | "Dispatch check for perl semantic eof functions on BUF.
737 |
738 | DIRECTIVE may be a symbol listed in `hardhat-directives'.
739 |
740 | Optional FILE overrides the file associated with BUF for the
741 | purpose of optimization.
742 |
743 | See `hardhat-editable-by-perl-semantic-eof' and
744 | `hardhat-protected-by-perl-semantic-eof'"
745 | (with-current-buffer buf
746 | (when (and (or (not noninteractive) ert--running-tests)
747 | (bufferp buf)
748 | (or file (buffer-file-name buf)))
749 | (save-excursion
750 | (save-restriction
751 | (save-match-data
752 | (widen)
753 | (goto-char (point-min))
754 | (when (let ((case-fold-search nil))
755 | (search-forward-regexp "^__\\(?:DATA\\|END\\)__$" nil t))
756 | (narrow-to-region (point-min) (line-beginning-position))
757 | (let ((hardhat--respect-narrowing t))
758 | (hardhat-dispatch-generic-check buf directive 'eof-content file)))))))))
759 |
760 | (defun hardhat-protected-by-perl-semantic-eof (buf &optional file)
761 | "Return non-nil if protection regexps match near end of code in BUF.
762 |
763 | `hardhat-eof-content-protected-regexps' are tested above a
764 | __DATA__ or __END__ marker, which marks the end of code
765 | in a Perl file.
766 |
767 | Optional FILE overrides the file associated with BUF for the
768 | purpose of optimization.
769 |
770 | This function may be used as a member of `hardhat-buffer-protected-functions'."
771 | (hardhat-dispatch-perl-check buf 'protected file))
772 |
773 | (defun hardhat-editable-by-perl-semantic-eof (buf &optional file)
774 | "Return non-nil if editable regexps match near end of code in BUF.
775 |
776 | `hardhat-eof-content-editable-regexps' are tested above a
777 | __DATA__ or __END__ marker, which marks the end of code
778 | in a Perl file.
779 |
780 | Optional FILE overrides the file associated with BUF for the
781 | purpose of optimization.
782 |
783 | This function may be used as a member of `hardhat-buffer-editable-functions'."
784 | (hardhat-dispatch-perl-check buf 'editable file))
785 |
786 | (defun hardhat-protected-osx-homebrew (buf &optional file)
787 | "Return non-nil if BUF is visiting a Homebrew file on OS X.
788 |
789 | The Homebrew project \(http://mxcl.github.com/homebrew/\)
790 | encourages the installation of user-writable files under
791 | /usr/local/.
792 |
793 | Optional FILE overrides the file associated with BUF for the
794 | purpose of optimization."
795 | (when (eq system-type 'darwin)
796 | (cl-callf or file (hardhat-safe-file-truename (expand-file-name (buffer-file-name buf))))
797 | (when (and (string-match-p "\\`/usr/local/" file)
798 | (file-writable-p file))
799 | buf)))
800 |
801 | (defun hardhat-buffer-included-p (buf)
802 | "Return BUF if `global-hardhat-mode' should enable `hardhat-mode' in BUF."
803 | (when (and (or (not noninteractive) ert--running-tests)
804 | (bufferp buf)
805 | (buffer-file-name buf)
806 | (not buffer-read-only)
807 | (not buffer-file-read-only))
808 | (let* ((file (hardhat-safe-file-truename (expand-file-name (buffer-file-name buf))))
809 | (basename (file-name-nondirectory file))
810 | (answer nil))
811 | (when (fboundp 'ignoramus-compute-common-regexps)
812 | (ignoramus-compute-common-regexps))
813 | (unless (eq 'file-local-variable (cadr hardhat-reasons))
814 | (setq hardhat-reasons (catch 'hardhat
815 | (dolist (directive hardhat-directives)
816 | (dolist (criterion hardhat-criteria)
817 | (when (setq answer (hardhat-dispatch-generic-check buf directive criterion file basename))
818 | (throw 'hardhat (list directive criterion answer)))))))
819 | (when (eq 'protected (car hardhat-reasons))
820 | buf)))))
821 |
822 | ;;; minor-mode definition
823 |
824 | ;;;###autoload
825 | (define-minor-mode hardhat-mode
826 | "Turn on `hardhat-mode'.
827 |
828 | When called interactively with no prefix argument this command
829 | toggles the mode. With a prefix argument, it enables the mode
830 | if the argument is positive and otherwise disables the mode.
831 |
832 | When called from Lisp, this command enables the mode if the
833 | argument is omitted or nil, and toggles the mode if the argument
834 | is 'toggle."
835 | :group 'hardhat
836 | (cond
837 | (hardhat-mode
838 | (cond
839 | ((and (or (not noninteractive) ert--running-tests)
840 | (buffer-file-name (current-buffer))
841 | (not buffer-read-only)
842 | (not buffer-file-read-only))
843 | (when (and (stringp hardhat-mode-lighter)
844 | (not (local-variable-p 'hardhat-mode-lighter)))
845 | (make-local-variable 'hardhat-mode-lighter)
846 | (cl-callf concat hardhat-mode-lighter "[on]")
847 | (hardhat--propertize-lighter))
848 | (add-hook 'pre-command-hook 'hardhat-local-hook nil t)
849 | (when (hardhat-called-interactively-p 'interactive)
850 | (setq hardhat-reasons (list 'protected 'user-interactive 'hardhat-mode-toggled))
851 | (when (not hardhat-less-feedback)
852 | (message "hardhat-mode enabled"))))
853 | (t
854 | (when (and (hardhat-called-interactively-p 'interactive)
855 | (not hardhat-less-feedback))
856 | (message "hardhat-mode cannot be enabled in this buffer"))
857 | (setq hardhat-mode nil))))
858 | (t
859 | (when (stringp (default-value 'hardhat-mode-lighter))
860 | (kill-local-variable 'hardhat-mode-lighter))
861 | (cond
862 | ((hardhat-called-interactively-p 'interactive)
863 | (setq hardhat-reasons (list 'editable 'user-interactive 'hardhat-mode-toggled)))
864 | ((eq (car hardhat-reasons) 'protected)
865 | (setq hardhat-reasons nil)))
866 | (remove-hook 'pre-command-hook 'hardhat-local-hook t)
867 | (unless buffer-file-read-only
868 | (setq buffer-read-only nil))
869 | (when (and (hardhat-called-interactively-p 'interactive)
870 | (not hardhat-less-feedback))
871 | (message "hardhat-mode disabled")))))
872 |
873 | ;;; global minor-mode definition
874 |
875 | (defun hardhat-maybe-turn-on (&optional arg)
876 | "Activate `hardhat-mode' in a buffer if appropriate.
877 |
878 | The buffer must be file-associated to be considered. The pathname
879 | of the associated file is tested according to
880 |
881 | `hardhat-basename-protected-regexps'
882 | `hardhat-fullpath-protected-regexps'
883 |
884 | The content of the buffer is tested according to
885 |
886 | `hardhat-bof-content-protected-regexps'
887 | `hardhat-eof-content-protected-regexps'
888 |
889 | In addition, the buffer is tested according to the functions in
890 |
891 | `hardhat-buffer-protected-functions'
892 | `hardhat-buffer-editable-functions'
893 |
894 | If called with a negative ARG, deactivate `hardhat-mode' in the buffer."
895 | (cl-callf or arg 1)
896 | (when (or (< arg 0)
897 | (hardhat-buffer-included-p (current-buffer)))
898 | (hardhat-mode arg)))
899 |
900 | ;; The global mode function is written by hand, avoiding the macro
901 | ;; `define-globalized-minor-mode', so as to confine checking to
902 | ;; specific hooks. Otherwise checks would fire much more often.
903 | ;;;###autoload
904 | (defun global-hardhat-mode (&optional arg)
905 | "Toggle Hardhat mode in all buffers.
906 | With prefix ARG, enable Global-Hardhat mode if ARG is positive;
907 | otherwise, disable it. If called from Lisp, enable the mode if
908 | ARG is omitted or nil."
909 | (interactive "P")
910 | (cond
911 | ((hardhat-called-interactively-p 'interactive)
912 | (cl-callf or arg (if global-hardhat-mode -1 1)))
913 | (t
914 | (cl-callf or arg 1)))
915 | (cl-callf prefix-numeric-value arg)
916 | (cond
917 | ((< arg 0)
918 | (remove-hook 'find-file-hook 'hardhat-global-hook)
919 | (remove-hook 'after-change-major-mode-hook 'hardhat-global-hook)
920 | (remove-hook 'hack-local-variables-hook 'hardhat-local-variables-hook)
921 | (setq global-hardhat-mode nil)
922 | (dolist (buf (cl-remove-if-not #'(lambda (buf)
923 | (ignore-errors
924 | (buffer-local-value 'hardhat-mode buf)))
925 | (buffer-list)))
926 | (with-current-buffer buf
927 | (hardhat-mode -1)))
928 | (when (and (hardhat-called-interactively-p 'interactive)
929 | (not hardhat-less-feedback))
930 | (message "Global-Hardhat mode disabled")))
931 | (t
932 | (hardhat--propertize-lighter)
933 | (unless (assoc 'global-hardhat-mode minor-mode-alist)
934 | (push '(global-hardhat-mode hardhat-mode-lighter) minor-mode-alist))
935 | (dolist (buf (buffer-list))
936 | (with-current-buffer buf
937 | (hardhat-maybe-turn-on)))
938 | (add-hook 'find-file-hook 'hardhat-global-hook)
939 | (add-hook 'after-change-major-mode-hook 'hardhat-global-hook)
940 | (add-hook 'hack-local-variables-hook 'hardhat-local-variables-hook)
941 | (setq global-hardhat-mode t)
942 | (when (and (hardhat-called-interactively-p 'interactive)
943 | (not hardhat-less-feedback))
944 | (message "Global-Hardhat mode enabled")))))
945 |
946 | (defun global-hardhat-mode--setter (sym val)
947 | (cl-assert (eq sym 'global-hardhat-mode) nil
948 | "This function should only be called on `global-hardhat-mode'.")
949 | (global-hardhat-mode (if val 1 -1))
950 | (set-default sym val))
951 |
952 | (defcustom global-hardhat-mode nil
953 | "Non-nil if Global-Hardhat mode is enabled.
954 | See the command `global-hardhat-mode' for a description of this minor mode.
955 | Setting this variable directly does not take effect;
956 | either customize it (see the info node `Easy Customization')
957 | or call the function `global-hardhat-mode'."
958 | :group 'hardhat
959 | :type 'boolean
960 | :set #'global-hardhat-mode--setter)
961 |
962 | ;;; hooks
963 |
964 | (defun hardhat-local-variables-hook (&rest _ignored)
965 | "Hook to check a buffer for `hardhat-mode' protection based on file-locals.
966 |
967 | The file-local variable `hardhat-protect' is tested.
968 |
969 | Any arguments are ignored."
970 | (when (and (or (not noninteractive) ert--running-tests)
971 | (buffer-file-name (current-buffer))
972 | (not buffer-read-only)
973 | (not buffer-file-read-only))
974 | (cond
975 | ((not (local-variable-p 'hardhat-protect))
976 | t)
977 | ((eq hardhat-protect t)
978 | (setq hardhat-reasons (list 'protected 'file-local-variable t))
979 | (hardhat-mode 1))
980 | ((eq hardhat-protect nil)
981 | (setq hardhat-reasons (list 'editable 'file-local-variable nil))
982 | (hardhat-mode -1)))))
983 |
984 | (defun hardhat-local-hook (&rest _ignored)
985 | "Hook to check a buffer for `hardhat-mode' protection.
986 |
987 | Any arguments are ignored."
988 | (remove-hook 'pre-command-hook 'hardhat-local-hook t)
989 | (when (and hardhat-mode
990 | (or (not noninteractive) ert--running-tests)
991 | (buffer-file-name (current-buffer))
992 | (not buffer-read-only)
993 | (not buffer-file-read-only))
994 | (setq buffer-read-only t)
995 | (unless hardhat-less-feedback
996 | (message "hardhat: protecting %s from edits because: %s test matched \"%s\""
997 | (current-buffer)
998 | (nth 1 hardhat-reasons)
999 | (nth 2 hardhat-reasons)))))
1000 |
1001 | (defun hardhat-global-hook (&rest _ignored)
1002 | "Hook to check all buffers for `hardhat-mode' protection.
1003 |
1004 | Any arguments are ignored."
1005 | (when global-hardhat-mode
1006 | (with-demoted-errors
1007 | (hardhat-maybe-turn-on))))
1008 |
1009 | ;;; interactive commands
1010 |
1011 | ;;;###autoload
1012 | (defun hardhat-status ()
1013 | "Echo the `hardhat-mode' status of the current buffer."
1014 | (interactive)
1015 | (cond
1016 | (hardhat-reasons
1017 | (message "Hardhat marked this buffer %s, because: %s test matched \"%s\""
1018 | (car hardhat-reasons)
1019 | (nth 1 hardhat-reasons)
1020 | (nth 2 hardhat-reasons)))
1021 | ((and (not hardhat-reasons)
1022 | hardhat-mode)
1023 | (message "Bug: hardhat-mode is on but results are not available"))
1024 | ((not hardhat-reasons)
1025 | (message "Hardhat-mode did not mark this buffer"))
1026 | ((not global-hardhat-mode)
1027 | (message "Hardhat-mode is off globally"))
1028 | (t
1029 | (message "No status information available."))))
1030 |
1031 | (provide 'hardhat)
1032 |
1033 | ;;
1034 | ;; Emacs
1035 | ;;
1036 | ;; Local Variables:
1037 | ;; indent-tabs-mode: nil
1038 | ;; mangle-whitespace: t
1039 | ;; require-final-newline: t
1040 | ;; coding: utf-8
1041 | ;; byte-compile-warnings: (not cl-functions redefine)
1042 | ;; End:
1043 | ;;
1044 | ;; LocalWords: Hardhat ARGS alist devel Ryde callf defcustom hhat
1045 | ;; LocalWords: autosplit EIEIO smex virtualenv perlbrew virthualenv
1046 | ;; LocalWords: setf cpan rspec darcs elpa
1047 | ;;
1048 |
1049 | ;;; hardhat.el ends here
1050 |
--------------------------------------------------------------------------------