番茄鱼片汤
- 1~2大片巴沙鱼略挤水分,切7~10毫米厚片.
- 鱼片加盐鸡精料酒抓一下,加蛋清少量土豆粉搅拌(上浆后鱼片受热表面糊化,锁住鱼片水分)
- 4~6个番茄底部十字刀,开水烫一分钟,去皮,切块,块不要太小有口感
- 葱姜下锅炸出香味,很快(10秒)小火,以免葱变焦难看.
- 番茄出汁后加水,水滚后加适量盐,味精,胡椒粉(可略多点,有辣味),12克(三勺)白醋,和西红柿综合变成果香醋
- 加鱼片盖锅焖一分钟,洒香菜和葱丝出锅
视频: 龙利鱼腌制诀窍是什么?需要注意什么?老师傅详细讲解番茄鱼片 视频备份
附录,
- 我加入了豆腐,和少量冷冻绿色蔬菜,调个色,增加营养.
Use CI to improve the quality of emacs distribution
In Better Emacs package development workflow, I proved that running Emacs compiler in CI can give huge boost to package quality.
The same workflow can apply to emacs distributions. But designing a CI workflow for the distribution is much more challenging.
For example, my .emacs.d uses about 300 packages. In CI pipeline, those packages are automatically downloaded and compiled. If compiling errors/warnings from those third party packages are not ignored, the CI will always fail.
There are also many other engineering issues. I struggled for five hours and finally got satisfying solution. Now anyone can use my solution to set up same CI pipeline in ten minutes.
Makefile is in "~/.emacs.d", it's still simple,
EMACS ?= emacs
RM = @rm -rf
EMACS_BATCH_OPTS = --batch -Q --debug-init
install: clean
@$(EMACS) $(EMACS_BATCH_OPTS) -l init.el
compile: install
@$(EMACS) $(EMACS_BATCH_OPTS) -l init.el -l tests/my-byte-compile.el 2>&1 | grep -Ev "init-(hydra|evil).el:.*Warning: docstring wider than 80 characters|an obsolete" | grep -E "[0-9]: ([Ee]rror|[Ww]arning):" && exit 1 || exit 0
You can run make compile && echo good || echo bad
in shell to test the pipeline locally. Please note I use grep -v things-to-ignore
to ignore some warnings. The warnings are from anonymous functions created by third packages (hydra, general.el, …).
The final missing piece is "~/.emacs.d/tests/my-byte-compile.el",
(require 'find-lisp)
(require 'scroll-bar)
(require 'ivy)
(require 'counsel)
(require 'w3m)
(require 'ibuffer)
(require 'org)
(require 'diff-mode)
(require 'cliphist)
(require 'eacl)
(require 'tramp)
(require 'dired)
(require 'shellcop)
(require 'counsel-etags)
(require 'typewriter-mode)
(require 'pomodoro)
(require 'emms)
(require 'emms-playlist-mode)
(require 'gnus)
(require 'gnus-sum)
(require 'gnus-msg)
(require 'gnus-topic)
(require 'magit)
(require 'magit-refs)
(require 'gnus-art)
(require 'git-link)
(require 'ace-window)
(require 'js2-mode)
(require 'yasnippet)
(require 'ediff)
(require 'company)
(require 'evil-nerd-commenter)
(require 'git-timemachine)
(require 'pyim)
(require 'cal-china-x)
(require 'wucuo)
(require 'langtool)
(require 'web-mode)
(require 'bbdb)
(require 'gmail2bbdb)
(require 'org-mime)
(require 'pdf-tools)
(require 'recentf)
(require 'bookmark)
(require 'find-file-in-project)
(require 'flymake)
(require 'elec-pair)
(require 'elpy)
(require 'rjsx-mode)
(require 'simple-httpd)
(require 'vc)
(require 'sdcv)
(require 'wgrep)
(require 'mybigword)
(require 'yaml-mode)
(require 'octave)
(require 'undo-fu)
(require 'wc-mode)
(require 'exec-path-from-shell)
(require 'dictionary)
(require 'company-ispell)
(require 'company-ctags)
(require 'lsp-mode)
(let ((files (find-lisp-find-files-internal
"."
(lambda (file dir)
(and (not (file-directory-p (expand-file-name file dir)))
(string-match "\\.el$" file)
(not (member file '(".dir-locals.el"
"package-quickstart.el"
"company-statistics-cache.el"
"custom-set-variables.el"
"early-init.el")))))
(lambda (dir parent)
(member dir '("lisp"))))))
(dolist (file files)
;; (message "file=%s" file)
(byte-compile-file file)))
;;; my-byte-compile.el ends here
As you can see,
- I need add lots of
require
statement to make compiling succeed on Emacs 26, 27, 28 - Some "*.el" files generated by Emacs and 3rd party packages need be ignored
- My emacs setup code is only in "lisp" directory
That's it.
You can visit https://github.com/redguardtoo/emacs.d for a real world example.
BTW, you can find init-no-byte-compile.el where there are a few lines setup code the compiler will ignore. It's bad practice but sometimes there is no other way.
"init-no-byte-compile.el" is like,
;; -*- coding: utf-8; lexical-binding: t; -*-
;; blah blah
;; Local Variables:
;; no-byte-compile: t
;; End:
Better Emacs package development workflow
The Emacs Lisp syntax error should be automatically detected by CI (Continuous Integration).
Syntax errors could be a bit difficult to locate. For example, developers might use Emacs 28+ only APIs to develop packages running on Emacs 26.
Here is howto.
- Step 1, create a file
my-byte-compile.el
in the directory "tests/",
(require 'find-lisp)
(let ((files (find-lisp-find-files-internal
"."
(lambda (file dir)
(and (not (file-directory-p (expand-file-name file dir)))
(string-match "\\.el$" file)
(not (string-match "\\.dir-locals\\.el$" file))))
(lambda (dir parent)
(not (or (member dir '("." ".." ".git" ".svn" "deps" "tests"))
(file-symlink-p (expand-file-name dir parent))))))))
(dolist (file files)
(byte-compile-file file)))
- Step 2, insert below command line into the project's Makefile,
compile:
emacs --batch -Q -L . -l my-package-main-entry.el -l tests/my-byte-compile.el 2>&1 | grep -E "([Ee]rror|[Ww]arning):" && exit 1 || exit 0
DONE! Now Gitlab/Github could use command line make compile
in their CI pipeline.
Screenshot of a tricky bug of evil-matchit detected by this new workflow.
BTW, I also tried elint
, but it's not as reliable as byte-compile
.
Content of my-elint.el
,
(require 'elint)
(let ((elint-directory-skip-re "\\(\\.dir-locals\\|ldefs-boot\\|loaddefs\\)\\.el\\'"))
(elint-directory "."))
Here is link to the Makefile from my real world project.
I use below command lines to compile and test the project locally.
EMACS=~/myemacs/26.3/bin/emacs make compile # compile only
EMACS=~/myemacs/26.3/bin/emacs make test # compile and run unit test
Configure EMMS (Emacs Multi-Media System) for Multimedia Keyboard
Emacs server need be started first.
I use emacsclient
to execute emms commands in the emacs server.
Key bindings setup in ~/.i3/config
for i3 window manager,
# music player client (mpc, emms ...)
bindsym XF86Search exec --no-startup-id ~/bin/music-player-client show
bindsym XF86Tools exec --no-startup-id ~/bin/music-player-client random
bindsym XF86AudioStop exec --no-startup-id ~/bin/music-player-client toggle
bindsym XF86AudioPause exec --no-startup-id ~/bin/music-player-client toggle
bindsym XF86AudioNext exec --no-startup-id ~/bin/music-player-client next
bindsym XF86AudioPrev exec --no-startup-id ~/bin/music-player-client prev
Content of ~/bin/music-player-client
,
#!/bin/bash
# use mpc&mpd or emacsclient&emms to play music
if [ -z "$1" ]; then
echo "Usage: music-player-client pre|next|toggle|random|show"
exit 1
fi
# Please uninstall mpc&mpd if using emms
if command -v mpc &> /dev/null; then
case $1 in
prev )
mpc prev
;;
next )
mpc next
;;
toggle )
mpc toggle
;;
esac
elif command -v emacsclient &> /dev/null; then
case $1 in
prev )
emacsclient --eval '(emms-previous)'
;;
next )
emacsclient --eval '(emms-next)'
;;
toggle )
emacsclient --eval '(emms-pause)'
;;
random )
emacsclient --eval '(progn (emms-shuffle) (emms-next))'
;;
show )
# program like dunst can show the notification
notify-send "$(emacsclient --eval '(file-name-base (emms-show))')"
;;
esac
fi
I usually run M-x emms-play-directory-tree
to play music. My emms setup,
(with-eval-after-load 'emms
;; minimum setup is more robust
(emms-minimalistic)
(setq emms-player-list '(emms-player-mplayer
emms-player-vlc)))
Screen shot of running ~/bin/music-player-client show
,
Integrate delta into git
Delta is a syntax-highlighting pager for git, diff, and grep output.
Set up is as simple as copying its sample setup.
I wrote a shell script my-pager
which can use both less
and delta
as pager,
#!/bin/bash
# @see https://stackoverflow.com/questions/19408649/pipe-input-into-a-script
if [ -x "$HOME/.cargo/bin/delta" ]; then
cat | $HOME/.cargo/bin/delta "$@"
else
cat | less -F -X
fi
Here is my extra delta setup in ~/.gitconfig
(Delta reads settings from ~/.gitconfig
),
[core]
pager = ~/bin/my-pager
[interactive]
diffFilter = ~/bin/my-pager --color-only
[merge]
conflictstyle = diff3
[diff]
colorMoved = default
[delta "default"]
file-decoration-style= blue box
hunk-header-decoration-style = purple ol
[delta]
features = default
navigate = true # use n and N to move between diff sections
Screenshot,
Emacs 28.1 on Debian Linux
As a happy Emacs 27 user on Debian Linux, I plan to use both Emacs 28.1 and Emacs 27 and gradually migrate from Emacs 27 to Emacs 28.
So I installed Emacs 28.1 without X Window System Support (emacs-nox) and it only runs in daemon mode.
Here are the steps,
- Compare PKGBUILD of emacs-nox 27 and PKGBUILD of emacs-nativecomp 28 to get the difference of build script (I was more familiar with Arch Linux. You can use Gentoo Linux's website to collect information)
- The only missing third party package is
libgccjit
. Runsudo apt install libgccjit-12-dev
to install it - Download Emacs 28.1 source code, run below command in shell,
cd ~/Downloads/emacs-28.1 && mkdir -p ~/myemacs/28.1 && rm -rf ~/myemacs/28.1/* && ./configure CFLAGS=-no-pie --prefix=~/myemacs/28.1 --without-x --without-sound --with-modules --with-native-compilation --without-compress-install && make && make install
- After installation, run "~/myemacs/28.1/bin/emacs" and Emacs will compile the packages automatically (I watched a few youtube videos until the compilation finished)
- Create "~/.config/systemd/user/emacs.service" with below content ("/home/cb" is my HOME directory),
[Unit]
Description=Emacs text editor
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/
[Service]
Type=forking
ExecStart=/home/cb/myemacs/28.1/bin/emacs -Q --daemon -l "/home/cb/.emacs.d/init.el" --eval "(progn (require 'server) (server-start))"
ExecStop=emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure
[Install]
WantedBy=default.target
- Run
systemctl --user restart emacs.service
in shell - Done! Run
emacsclient
to enjoy Emacs 28.1.
2.1. disable "idle loader" in server mode
I use "idle loader" in my Emacs distribution. Obviously it need be disabled in server mode.
Here is the code,
(defvar my-disable-idle-timer (daemonp)
"If not nil, Function passed to `my-run-with-idle-timer' is run immediately.")
(defun my-run-with-idle-timer (seconds func)
"After SECONDS, run function FUNC once."
(cond
(my-disable-idle-timer
(funcall func))
(t
(run-with-idle-timer seconds nil func))))
2.2. Shell script to install Emacs
You could Use below script "install-emacs.sh" to install Emacs,
#!/bin/sh
[ -z "$EMACS_VERSION" ] && echo "Usage: EMACS_VERSION=25.1 install-emacs.sh or EMACS_VERSION=snapshot install-emacs.sh" && exit 1
[ -z "$EMACS_URL" ] && EMACS_URL="http://mirror.aarnet.edu.au/pub/gnu/emacs/"
# I've assign 12G memory to /tmp as ramdisk
[ -z "$EMACS_TMP" ] && EMACS_TMP="/tmp"
if [ "$EMACS_VERSION" != "snapshot" ]; then
echo "curl $EMACS_URL/emacs-$EMACS_VERSION.tar.gz"
curl $EMACS_URL/emacs-$EMACS_VERSION.tar.gz | tar xvz -C $EMACS_TMP
fi
# @see http://wiki.gentoo.org/wiki/Project:Emacs/GNU_Emacs_developer_guide
# @see http://packages.gentoo.org/package/app-editors/emacs for info on Gentoo Linux
# --without-gtk and --without-gtk3 is optional
echo "Installing Emacs ..."
if [ "$EMACS_VERSION" = "snapshot" ]; then
cd $HOME/projs/emacs && mkdir -p $HOME/myemacs/snapshot && rm -rf $HOME/myemacs/snapshot/* && ./autogen.sh && ./configure CFLAGS=-no-pie --prefix=$HOME/myemacs/snapshot --without-x --without-dbus --without-sound --with-gnutls=no && make && make install
echo "Emacs snapshot was installed!"
elif [ "$EMACS_VERSION" = "28.1" ]; then
cd $EMACS_TMP/emacs-$EMACS_VERSION && mkdir -p $HOME/myemacs/$EMACS_VERSION && rm -rf $HOME/myemacs/$EMACS_VERSION/* && ./configure CFLAGS=-no-pie --prefix=$HOME/myemacs/$EMACS_VERSION --without-x --without-sound --with-modules --with-native-compilation --without-compress-install && make && make install
else
cd $EMACS_TMP/emacs-$EMACS_VERSION && mkdir -p $HOME/myemacs/$EMACS_VERSION && rm -rf $HOME/myemacs/$EMACS_VERSION/* && ./configure CFLAGS=-no-pie --prefix=$HOME/myemacs/$EMACS_VERSION --without-x --without-sound --with-modules && make && make install
rm -rf $EMACS_TMP/emacs-$EMACS_VERSION
echo "Emacs $EMACS_VERSION was installed!"
fi
Start teamviewer on i3wm
See yveslec's analysis.
So the solution is just one liner in shell.
ssh -X 127.0.0.1 "DISPLAY=:0.0 teamviewer"
Here is my shell script "~/bin/sshx-teamviewer.sh" with a bit optimization,
#!/bin/sh
# Run "cat ~/.ssh/id_rsa.pubkey >> ~/.ssh/authorized_keys" to
# avoid inputting ssh login password
ssh -X -C 127.0.0.1 "DISPLAY=:0.0 teamviewer"
蒜苔炒蛋
要点,
- 蒜苔老的头掐掉, 开水焯一下后放入冷水,从中间撕成两半,切成四公分的段.
- 滚刀切葱段备用
- 炒蛋核桃块大小, 三分盐
- 油热后加葱和少许海鲜酱油.炒几下后加入蒜苔加盐花椒油翻炒
- 加蛋翻炒几下,略勾芡
注: 没有花椒油,所以我在油温较高时和葱段一起加入少许花椒粒,利用油温爆出花椒香味.
Set up vmtouch systemd service
"/etc/default/vmtouch" on Debian Testing,
# Change to yes to enable running vmtouch as a daemon
ENABLE_VMTOUCH=yes
# User and group to run as
VMTOUCH_USER_GROUP=cb:cb
# Whitespace separated list of files and directories for vmtouch to operate on
VMTOUCH_FILES="/home/cb/.emacs.d/lisp /home/cb/.emacs.d/elpa /home/cb/.emacs.d/site-lisp /home/cb/.mozilla/firefox/linux.default/*.sqlite /home/cb/.mozilla/firefox/linux.default/*.json"
# Options to pass to vmtouch itself. See vmtouch(8).
VMTOUCH_OPTIONS="-q -t"
Run sudo systemctl restart vmtouch
to restart the service.
"home/cb.emacs.d" is not touched because the package elpy will create a sub-directory "elpy" there. This sub-directory is huge. It contains many python libraries.