Skip to content

xuchunyang/dotfiles

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 

Repository files navigation

My Dotfiles in Org mode

Table of Contents

Meta

How to use this file?

  • To extract dotfiles (such as ~~/.bash_profile~) from this file, type C-c C-v t (org-babel-tangle) in Emacs.
  • To propagate changes in dotfiles (such as ~~/.bash_profile~) to this file, type M-x org-babel-detangle in Emacs.

Safer org-babel-tangle

Use the following command instead of org-babel-tangle to avoid overriding exist files. Notes that

  • it doesn’t respect :tangle-mode if the exiting file has different mode bits with :tangle-mode.
  • it might not work with remote file
(defun chunyang-org-babel-tangle (&optional arg target-file lang)
  "Like `org-babel-tangle' but don't override without permission."
  (declare (interactive-only org-babel-tangle))
  (interactive "P")
  (require 'ob-tangle)
  (require 'seq)
  (require 'cl-lib)
  (save-some-buffers)
  (let* ((tmpdir (let ((dir "/tmp/org-babel-tangle/"))
                   (or (file-exists-p dir) (make-directory dir))
                   dir))
         (mkbak (lambda (filename)
                  (expand-file-name
                   (replace-regexp-in-string "/" "!" (expand-file-name filename))
                   tmpdir)))
         (diffp (lambda (file-a file-b)
                  (/= 0 (call-process diff-command nil nil nil (expand-file-name file-a) file-b))))
         (swap (lambda (file-a file-b)
                 (let ((tmp (make-temp-name tmpdir)))
                   (copy-file file-a tmp t t t t)
                   (copy-file file-b file-a t t t t)
                   (copy-file tmp file-b t t t t))))
         deleted-files
         tangled-files
         (advice (define-advice delete-file (:around (old-fun filename &rest args) dont-delete)
                   (push filename deleted-files)
                   (copy-file filename (funcall mkbak filename) t t t t)
                   (apply old-fun filename args))))
    (unwind-protect
        (progn
          (setq tangled-files (org-babel-tangle arg target-file lang)
                deleted-files (nreverse deleted-files))
          (cl-loop for f in (seq-intersection deleted-files tangled-files)
                   for bak = (funcall mkbak f)
                   do
                   (funcall swap f bak)
                   (if (funcall diffp f bak)
                       (with-current-buffer (find-file-noselect f)
                         (message "Diff %s..." f)
                         (delete-region (point-min) (point-max))
                         (insert-file-contents bak))
                     (message "Skip %s..." f))
                   finally (save-some-buffers)))
      (advice-remove 'delete-file advice))))

Resources

Passwords

To view and edit these passwords, type M-x org-encrypt-entries.

During org-babel-tangle, it might be too annoying by asking for which key to use for encryption each time, use the following work-around to bypass it.

(require 'org-crypt)
(setq org-crypt-key "mail@xuchunyang.me")
(define-advice org-babel-tangle (:around (old-fun &rest r) shutup-epa-file)
  "Shut up epa-file.

`epa-file' will prompt for which key to use for encryption each
time if `epa-file-encrypt-to' is not set locally, however it looks like
local variables embedded in comment will not applied during org-tangle."
  (with-current-buffer (current-buffer)
    (cl-assert (eq major-mode 'org-mode))
    (let (before-save-hook return)
      (org-decrypt-entries)
      (save-buffer)
      (define-advice write-region (:before (&rest r) set-epa-file-encrypt-to)
        (setq-local epa-file-encrypt-to org-crypt-key))
      (unwind-protect
          (setq return (apply old-fun r))
        (advice-remove 'write-region #'write-region@set-epa-file-encrypt-to))
      (org-encrypt-entries)
      (save-buffer)
      return)))

~/.authinfo.gpg

-----BEGIN PGP MESSAGE----- Version: GnuPG v2

hQIMA+LcwErZWE+CARAAkDKQp7aAUKRDjy3cRYyG+FfVZCSBWG4yYz41kXa51mfV Qd21dUflyoCxnT1XizaXhzHnuIXEShxXzdJOUyTD8aL1Bc2GexZUs/jWZiZpGESq nuYvfNTeOUbXQW3Ub8Q4NngjR+xoOrupt64DVYPaFi5LsQeDYDHdoUHszjLuilCF 1pkkwowOBKrIxpRbznNts+4dD6TGdFyfIlowcds9PoNKWV6iFzqARmgVkKvyAv54 F7neoaMbIcdbymj+euR/abE4pTH0Su/mHmm1oat9vh9RWFlH4RF1rrsJgjXkxX0F NWmPJgb9thYVEY7Ooijj+10Pd1NGWpNCE9+3HUsVKONDMW/PvX29Ve4QFqIdMmte fqFlE/SVBAkdMLmVB9y53lcZxrpE22LVsv4GQrzPw5K77AnO8sWzxEd8k/ijqJco Jvox/jOm0XaZO2bUa7KUnz1J1l/aDvnfHw/iWeg25S5/86sU3QXXbN2heuHq46NL b0GkCb06EL2Xq/b3BSDoJXY57BuROl2FQXhBxPNYzmjKKbEL4qQ98j49ny2hWtSd gud9IDxIVwqU1pfKSQ2eUm9kBzYWzhbKa8zHcHpYr4GnLoeK6tdZclvcmThqbOu8 pcoW4e4ouTxGLmH2E91XACrSV1AUcm1hKrAaozsStlP+o6WJuCj9h8AQJVG/3MDS wFUBbA/dWHGZl4ZXIq6JqRRPqSqA9JzxpA/xJCLy+USav7U7G9lABDbSR0GUeSI+ dlnSjFHa01pIkgrb26rWThYnGVBeEJPQyqp7rwfDX2nLX2AZA/EErMeNQCCaAzFk PI5hTOkFME3G00wyWnczBTbfVjXUWbBYfqtJLYpN12ZvNG0z2sy4TWQb3YWcSNIa dyxXsmGyIXYWCUpfh21qqCPm+KxeVg6CmXPgESmUWb31Y3aC5YvmR2ABYyTCqqby 6XlsI00xj9YeTK5xmqchSXcjHdHWUGAq9IEVSgL3hp9ET33r1l42zd3aHJqmiaFm xmMzK1KWgt5jJYKKz1snAgCCFdGq3fx6Dh4fcIv40HwTa/yDGvVV =PH15 -----END PGP MESSAGE-----

Bash

Meta

学习 Bash

变量(全局本地)、判断、控制结构、函数。

learn/sh at master · javier-lopez/learn

Resources

Style Guides

Guides

Tools

~~/.bashrc~ vs ~~/.bash_profile~

Don’t use ~/.bashrc to keep configuration, use ~/.bash_profile instead.

# The variable PS1 is unset in non-interactive shells:
# [[https://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html][Bash Reference Manual: Is this Shell Interactive?]]
if [ -z "$PS1" ]; then
    # This shell is not interactive
    source ~/.path
else
    # This shell is interactive
    source ~/.bash_profile
fi

OS detection

function is_mac () {
    [[ "$OSTYPE" =~ ^darwin ]]
}

function is_gnu_linux () {
    [[ "$OSTYPE" == linux-gnu ]]
}

Helper

function source_maybe () {
    local file="$1"
    [ -r "$file" ] && [ -f "$file" ] && source "$file"
}

Startup

# Add `~/bin` to the `$PATH`
export PATH="$HOME/bin:$PATH"

# Load the shell dotfiles, and then some:
# * ~/.path can be used to extend `$PATH`.
# * ~/.extra can be used for other settings you don’t want to commit.
for file in ~/.{path,bash_prompt,exports,aliases,functions,extra}; do
    source_maybe "$file"
done
unset file

$PATH in ~/.path

Here’s an example ~~/.path~ file that adds /usr/local/bin to the $PATH:

export PATH="/usr/local/bin:$PATH"

Prompt

# Looks like "~$ " in $HOME ("~" is in blue)
PS1="\[\e[34m\]\w\[\e[m\]\\$ "

Other Environment variables in ~/.exports

# Make Emacs the default editor.
export EDITOR='emacsclient'
export VISUAL='emacsclient'

# Enable support of searching Chinese for Notmuch
export XAPIAN_CJK_NGRAM=1

Aliases in ~/.aliases

# Detect which `ls` flavor is in use
if ls --color > /dev/null 2>&1; then # GNU `ls`
    colorflag="--color=auto"
    export LS_COLORS='no=00:fi=00:di=01;31:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.ogg=01;35:*.mp3=01;35:*.wav=01;35:'
else # macOS `ls`
    colorflag="-G"
    export LSCOLORS='BxBxhxDxfxhxhxhxhxcxcx'
fi

# List all files colorized in long format
alias l="ls -lF ${colorflag}"

# List all files colorized in long format, including dot files
alias la="ls -laF ${colorflag}"

# List only directories
alias lsd="ls -lF ${colorflag} | grep --color=never '^d'"

# Always use color output for `ls`
alias ls="command ls ${colorflag}"

# Enable aliases to be sudo’ed
alias sudo='sudo '

# Stopwatch
alias timer='echo "Timer started. Stop with Ctrl-D." && date && time cat && date'

# Reload the shell (i.e. invoke as a login shell)
alias reload="exec $SHELL -l"

# Print each PATH entry on a separate line
alias path='echo -e ${PATH//:/\\n}'

# Use color with Grep
alias grep="command grep --color=auto"

# Cat with syntax highlight
alias e2ansi-cat="$HOME/src/e2ansi/bin/e2ansi-cat"

Completion

# Add tab completion for many Bash commands (MacPorts)
if is_mac && [ -f /opt/local/etc/profile.d/bash_completion.sh ]; then
    . /opt/local/etc/profile.d/bash_completion.sh
elif is_gnu_linux && [ -f /usr/share/bash-completion/bash_completion ]; then
    . /usr/share/bash-completion/bash_completion
fi

Personal bash completion in ~/.bash_completion

command -v pandoc &>/dev/null && eval "$(pandoc --bash-completion)"

# Use a custom version: 1) enable git-ls-files 2) support the alias dotfiles
# cp /usr/share/bash-completion/completions/git ~/.git-completion.bash
source_maybe "~/.git-completion.bash"

source_maybe "/Applications/Docker.app/Contents/Resources/etc/docker.bash-completion"

_emacs ()
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts='--help --version -L --directory --l --load --script --daemon --debug-init -Q --reverse-video --no-desktop --no-window-system --batch --eval --funcall'

    case $prev in
        --help|--version)
            return
            ;;
        -L|--directory)
            COMPREPLY=( $(compgen -d ${cur}) )
            return
            ;;
        -l|--load|--script)
            COMPREPLY=( $(compgen -f ${cur}) )
            return
            ;;
    esac

    COMPREPLY=( $(compgen -f -W "${opts}" -- ${cur}) )
}
complete -F _emacs emacs

_emacsclient ()
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts='
    --version
    --help
    --tty
    --create-frame
    --eval
    --no-wait
    --quiet
    --socket-name
    --server-file
    --alternate-editor
    '

    COMPREPLY=( $(compgen -f -W "${opts}" -- ${cur}) )
}
complete -F _emacsclient emacsclient

History

The following settings of Bash history is copied from Better Bash history | Arabesque.

# Append history instead of rewriting it
shopt -s histappend

# Allow a larger history file
HISTFILESIZE=1000000
HISTSIZE=1000000

# Don’t store specific lines
HISTCONTROL='ignorespace:ignoredups'
HISTIGNORE='pwd:ls:bg:fg:history'

# Record timestamps
HISTTIMEFORMAT='%F %T '

# Use one command per line
shopt -s cmdhist

# Store history immediately
PROMPT_COMMAND='history -a;'

Select history with peco (base on bash/zsh のヒストリを peco で便利にする - Qiita):

peco-select-history () {
    declare l=$(HISTTIMEFORMAT= history | tac | peco --query "$READLINE_LINE" | cut -c 8-)
    READLINE_LINE="$l"
    READLINE_POINT=${#l}
}

bind -x '"\C-r": peco-select-history'

See also Examples · junegunn/fzf Wiki and Sample Usage · peco/peco Wiki.

Change directory

# Enable some Bash 4 features when possible:
# * `autocd`, e.g. `**/qux` will enter `./foo/bar/baz/qux`
# * Recursive globbing, e.g. `echo **/*.txt`
for option in autocd globstar; do
    shopt -s "$option" 2> /dev/null
done

Setup rupa/z: z - jump around:

if is_mac; then
    file=/opt/local/etc/profile.d/z.sh
elif is_gnu_linux; then
    file=/etc/profile.d/z.sh
fi

if [ -f "$file" ]; then
    source "$file"
else
    echo "Can't source $file, install it from <https://github.com/rupa/z>"
fi
unset file

Emacs

~/.emacs.d/misc/emacs.sh includes shell functions to launch Emacs’s functions (such as Magit and C-x C-f) inside Shell/Terminal.

source ~/.emacs.d/misc/emacs.sh

iTerm2

With iTerm2 Shell Integration, iTerm2 can

  • track recent used directories
  • capture command results
  • set mark
  • view command exit status
  • view command history
  • switch profile automatically

To install, first downlaod the script:

curl -L https://iterm2.com/misc/bash_startup.in -o ~/.iterm2_shell_integration.bash

Then load it:

[ "$TERM_PROGRAM" == "iTerm.app" ] && source_maybe "$HOME/.iterm2_shell_integration.bash"

Readline

info:bash#Readline Init File

# This file controls the behaviour of line input editing for
# programs that use the GNU Readline library.  Existing
# programs include FTP, Bash, and GDB.
#
# You can re-read the inputrc file with C-x C-r.
# Lines beginning with '#' are comments.
#
# First, include any system-wide bindings and variable
# assignments from /etc/Inputrc
$include /etc/Inputrc

$if Bash
# edit the path
"\C-xp": "PATH=${PATH}\e\C-e\C-a\ef\C-f"
# prepare to type a quoted word --
# insert open and close double quotes
# and move to just after the open quote
"\C-x\"": "\"\"\C-b"
# Quote the current or previous word
"\C-xq": "\eb\"\ef\""
$endif

# For FTP
$if Ftp
"\C-xg": "get \M-?"
"\C-xt": "put \M-?"
"\M-.": yank-last-arg
$endif

isync

OfflineImap 报 “Too many read 0” 错误

abort: command: FETCH => socket error: <type 'exceptions.IOError'> - Too many read 0

转而用 isync 。下面的配置是从 isync - ArchWiki 抄来的,其中的 “gmail” 懒得改了。

IMAPAccount main
# Address to connect to
Host imap.migadu.com
User mail@xuchunyang.me
# gem install netrc
PassCmd "ruby -r netrc -e 'print (Netrc.read(File.expand_path(\"~/.authinfo.gpg\"))[\"imap.migadu.com\"]).password'"
#
# Use SSL
SSLType IMAPS
CertificateFile /opt/local/share/curl/curl-ca-bundle.crt

IMAPStore main-remote
Account main

MaildirStore main-local
# The trailing "/" is important
Path ~/.mail/
Inbox ~/.mail/INBOX

Channel main
Master :main-remote:
Slave :main-local:
# Or include everything
Patterns *
# Automatically create missing mailboxes, both locally and on the server
Create Both
# Save the synchronization state files in the relevant directory
SyncState *

OfflineIMAP

Write a Python Script ~/.offlineimap.py to extract IMAP password from ~/.authinfo.gpg. I don’t know Python, the following is based on Gábor Melis’ () blog - OfflineIMAP with Encrypted Authinfo.

import re, os
from distutils.spawn import find_executable

def get_authinfo_password(machine, login):
    s = "machine %s login %s password ([^ ]*)\n" % (machine, login)
    p = re.compile(s)
    if find_executable("gpg2"):
        authinfo = os.popen("gpg2 -q --no-tty -d ~/.authinfo.gpg").read()
    else:
        authinfo = os.popen("gpg -q --no-tty -d ~/.authinfo.gpg").read()
    return p.search(authinfo).group(1)
[general]
pythonfile = ~/.offlineimap.py
accounts = Personal

[Account Personal]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = ~/Maildir

[Repository Remote]
type = IMAP

remotehost = imap.migadu.com
remoteuser = mail@xuchunyang.me
remotepasseval = get_authinfo_password("imap.migadu.com", "mail@xuchunyang.me")
sslcacertfile = /opt/local/etc/openssl/cert.pem

Resources

Notmuch

Hooks

set -x

mbsync -V -a

echo "pre-new hook Done!"
# [[man:notmuch-hooks][Manpage for notmuch-hooks]]
# 
# [[https://notmuchmail.org/initial_tagging/][initial tagging]]
# [[https://notmuchmail.org/pipermail/notmuch/2010/001691.html][{notmuch} Initial tagging]]

set -x

# notmuch tag +to-me -- to:mail@xuchunyang.me and not tag:to-me
# notmuch tag +sent -- from:mail@xuchunyang.me and not tag:sent
# notmuch tag +org -- to:emacs-orgmode@gnu.org and not tag:org
# notmuch tag +emacs -- to:emacs-devel@gnu.org and not tag:emacs
# notmuch tag +emacs -- to:help-gnu-emacs@gnu.org and not tag:emacs
# notmuch tag +notmuch -- to:notmuch@notmuchmail.org and not tag:notmuch

echo "post-new hook Done!"

Git

~/.gitignore

# Folder view configuration files
.DS_Store

~/.gitconfig

[user]
        name = Chunyang Xu
        email = mail@xuchunyang.me
        signingkey = A952083AF6D0A8BF
[gpg]
        program = gpg
[credential]
        helper = osxkeychain
[http]
        proxy = socks5://localhost:1086
[core]
        # Restroe Terminal after quitting
        #
        # See [[man:git-config][Manpage for git-config]] and [[man:less][Manpage for less]]
        #
        # Git defaults to less FRX
        #
        # -F or --quit-if-one-screen
        # -R or --RAW-CONTROL-CHARS
        # -X or --no-init
        #
        # XXX: -F doesn't work without -X, see
        # https://unix.stackexchange.com/questions/107315/less-quit-if-one-screen-without-no-init
        #
        # Thus deactivate X to restore terminal, and deactivate F to work with
        # it.
        pager = less -+X -+F
[include]
        path = .gitconfig_local

SSH

~/.ssh/id_rsa

-----BEGIN PGP MESSAGE----- Version: GnuPG v2

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 =X/y7 -----END PGP MESSAGE-----

~/.ssh/id_rsa.pub

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDHOci6JWgdNE8oxyuGOSSt2Ekn2VIhWMv9ipCAlBa+b+KDneA8kFOo2CdtvEywyv0/z7++DVA0j6Y7QMK4vh1H6PdD+N84ZL2wHXGlWCliYl2wlGhvefOaV3YVgTz4L3TQCsXnmCAWiFNzWAp+dHibgYuy0Sk2+vftcCpwgWFvMYZ5e/8HMNaAYA/aNauWivci1k6VzSmr2XToxOfyeXfkhmPsM3rnHxQbmW2CZJ4L5y0P8innLJSC8MC4zzddbqazHB+KbZYGGXFrJ4BPXN9zst+Q+mNZGCEg/fz8X6X92+C8zyvNgHM6sLPRqsKqpTIjqjGnIbuVCT7E8J8AzwiIUcRIjpeyYeJl5dnh1d1GQcFoa6ZRdhfZ7hMLUvxSsEPflrwdw8UqE6SOIOGi7r2C8FTnoXYkOipff6u0fngSq9CFQ7WQHqgIA1ABnq243EojimwARqcSHbhrWyUxY0D6Q7rs51nHXTOawnFr/46na0CI6sxTv3h6uGfjt5KBn56Y8meHHQlpsk1NR3R2P5UAOA0+xu7MsJUN3b4/xmALUIO6Eiz1ph25umEJC9sWuE6dMm9Wta+s6yLREdHZtV5YnTr1b/79lGLrbJlavTqf2jnBQAewRpMvRpSzVzbtRY8Ucq1+fL3/0eJTXUCAIrOiTAnRhfVqmzcFgftHnXdYuQ== mail@xuchunyang.me

~/.ssh/config

Host *
     # If the network connection is down, don't hang
     ServerAliveInterval 5
     # Master Connection
     # https://unix.stackexchange.com/questions/2857/ssh-easily-copy-file-to-local-system
     ControlMaster auto
     ControlPath ~/.ssh/control:%h:%p:%r

Host vps
     HostName xuchunyang.me
     User root

Host elpa
     HostName elpa.emacs-china.org
     User root

Host pc
     Hostname 192.168.0.105
     User xcy

GnuPG

I have made a backup for my GPG keys in my USB disk with

mkdir -v -p /Volumes/USB/backup/gnupg
cp -v ~/.gnupg/*.gpg /Volumes/USB/backup/gnupg

To resture these keys, use

cp /Volumes/USB/backup/gnupg/*.gpg ~/.gnupg

This method is from Instructions for exporting/importing (backup/restore) GPG keys.

nano

参考 /opt/local/share/doc/nano/sample.nanorc

## Use the blank line below the titlebar as extra editing space.
set morespace

## Switch on multiple file buffers (inserting a file will put it into
## a separate buffer).
set multibuffer

## Remember the cursor position in each file for the next editing session.
set positionlog

## Use smooth scrolling as the default.
set smooth

## Allow nano to be suspended.
set suspend

## Syntax highlight.
include "/opt/local/share/nano/*.nanorc"

## Key bindings.
## See nanorc(5) (section REBINDING KEYS) for more details on this.
bind ^S savefile main
bind M-Q findprevious main
bind M-W findnext main

Wget

# Set this to on to use timestamping by default:
# timestamping = on

# It is a good idea to make Wget send your email address in a `From:'
# header with your request (so that server administrators can contact
# you in case of errors).  Wget does *not* send `From:' by default.
header = From: Chunyang Xu <mail@xuchunyang.me>

Tips

Redirect wget to standard output

--output-document/-O 选项

wget --quiet --output-document=- xuchunyang.me
wget -q -O - xuchunyang.me

也可以写成更短的,不知道参数本来就可以这么写,又或者只是 Wget 的一个特例?

wget -qO- xuchunyang.me

Hammerspoon

-- http://www.hammerspoon.org/

hs.hotkey.bind({"ctrl", "cmd"}, "left", function()
      local win = hs.window.focusedWindow()
      local f = win:frame()
      local screen = win:screen()
      local max = screen:frame()

      f.x = max.x
      f.y = max.y
      f.w = max.w / 2
      f.h = max.h
      win:setFrame(f)
end)

hs.hotkey.bind({"ctrl", "cmd"}, "right", function()
      local win = hs.window.focusedWindow()
      local f = win:frame()
      local screen = win:screen()
      local max = screen:frame()

      f.x = max.x + (max.w / 2)
      f.y = max.y
      f.w = max.w / 2
      f.h = max.h
      win:setFrame(f)
end)

hs.hotkey.bind({"ctrl", "cmd"}, "up", function()
      local win = hs.window.focusedWindow()
      win:maximize()
end)

hs.hotkey.bind({"ctrl", "cmd"}, "down", function()
      local win = hs.window.focusedWindow()
      win:centerOnScreen()
end)

hs.alert.show("init.lua reloaded")

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published