Compare
5476e275fe0ef41e07360a68b386e8dd6c0c2191
…
broken-new-portal
· 120 commits
Commits
@@ -1 +1,2 @@
current
+home-config/sway/monitors
@@ -0,0 +1,29 @@
+# Guix Installation
+
+## Installing Guix
+
+### Instructions
+
+- Create USB with Guix installation image
+- Boot and create partitions using graphical installer
+- Bail out right before installation begins, go to terminal
+ - Mount cow-store using herd start cow-store /mnt
+ - Download latest version of configuration using `curl -o main.tar.gz --insecure --follow https://git.ryanserver.home.arpa/ryan77627/guix-config/archive/main.tar.gz` and unpack using tar
+ - Authorize nonguix channel using `curl -o signkey.pub https://substitutes.nonguix.org/signing-key.pub and guix archive --authorize < signkey.pub`
+ - Modify/add system config for system and initialize using `guix time-machine -C channels.scm -- system -L modules/ --substitute-urls='https://bordeaux.guix.gnu.org https://ci.guix.gnu.org https://substitutes.nonguix.org' init system.scm /mnt`
+ - When installed, proceed
+- Reboot into system, assign root and ryan user a password
+- Setup system completely
+ - Clone guix-config to proper location
+ - Reconfigure system
+ - `sudo -E guix time-machine -C channels.scm -- system -L modules reconfigure system.scm` <---- may not be needed
+ - `guix pull`
+ - `hash guix`
+ - `sudo guix system -L modules reconfigure system.scm`
+ - Configure GUIX Home
+ - Install Nix Home Manager
+ - May need to sudo herd restart nix-daemon or reconfigure system to get nix working???
+ - `nix-channel --update`
+ - `nix-shell '<home-manager>' -A install`
+ - `home-manager switch`
+- Everything should now be set up and ready to use :)
@@ -0,0 +1,24 @@
+(use-modules (ryan-config base-system)
+ (gnu))
+
+(operating-system
+ (inherit base-operating-system)
+ (host-name "RyanLaptop")
+ (mapped-devices (list (mapped-device
+ (source (uuid
+ "4de50ae4-e6f5-4f0c-ba4b-dd97b44a2ef2"))
+ (target "sysroot")
+ (type luks-device-mapping))))
+ (file-systems (cons* (file-system
+ (mount-point "/")
+ (device "/dev/mapper/sysroot")
+ (type "ext4")
+ (dependencies mapped-devices))
+ (file-system
+ (mount-point "/boot/efi")
+ (device (uuid "4C53-D400"
+ 'fat32))
+ (type "vfat")) %base-file-systems))
+ (swap-devices
+ (list
+ (swap-space (target (uuid "6758bed3-9ff2-49a0-9cc3-7c48eaee6c4a"))))))
@@ -0,0 +1,28 @@
+(use-modules (ryan-config base-system)
+ (gnu))
+
+(operating-system
+ (inherit base-operating-system)
+ (kernel-arguments (append (list "intel_iommu=on")
+ %default-kernel-arguments))
+ (initrd-modules (cons* "vfio_pci" "vfio" "vfio_iommu_type1"
+ %base-initrd-modules))
+ (host-name "RyanThinkpad")
+ (mapped-devices (list (mapped-device
+ (source (uuid
+ "adcaf322-7ee5-48ec-abf6-4a9b10643878"))
+ (target "sysroot")
+ (type luks-device-mapping))))
+ (file-systems (cons* (file-system
+ (mount-point "/")
+ (device "/dev/mapper/sysroot")
+ (type "ext4")
+ (dependencies mapped-devices))
+ (file-system
+ (mount-point "/boot/efi")
+ (device (uuid "DFE8-32EF"
+ 'fat32))
+ (type "vfat")) %base-file-systems))
+ (swap-devices
+ (list
+ (swap-space (target (uuid "7e1bb7c5-da2a-4509-8263-f707fc752993"))))))
@@ -0,0 +1,6 @@
+(use-modules (guix ci))
+
+(list (channel-with-substitutes-available
+ %default-guix-channel
+ "https://ci.guix.gnu.org")
+ )
@@ -2,6 +2,8 @@
(name 'guix)
(url "https://git.savannah.gnu.org/git/guix.git")
(branch "master")
+ (commit
+ "40e78353a4699b8edb6600d82df648914c9110b9")
(introduction
(make-channel-introduction
"9edb3f66fd807b096b48283debdcddccfea34bad"
@@ -11,8 +13,22 @@
(name 'nonguix)
(url "https://gitlab.com/nonguix/nonguix")
(branch "master")
+ (commit
+ "bb184bd0a8f91beec3a00718759e96c7828853de")
(introduction
(make-channel-introduction
"897c1a470da759236cc11798f4e0a5f7d4d59fbc"
(openpgp-fingerprint
- "2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5")))))
+ "2A39 3FFF 68F4 EF7A 3D29 12AF 6F51 20A0 22FB B2D5"))))
+ (channel
+ (name 'rosenthal)
+ (url "https://codeberg.org/hako/rosenthal.git")
+ (branch "trunk")
+ (commit
+ "58ad8f96b670fd58c474d188be7ae8fa0840b791")
+ (introduction
+ (make-channel-introduction
+ "7677db76330121a901604dfbad19077893865f35"
+ (openpgp-fingerprint
+ "13E7 6CD6 E649 C28C 3385 4DF5 5E5A A665 6149 17F7"))))
+ )
@@ -0,0 +1,93 @@
+#!/run/current-system/profile/bin/bash
+
+gather_env() {
+ # Gather needed information
+ echo -n "Type 'e' for encrypted or 'd' for decrypted install: "
+ read install_type
+
+ echo -n "Type system hostname: "
+ read install_hostname
+
+ echo -n "Type device file for ROOT data: "
+ read root_dev
+
+ echo -n "Type device file for BOOT data: "
+ read boot_dev
+
+ echo -n "Type device file for SWAP: "
+ read swap_dev
+
+}
+
+copy_and_prepare() {
+ # Associate devs with uuids
+ root_uuid=`blkid $root_dev | awk -F\" '{print $2}'`
+ boot_uuid=`blkid $boot_dev | awk -F\" '{print $2}'`
+ swap_uuid=`blkid $swap_dev | awk -F\" '{print $2}'`
+ # Let's a go!
+ echo "Information gathered. Deploying Guix on $root_dev ($root_uuid) with boot on $boot_dev ($boot_uuid) and swap on $swap_dev ($swap_uuid)"
+ echo -n "Proceed? (y/n): "
+ read install_choice
+
+ if [ "$install_choice" != "y" ]
+ then
+ echo "Bailing!"
+ exit 1
+ fi
+
+ # We are installing!
+ # Copy template to root of repo
+ if [ "$install_type" == "e" ]
+ then
+ cp ./modules/ryan-config/deploy-templates/HostTemplateEncrypted ./$install_hostname.scm
+ elif [ "$install_type" == "d" ]
+ then
+ cp ./modules/ryan-config/deploy-templates/HostTemplate ./$install_hostname.scm
+ else
+ echo "Invalid install type (not d or e), bailing!"
+ exit 1
+ fi
+
+ # Correct the information
+ sed -i "s/ChangeMe_ROOT/$root_uuid/" ./$install_hostname.scm
+ sed -i "s/ChangeMe_BOOTEFI/$boot_uuid/" ./$install_hostname.scm
+ sed -i "s/ChangeMe_SWAP/$swap_uuid/" ./$install_hostname.scm
+ sed -i "s/ChangeMe_HOST/$install_hostname/" ./$install_hostname.scm
+
+ # Install!
+ echo "Mounting /gnu/store to destination disk..."
+ herd start cow-store /mnt
+
+ # Install the non-guix signing keys
+ echo "Installing non-guix signing keys for substitutes..."
+ curl -o sign-key.pub https://substitutes.nonguix.org/signing-key.pub
+ guix archive --authorize < sign-key.pub
+}
+
+install_system() {
+ echo "Beginning install!"
+ guix time-machine -C ./channels.scm -- system -L ./modules --substitute-urls='https://substitutes.nonguix.org https://bordeaux.guix.gnu.org https://ci.guix.gnu.org' init $install_hostname.scm /mnt
+}
+
+install_user_env() {
+ # System should be installed now, we can chroot in and configure the user profile now
+ # NOTE: This assumes the user "ryan" for things, so change the USER var if you change your username
+
+ # Copy some files over to prepare for reboot
+ USER=ryan
+ guix shell git -- git clone https://git.stationery.faith/ryan77627/guix-dotfiles /mnt/home/$USER/.config/guix
+
+ cp ~/guix-dotfiles/$install_hostname.scm /mnt/home/$USER/.config/guix/$install_hostname.scm
+ cp ~/guix-dotfiles/modules/ryan-config/user_first_run.sh /mnt/home/$USER/.bashrc
+
+ chown 1000:1000 -R /mnt/home/ryan
+
+}
+
+gather_env
+copy_and_prepare
+install_system
+install_user_env
+
+# Reboot the machine at this point!
+reboot
@@ -0,0 +1,21 @@
+[Personal]
+source = imaps://ryan%40rschanz.org@mail.rschanz.org:993
+source-cred-cmd = pass emails/personal 2>/dev/null | tr -d '\n'
+outgoing = smtps://ryan%40rschanz.org@mail.rschanz.org:465
+outgoing-cred-cmd = pass emails/personal 2>/dev/null | tr -d '\n'
+default = INBOX
+from = Ryan Schanzenbacher <ryan@rschanz.org>
+copy-to = Sent
+signature-file = ~/.config/aerc/signature_personal
+check-mail = 5m
+
+[School]
+source = imaps+oauthbearer://rjs1877%40rit.edu@imap.gmail.com:993?token_endpoint=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Ftoken&client_id=667738788924-0rdfvaq9ijfo1vk4474eb3quf8206h2t.apps.googleusercontent.com&client_secret=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
+source-cred-cmd = pass emails/rit_personal 2>/dev/null | tr -d '\n'
+outgoing = smtps+oauthbearer://rjs1877%40rit.edu@imap.gmail.com:465?token_endpoint=https%3A%2F%2Faccounts.google.com%2Fo%2Foauth2%2Ftoken&client_id=667738788924-0rdfvaq9ijfo1vk4474eb3quf8206h2t.apps.googleusercontent.com&client_secret=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
+outgoing-cred-cmd = pass emails/rit_personal 2>/dev/null | tr -d '\n'
+from = Ryan Schanzenbacher <rjs1877@rit.edu>
+signature-file = ~/.config/aerc/signature_rit_personal
+check-mail = 5m
+default = INBOX
+copy-to = [Gmail]/Sent Mail
@@ -0,0 +1,566 @@
+#
+# aerc main configuration
+
+[general]
+#
+# Used as a default path for save operations if no other path is specified.
+# ~ is expanded to the current user home dir.
+#
+default-save-path=~/Downloads/
+
+# If set to "gpg", aerc will use system gpg binary and keystore for all crypto
+# operations. If set to "internal", the internal openpgp keyring will be used.
+# If set to "auto", the system gpg will be preferred unless the internal
+# keyring already exists, in which case the latter will be used.
+#
+# Default: auto
+pgp-provider=gpg
+
+# By default, the file permissions of accounts.conf must be restrictive and
+# only allow reading by the file owner (0600). Set this option to true to
+# ignore this permission check. Use this with care as it may expose your
+# credentials.
+#
+# Default: false
+unsafe-accounts-conf=true # I don't store my creds in this
+
+# Output log messages to specified file. A path starting with ~/ is expanded to
+# the user home dir. When redirecting aerc's output to a file using > shell
+# redirection, this setting is ignored and log messages are printed to stdout.
+#
+#log-file=~/aerc_log
+
+# Only log messages above the specified level to log-file. Supported levels
+# are: trace, debug, info, warn and error. When redirecting aerc's output to
+# a file using > shell redirection, this setting is ignored and the log level
+# is forced to trace.
+#
+# Default: info
+log-level=trace
+
+# Set the $TERM environment variable used for the embedded terminal.
+#
+# Default: xterm-256color
+#term=xterm-256color
+
+# Display OSC8 strings in the embedded terminal
+#
+# Default: false
+#enable-osc8=false
+
+[ui]
+#
+# Describes the format for each row in a mailbox view. This is a comma
+# separated list of column names with an optional align and width suffix. After
+# the column name, one of the '<' (left), ':' (center) or '>' (right) alignment
+# characters can be added (by default, left) followed by an optional width
+# specifier. The width is either an integer representing a fixed number of
+# characters, or a percentage between 1% and 99% representing a fraction of the
+# terminal width. It can also be one of the '*' (auto) or '=' (fit) special
+# width specifiers. Auto width columns will be equally attributed the remaining
+# terminal width. Fit width columns take the width of their contents. If no
+# width specifier is set, '*' is used by default.
+#
+# Default: date<20,name<17,flags>4,subject<*
+#index-columns=date<20,name<17,flags>4,subject<*
+
+#
+# Each name in index-columns must have a corresponding column-$name setting.
+# All column-$name settings accept golang text/template syntax. See
+# aerc-templates(7) for available template attributes and functions.
+#
+# Default settings
+#column-date={{.DateAutoFormat .Date.Local}}
+#column-name={{index (.From | names) 0}}
+#column-flags={{.Flags | join ""}}
+#column-subject={{.ThreadPrefix}}{{.Subject}}
+
+#
+# String separator inserted between columns. When the column width specifier is
+# an exact number of characters, the separator is added to it (i.e. the exact
+# width will be fully available for the column contents).
+#
+# Default: " "
+#column-separator=" "
+
+#
+# See time.Time#Format at https://godoc.org/time#Time.Format
+#
+# Default: 2006-01-02 03:04 PM (ISO 8601 + 12 hour time)
+#timestamp-format=2006-01-02 03:04 PM
+
+#
+# Index-only time format for messages that were received/sent today.
+# If this is not specified, timestamp-format is used instead.
+#
+#this-day-time-format=
+
+#
+# Index-only time format for messages that were received/sent within the last
+# 7 days. If this is not specified, timestamp-format is used instead.
+#
+#this-week-time-format=
+
+#
+# Index-only time format for messages that were received/sent this year.
+# If this is not specified, timestamp-format is used instead.
+#
+#this-year-time-format=
+
+#
+# Width of the sidebar, including the border.
+#
+# Default: 20
+#sidebar-width=20
+
+#
+# Message to display when viewing an empty folder.
+#
+# Default: (no messages)
+#empty-message=(no messages)
+
+# Message to display when no folders exists or are all filtered
+#
+# Default: (no folders)
+#empty-dirlist=(no folders)
+
+# Enable mouse events in the ui, e.g. clicking and scrolling with the mousewheel
+#
+# Default: false
+#mouse-enabled=false
+
+#
+# Ring the bell when new messages are received
+#
+# Default: true
+#new-message-bell=true
+
+#
+# Template to use for Account tab titles
+#
+# Default: {{.Account}}
+#tab-title-account={{.Account}}
+
+# Marker to show before a pinned tab's name.
+#
+# Default: `
+#pinned-tab-marker='`'
+
+# Template for the left side of the directory list.
+# See aerc-templates(7) for all available fields and functions.
+#
+# Default: {{.Folder}}
+#dirlist-left={{.Folder}}
+
+# Template for the right side of the directory list.
+# See aerc-templates(7) for all available fields and functions.
+#
+# Default: {{if .Unread}}{{humanReadable .Unread}}/{{end}}{{if .Exists}}{{humanReadable .Exists}}{{end}}
+#dirlist-right={{if .Unread}}{{humanReadable .Unread}}/{{end}}{{if .Exists}}{{humanReadable .Exists}}{{end}}
+
+# Delay after which the messages are actually listed when entering a directory.
+# This avoids loading messages when skipping over folders and makes the UI more
+# responsive. If you do not want that, set it to 0s.
+#
+# Default: 200ms
+#dirlist-delay=200ms
+
+# Display the directory list as a foldable tree that allows to collapse and
+# expand the folders.
+#
+# Default: false
+#dirlist-tree=false
+
+# If dirlist-tree is enabled, set level at which folders are collapsed by
+# default. Set to 0 to disable.
+#
+# Default: 0
+#dirlist-collapse=0
+
+# List of space-separated criteria to sort the messages by, see *sort*
+# command in *aerc*(1) for reference. Prefixing a criterion with "-r "
+# reverses that criterion.
+#
+# Example: "from -r date"
+#
+#sort=
+
+# Moves to next message when the current message is deleted
+#
+# Default: true
+#next-message-on-delete=true
+
+# Automatically set the "seen" flag when a message is opened in the message
+# viewer.
+#
+# Default: true
+#auto-mark-read=true
+
+# The directories where the stylesets are stored. It takes a colon-separated
+# list of directories. If this is unset or if a styleset cannot be found, the
+# following paths will be used as a fallback in that order:
+#
+# ${XDG_CONFIG_HOME:-~/.config}/aerc/stylesets
+# ${XDG_DATA_HOME:-~/.local/share}/aerc/stylesets
+# /usr/local/share/aerc/stylesets
+# /usr/share/aerc/stylesets
+#
+#stylesets-dirs=
+
+# Uncomment to use box-drawing characters for vertical and horizontal borders.
+#
+# Default: " "
+#border-char-vertical=" "
+#border-char-horizontal=" "
+
+# Sets the styleset to use for the aerc ui elements.
+#
+# Default: default
+#styleset-name=default
+
+# Activates fuzzy search in commands and their arguments: the typed string is
+# searched in the command or option in any position, and need not be
+# consecutive characters in the command or option.
+#
+# Default: false
+#fuzzy-complete=false
+
+# How long to wait after the last input before auto-completion is triggered.
+#
+# Default: 250ms
+#completion-delay=250ms
+
+# The minimum required characters to allow auto-completion to be triggered after
+# completion-delay.
+#
+# Default: 1
+#completion-min-chars=1
+
+#
+# Global switch for completion popovers
+#
+# Default: true
+#completion-popovers=true
+
+# Uncomment to use UTF-8 symbols to indicate PGP status of messages
+#
+# Default: ASCII
+#icon-unencrypted=
+#icon-encrypted=✔
+#icon-signed=✔
+#icon-signed-encrypted=✔
+#icon-unknown=✘
+#icon-invalid=⚠
+
+# Reverses the order of the message list. By default, the message list is
+# ordered with the newest (highest UID) message on top. Reversing the order
+# will put the oldest (lowest UID) message on top. This can be useful in cases
+# where the backend does not support sorting.
+#
+# Default: false
+#reverse-msglist-order = false
+
+# Reverse display of the mesage threads. Default order is the the intial
+# message is on the top with all the replies being displayed below. The
+# reverse option will put the initial message at the bottom with the
+# replies on top.
+#
+# Default: false
+#reverse-thread-order=false
+
+# Sort the thread siblings according to the sort criteria for the messages. If
+# sort-thread-siblings is false, the thread siblings will be sorted based on
+# the message UID in ascending order. This option is only applicable for
+# client-side threading with a backend that enables sorting. Note that there's
+# a performance impact when sorting is activated.
+#
+# Default: false
+#sort-thread-siblings=false
+
+#[ui:account=Personal]
+#
+# Enable a threaded view of messages. If this is not supported by the backend
+# (IMAP server or notmuch), threads will be built by the client.
+#
+# Default: false
+threading-enabled=true
+
+# Force client-side thread building
+#
+# Default: false
+#force-client-threads=false
+
+# Debounce client-side thread building
+#
+# Default: 50ms
+#client-threads-delay=50ms
+
+[statusline]
+#
+# Describes the format for the status line. This is a comma separated list of
+# column names with an optional align and width suffix. See [ui].index-columns
+# for more details. To completely mute the status line except for push
+# notifications, explicitly set status-columns to an empty string.
+#
+# Default: left<*,center:=,right>*
+#status-columns=left<*,center:=,right>*
+
+#
+# Each name in status-columns must have a corresponding column-$name setting.
+# All column-$name settings accept golang text/template syntax. See
+# aerc-templates(7) for available template attributes and functions.
+#
+# Default settings
+#column-left=[{{.Account}}] {{.StatusInfo}}
+#column-center={{.PendingKeys}}
+#column-right={{.TrayInfo}}
+
+#
+# String separator inserted between columns.
+# See [ui].column-separator for more details.
+#
+#column-separator=" "
+
+# Specifies the separator between grouped statusline elements.
+#
+# Default: " | "
+#separator=" | "
+
+# Defines the mode for displaying the status elements.
+# Options: text, icon
+#
+# Default: text
+#display-mode=text
+
+[viewer]
+#
+# Specifies the pager to use when displaying emails. Note that some filters
+# may add ANSI codes to add color to rendered emails, so you may want to use a
+# pager which supports ANSI codes.
+#
+# Default: less -R
+#pager=less -R
+
+#
+# If an email offers several versions (multipart), you can configure which
+# mimetype to prefer. For example, this can be used to prefer plaintext over
+# html emails.
+#
+# Default: text/plain,text/html
+#alternatives=text/plain,text/html
+
+#
+# Default setting to determine whether to show full headers or only parsed
+# ones in message viewer.
+#
+# Default: false
+#show-headers=false
+
+#
+# Layout of headers when viewing a message. To display multiple headers in the
+# same row, separate them with a pipe, e.g. "From|To". Rows will be hidden if
+# none of their specified headers are present in the message.
+#
+# Default: From|To,Cc|Bcc,Date,Subject
+#header-layout=From|To,Cc|Bcc,Date,Subject
+
+# Whether to always show the mimetype of an email, even when it is just a single part
+#
+# Default: false
+#always-show-mime=false
+
+# Parses and extracts http links when viewing a message. Links can then be
+# accessed with the open-link command.
+#
+# Default: true
+#parse-http-links=true
+
+[compose]
+#
+# Specifies the command to run the editor with. It will be shown in an embedded
+# terminal, though it may also launch a graphical window if the environment
+# supports it. Defaults to $EDITOR, or vi.
+#editor=
+
+# Address book command
+address-book-cmd = sh -c 'abook --mutt-query "%s" | tail -n +2'
+
+#
+# Default header fields to display when composing a message. To display
+# multiple headers in the same row, separate them with a pipe, e.g. "To|From".
+#
+# Default: To|From,Subject
+#header-layout=To|From,Subject
+
+#
+# Specifies the command to be used to tab-complete email addresses. Any
+# occurrence of "%s" in the address-book-cmd will be replaced with what the
+# user has typed so far.
+#
+# The command must output the completions to standard output, one completion
+# per line. Each line must be tab-delimited, with an email address occurring as
+# the first field. Only the email address field is required. The second field,
+# if present, will be treated as the contact name. Additional fields are
+# ignored.
+#
+# This parameter can also be set per account in accounts.conf.
+#address-book-cmd=
+
+# Specifies the command to be used to select attachments. Any occurence of '%s'
+# in the file-picker-cmd will be replaced the argument <arg> to :attach -m
+# <arg>.
+#
+# The command must output the selected files to standard output, one file per
+# line.
+file-picker-cmd=fzf --multi --query=%s
+
+#
+# Allow to address yourself when replying
+#
+# Default: true
+#reply-to-self=true
+
+#
+# Warn before sending an email that matches the specified regexp but does not
+# have any attachments. Leave empty to disable this feature.
+#
+# Uses Go's regexp syntax, documented at https://golang.org/s/re2syntax. The
+# "(?im)" flags are set by default (case-insensitive and multi-line).
+#
+# Example:
+# no-attachment-warning=^[^>]*attach(ed|ment)
+#
+#no-attachment-warning=
+
+#
+# When set, aerc will generate "format=flowed" bodies with a content type of
+# "text/plain; format=flowed" as described in RFC3676. This format is easier to
+# handle for some mailing software, and generally just looks like ordinary
+# text. To actually make use of this format's features, you'll need support in
+# your editor.
+#
+format-flowed=true
+
+[multipart-converters]
+#
+# Converters allow to generate multipart/alternative messages by converting the
+# main text/plain part into any other MIME type. Only exact MIME types are
+# accepted. The commands are invoked with sh -c and are expected to output
+# valid UTF-8 text.
+#
+# Example (obviously, this requires that you write your main text/plain body
+# using the markdown syntax):
+text/html=pandoc --wrap=preserve -f gfm+hard_line_breaks -t html --standalone
+
+[filters]
+#
+# Filters allow you to pipe an email body through a shell command to render
+# certain emails differently, e.g. highlighting them with ANSI escape codes.
+#
+# The commands are invoked with sh -c. The following folders are appended to
+# the system $PATH to allow referencing filters from their name only:
+#
+# ${XDG_CONFIG_HOME:-~/.config}/aerc/filters
+# ${XDG_DATA_HOME:-~/.local/share}/aerc/filters
+# $PREFIX/share/aerc/filters
+# /usr/share/aerc/filters
+#
+# The following variables are defined in the filter command environment:
+#
+# AERC_MIME_TYPE the part MIME type/subtype
+# AERC_FORMAT the part content type format= parameter
+# AERC_FILENAME the attachment filename (if any)
+# AERC_SUBJECT the message Subject header value
+# AERC_FROM the message From header value
+#
+# The first filter which matches the email's mimetype will be used, so order
+# them from most to least specific.
+#
+# You can also match on non-mimetypes, by prefixing with the header to match
+# against (non-case-sensitive) and a comma, e.g. subject,text will match a
+# subject which contains "text". Use header,~regex to match against a regex.
+#
+#text/plain=colorize
+#text/calendar=calendar
+message/delivery-status=bat -fn
+message/rfc822=bat -fn
+text/html=pandoc -f html -t plain | bat -fn
+#text/html=html | colorize
+text/*=bat -fn --file-name="$AERC_FILENAME"
+application/x-sh=bat -fn -l sh
+#image/*=catimg -w $(tput cols) -
+#subject,~Git(hub|lab)=lolcat -f
+#from,thatguywhodoesnothardwraphismessages=wrap -w 100 | colorize
+
+# This special filter is only used to post-process email headers when
+# [viewer].show-headers=true
+# By default, headers are piped directly into the pager.
+#
+#.headers=bat -fp
+
+[openers]
+#
+# Openers allow you to specify the command to use for the :open and :open-link
+# actions on a per-MIME-type basis. The :open-link URL scheme is used to
+# determine the MIME type as follows: x-scheme-handler/<scheme>.
+#
+# {} is expanded as the temporary filename to be opened. If it is not
+# encountered in the command, the temporary filename will be appened to the end
+# of the command.
+#
+# Like [filters], openers support basic shell globbing. The first opener which
+# matches the part's MIME type (or URL scheme handler MIME type) will be used,
+# so order them from most to least specific.
+#
+# Examples:
+# x-scheme-handler/irc=hexchat
+# x-scheme-handler/http*=firefox
+# text/html=surf -dfgms
+# text/plain=gvim {} +125
+# message/rfc822=thunderbird
+
+[hooks]
+#
+# Hooks are triggered whenever the associated event occurs.
+
+#
+# Executed when a new email arrives in the selected folder
+mail-received=notify-send "$AERC_FROM_NAME" "$AERC_SUBJECT"
+
+#
+# Executed when aerc starts
+#aerc-startup=aerc :terminal calcurse && aerc :next-tab
+
+#
+# Executed when aerc shuts down.
+#aerc-shutdown=
+
+[templates]
+# Templates are used to populate email bodies automatically.
+#
+
+# The directories where the templates are stored. It takes a colon-separated
+# list of directories. If this is unset or if a template cannot be found, the
+# following paths will be used as a fallback in that order:
+#
+# ${XDG_CONFIG_HOME:-~/.config}/aerc/templates
+# ${XDG_DATA_HOME:-~/.local/share}/aerc/templates
+# /usr/local/share/aerc/templates
+# /usr/share/aerc/templates
+#
+#template-dirs=
+
+# The default template to be used for new messages.
+#
+# default: new_message
+#new-message=new_message
+
+# The default template to be used for quoted replies.
+#
+# default: quoted_reply
+#quoted-reply=quoted_reply
+
+# The default template to be used for forward as body.
+#
+# default: forward_as_body
+#forwards=forward_as_body
@@ -0,0 +1,144 @@
+# Binds are of the form <key sequence> = <command to run>
+# To use '=' in a key sequence, substitute it with "Eq": "<Ctrl+Eq>"
+# If you wish to bind #, you can wrap the key sequence in quotes: "#" = quit
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+<C-t> = :term<Enter>
+? = :help keys<Enter>
+
+[messages]
+q = :quit<Enter>
+
+j = :next<Enter>
+<Down> = :next<Enter>
+<C-d> = :next 50%<Enter>
+<C-f> = :next 100%<Enter>
+<PgDn> = :next 100%<Enter>
+
+k = :prev<Enter>
+<Up> = :prev<Enter>
+<C-u> = :prev 50%<Enter>
+<C-b> = :prev 100%<Enter>
+<PgUp> = :prev 100%<Enter>
+g = :select 0<Enter>
+G = :select -1<Enter>
+<C-r> = :read<Enter>
+<C-u> = :unread<Enter>
+
+J = :next-folder<Enter>
+K = :prev-folder<Enter>
+H = :collapse-folder<Enter>
+L = :expand-folder<Enter>
+
+v = :mark -t<Enter>
+V = :mark -v<Enter>
+
+T = :toggle-threads<Enter>
+
+<Enter> = :view<Enter>
+dd = :mv Trash<Enter>
+dg = :mv [Gmail]/Trash<Enter>
+D = :delete<Enter>
+A = :archive year<Enter>
+
+C = :compose<Enter>
+
+rr = :reply -a<Enter>
+rq = :reply -aq<Enter>
+Rr = :reply<Enter>
+Rq = :reply -q<Enter>
+f = :forward -A<Enter>
+
+c = :cf<space>
+$ = :term<space>
+! = :term<space>
+| = :pipe<space>
+
+/ = :search<space>
+\ = :filter<space>
+n = :next-result<Enter>
+N = :prev-result<Enter>
+<Esc> = :clear<Enter>
+
+[messages:folder=Drafts]
+<Enter> = :recall<Enter>
+
+[view]
+/ = :toggle-key-passthrough<Enter>/
+q = :close<Enter>
+O = :open<Enter>
+S = :save<space>
+| = :pipe<space>
+D = :delete<Enter>
+dd = :mv Trash<Enter>
+dg = :mv [Gmail]/Trash<Enter>
+A = :archive year<Enter>
+
+<C-l> = :open-link <space>
+
+f = :forward -A<Enter>
+rr = :reply -a<Enter>
+rq = :reply -aq<Enter>
+Rr = :reply<Enter>
+Rq = :reply -q<Enter>
+
+H = :toggle-headers<Enter>
+<C-k> = :prev-part<Enter>
+<C-j> = :next-part<Enter>
+J = :next<Enter>
+K = :prev<Enter>
+
+[view::passthrough]
+$noinherit = true
+$ex = <C-x>
+<Esc> = :toggle-key-passthrough<Enter>
+
+[compose]
+# Keybindings used when the embedded terminal is not selected in the compose
+# view
+$noinherit = true
+$ex = <C-x>
+<C-k> = :prev-field<Enter>
+<C-j> = :next-field<Enter>
+<A-p> = :switch-account -p<Enter>
+<A-n> = :switch-account -n<Enter>
+<tab> = :next-field<Enter>
+<backtab> = :prev-field<Enter>
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+<C-c> = :cc<Enter>
+<C-b> = :bcc<Enter>
+<C-q> = :abort<Enter>
+
+[compose::editor]
+# Keybindings used when the embedded terminal is selected in the compose view
+$noinherit = true
+$ex = <C-x>
+<C-k> = :prev-field<Enter>
+<C-j> = :next-field<Enter>
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
+<C-q> = :abort<Enter>
+
+[compose::review]
+# Keybindings used when reviewing a message to be sent
+y = :send<Enter>
+n = :abort<Enter>
+v = :preview<Enter>
+p = :postpone<Enter>
+q = :choose -o d discard abort -o p postpone postpone<Enter>
+e = :edit<Enter>
+a = :attach<space>
+d = :detach<space>
+S = :sign<Enter>
+E = :encrypt<Enter>
+A = :attach-key<Enter>
+C = :multipart text/html<Enter>
+
+[terminal]
+$noinherit = true
+$ex = <C-x>
+<C-q> = :close<Enter>
+
+<C-p> = :prev-tab<Enter>
+<C-n> = :next-tab<Enter>
@@ -0,0 +1,3 @@
+--
+Best,
+Ryan Schanzenbacher
@@ -0,0 +1,5 @@
+--
+Best,
+Ryan Schanzenbacher
+Rochester Institute of Technology
+Cybersecurity BS/MS Student
@@ -0,0 +1,15 @@
+window:
+ opacity: 0.70
+font:
+ size: 15
+ normal:
+ family: "Monofur Nerd Font Mono"
+ style: Regular
+
+ bold:
+ family: "Monofur Nerd Font Mono"
+ style: Bold
+
+ italic:
+ family: "Monofur Nerd Font Mono"
+ style: Italic
@@ -4,5 +4,13 @@ export XDG_CURRENT_DESKTOP=sway
export XDG_SESSION_DESKTOP=sway
export _JAVA_AWT_WM_NONREPEATING=1
+export XDG_DATA_DIRS=$XDG_DATA_DIRS:~/.nix-profile/share
+export PATH=$PATH:~/.nix-profile/bin
+
# Honor per-interactive-shell startup file
if [ -f ~/.bashrc ]; then . ~/.bashrc; fi
+
+if [ -z "$SSH_CLIENT" ] && [ -z "${DISPLAY}" ] && [ "${XDG_VTNR}" -eq 1 ]; then
+ exec Hyprland
+fi
+
@@ -19,6 +19,10 @@ fi
# Source the system-wide file.
source /etc/bashrc
+# Activate vim mode >:)
+set -o vi
+set show-mode-in-prompt on
+
# Adjust the prompt depending on whether we're in 'guix environment'.
if [ -n "$GUIX_ENVIRONMENT" ]
then
@@ -34,8 +38,14 @@ alias grep='grep --color=auto'
alias quit='exit'
export EDITOR=nvim
alias cat='bat --paging=never'
+alias ds='sudo -E guix system -L ~/.config/guix/modules reconfigure ~/.config/guix/$(hostname).scm'
+alias dh='guix home -L ~/.config/guix/modules reconfigure ~/.config/guix/home-config/home-configuration.scm && home-manager switch'
+alias gc='git -C ~/.config/guix add . && git -C ~/.config/guix commit && git -C ~/.config/guix push all'
+alias cg='git -C ~/.config/guix pull'
+alias cgh='git -C ~/.config/guix pull stationeryh main'
+export XDG_DATA_DIRS=$XDG_DATA_DIRS:/var/lib/flatpak/exports/share:/home/ryan/.local/share/flatpak/exports/share
# GPG SETUP FOR SSH
-export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
-gpgconf --launch gpg-agent
+#export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
+#gpgconf --launch gpg-agent
export GPG_TTY=$(tty)
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFont-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFont-BoldItalic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFont-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFont-Regular.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontMono-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontMono-BoldItalic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontMono-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontMono-Regular.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontPropo-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontPropo-BoldItalic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontPropo-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/AnonymicePro/AnonymiceProNerdFontPropo-Regular.ttf differ
@@ -0,0 +1,94 @@
+Copyright (c) 2009, Mark Simonson (http://www.ms-studio.com, mark@marksimonson.com),
+with Reserved Font Name Anonymous Pro.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,8 @@
+
+# Nerd Fonts
+
+This is an archived font from a Nerd Fonts release.
+
+For more information see:
+* https://github.com/ryanoasis/nerd-fonts/
+* https://github.com/ryanoasis/nerd-fonts/releases/latest/
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Bold Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Bold Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Bold Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Bold Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Light Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Light Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Light Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Light Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Medium Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Medium Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Medium Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Medium Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Regular Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Regular Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Regular Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Regular Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Retina Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Retina Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Retina Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code Retina Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code SemiBold Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code SemiBold Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code SemiBold Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Fira Code/Fira Code SemiBold Nerd Font Complete.ttf differ
@@ -0,0 +1,93 @@
+Copyright (c) 2019, The Lilex Project Authors (https://github.com/mishamyrt/lilex)
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
\ No newline at end of file
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Mono Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Mono.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Bold Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Mono Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Mono.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Light Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Mono Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Mono.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Medium Nerd Font Complete.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Mono Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Mono Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Mono.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Mono.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Windows Compatible.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete Windows Compatible.ttf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete.otf differ
Binary files /dev/null and b/home-config/fonts/Lilex/Lilex Regular Nerd Font Complete.ttf differ
@@ -0,0 +1,8 @@
+
+# Nerd Fonts
+
+This is an archived font from a Nerd Fonts release.
+
+For more information see:
+* https://github.com/ryanoasis/nerd-fonts/
+* https://github.com/ryanoasis/nerd-fonts/releases/latest/
Binary files /dev/null and b/home-config/fonts/Monofur For Powerline/Monofur Bold for Powerline.ttf differ
Binary files /dev/null and b/home-config/fonts/Monofur For Powerline/Monofur Italic for Powerline.ttf differ
Binary files /dev/null and b/home-config/fonts/Monofur For Powerline/Monofur for Powerline.ttf differ
@@ -0,0 +1,20 @@
+------------------------------------------------------------------------
+The monofur typeface by tobias b koehler (unci@tigerden.com)
+------------------------------------------------------------------------
+
+This is a monospaced geometric rounded sans serif font based on the
+eurofurence typeface family.
+
+The character set includes Roman, Greek and Cyrillic characters as well
+as box drawing characters. File format is TrueType for PC (under
+Windows, Linux etc).
+
+These fonts are freeware and can be distributed as long as they are
+together with this text file. I would appreciate it though if you could
+contact me at unci@tigerden.com if you put them on a server. Free
+samples from commercial users are always very welcome. :)
+
+For more information, please see the uncifonts WWW page at:
+http://mercurio.iet.unipi.it/users/tobias/uncifonts.html
+
+Have fun! tobias b koehler, 2000-04-02
\ No newline at end of file
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFont-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFont-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFont-Regular.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontMono-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontMono-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontMono-Regular.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontPropo-Bold.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontPropo-Italic.ttf differ
Binary files /dev/null and b/home-config/fonts/MonofurNerdFont/MonofurNerdFontPropo-Regular.ttf differ
@@ -0,0 +1,8 @@
+
+# Nerd Fonts
+
+This is an archived font from a Nerd Fonts release.
+
+For more information see:
+* https://github.com/ryanoasis/nerd-fonts/
+* https://github.com/ryanoasis/nerd-fonts/releases/latest/
@@ -0,0 +1,3 @@
+enable-ssh-support
+
+pinentry-program /run/current-system/profile/bin/pinentry
@@ -0,0 +1,10 @@
+# List of allowed ssh keys. Only keys present in this file are used
+# in the SSH protocol. The ssh-add tool may add new entries to this
+# file to enable them; you may also add them manually. Comment
+# lines, like this one, as well as empty lines are ignored. Lines do
+# have a certain length limit but this is not serious limitation as
+# the format of the entries is fixed and checked by gpg-agent. A
+# non-comment line starts with optional white spaces, followed by the
+# keygrip of the key given as 40 hex digits, optionally followed by a
+# caching TTL in seconds, and another optional field for arbitrary
+# flags. Prepend the keygrip with an '!' mark to disable it.
@@ -6,34 +6,96 @@
(use-modules (gnu home)
(gnu packages)
+ (gnu packages vim)
+ (gnu packages gcc)
+ (gnu packages gnupg)
(gnu services)
+ (guix packages)
(guix gexp)
- (gnu home services shells))
+ (gnu home services shells)
+ (gnu home services desktop)
+ (gnu home services gnupg)
+ (gnu home services)
+ (ryan-services pipewire)
+ (ryan-packages freedesktop)
+ (ryan-packages mozilla))
+
+(define my-neovim
+ (package
+ (inherit neovim)
+ (native-inputs
+ (modify-inputs (package-native-inputs neovim)
+ (prepend gcc-12)))))
(home-environment
;; Below is the list of packages that will show up in your
;; Home profile, under ~/.guix-home/profile.
- (packages (specifications->packages (list "bat"
- "qrencode"
- "libreoffice"
- "flatpak"
- "gnupg"
- "lsof"
- "pavucontrol"
- "bind:utils"
- ;"firefox"
- "irssi"
- "font-cns11643"
- "syncthing"
- "perl"
- "tor"
- "unzip"
- "alacritty"
- "htop"
- "curl"
- "neovim"
- "weechat"
- "git")))
+ (packages (append (specifications->packages (list "bat"
+ "xdg-utils"
+ "abook"
+ "libnotify"
+ "fzf"
+ "waypipe"
+ "gnunet"
+ "qrencode"
+ "binutils"
+ "gcc-toolchain"
+ "borg"
+ "restic"
+ "rsync"
+ "pv"
+ "python-msgpack"
+ "libreoffice"
+ "flatpak"
+ "gnupg"
+ "lsof"
+ "pavucontrol"
+ "netcat"
+ "bind:utils"
+ "font-cns11643"
+ "syncthing"
+ "imv"
+ "perl"
+ "tor"
+ "unzip"
+ "alacritty"
+ "htop"
+ "curl"
+ "pandoc"
+ "texlive-bin"
+ "texlive-scheme-basic"
+ "texlive-txfonts"
+ "texlive-amsfonts"
+ "texlive-lm"
+ "texlive-lm-math"
+ "texlive-iftex"
+ "texlive-unicode-math"
+ "texlive-fontspec"
+ "texlive-xcolor"
+ "texlive-geometry"
+ "texlive-hyperref"
+ "texlive-parskip"
+ "texlive-etoolbox"
+ "zathura"
+ "zathura-pdf-mupdf"
+ "fzf"
+ "weechat"
+ "gimp"
+ "python"
+ "python:tk"
+ "file"
+ "python-lsp-server"
+ "kdenlive"
+ "sqlite"
+ "mpv"
+ "playerctl"
+ "aerc"
+ "tcpdump"
+ "pamixer"
+ "git"
+ "node"
+ "git-lfs"))
+ (list my-neovim wl-mirror firefox-wayland-new)))
;; Below is the list of Home services. To search for available
;; services, run 'guix home search KEYWORD' in a terminal.
@@ -41,10 +103,32 @@
(list (service home-bash-service-type
(home-bash-configuration
(aliases '(("grep" . "grep --color=auto") ("ll" . "ls -l")
- ("ls" . "ls -p --color=auto")))
+ ("ls" . "ls -p --color=auto")
+ ("python" . "python3")))
(bashrc (list (local-file
- "/home/ryan/.config/guix/home-config/.bashrc"
"bashrc")))
(bash-profile (list (local-file
- "/home/ryan/.config/guix/home-config/.bash_profile"
- "bash_profile"))))))))
+ "bash_profile")))))
+ (service home-xdg-configuration-files-service-type
+ `(("nvim/init.vim" ,(local-file "nvim/config/init.vim"))
+ ("nvim/after/ftplugin/markdown/custom.vim" ,(local-file "nvim/config/after/ftplugin/markdown/custom.vim"))
+ ("sway" ,(local-file "sway" #:recursive? #t))
+ ("hypr" ,(local-file "hypr" #:recursive? #t))
+ ("waybar" ,(local-file "waybar" #:recursive? #t))
+ ("alacritty" ,(local-file "alacritty" #:recursive? #t))
+ ("aerc" ,(local-file "aerc" #:recursive? #t))
+ ("home-manager" ,(local-file "nix-home-manager" #:recursive? #t)) ))
+ (service home-files-service-type
+ `((".local/share/nvim/site/autoload/plug.vim" ,(local-file "nvim/plugin-manager/plug.vim"))
+ (".ssh/config" ,(local-file "ssh/config"))
+ ;(".gnupg/sshcontrol" ,(local-file "gnupg/sshcontrol"))
+ ;(".gnupg/gpg-agent.conf" ,(local-file "gnupg/gpg-agent.conf"))
+ (".fonts" ,(local-file "fonts" #:recursive? #t))
+ (".nix-channels" ,(local-file "nix-channels"))))
+ (service home-pipewire-service-type)
+ (service home-dbus-service-type)
+ (service home-gpg-agent-service-type
+ (home-gpg-agent-configuration
+ (pinentry-program
+ (file-append pinentry "/bin/pinentry"))
+ (ssh-support? #t))) )))
Binary files /dev/null and b/home-config/hypr/Wallpapers/mountains.jpg differ
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+
+hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP &
+
+waybar &
+
+mako &
+
+swaybg -i ~/.config/hypr/Wallpapers/mountains.jpg &
+
+swayidle -w timeout 300 'swaylock --screenshots --clock --indicator --grace 3 --fade-in 1 --effect-blur 7x5 --effect-greyscale' timeout 600 'hyprctl dispatch dpms off' resume 'hyprctl dispatch dpms on' before-sleep 'swaylock -f -c 000000' &
+
+syncthing serve --no-browser &
@@ -0,0 +1,221 @@
+exec-once = dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP=Hyprland
+
+#
+# Please note not all available settings / options are set here.
+# For a full list, see the wiki
+#
+
+# See https://wiki.hyprland.org/Configuring/Monitors/
+monitor=,preferred,auto,1
+
+
+# See https://wiki.hyprland.org/Configuring/Keywords/ for more
+
+# Execute your favorite apps at launch
+# exec-once = waybar & hyprpaper & firefox
+
+# Source a file (multi-file configs)
+source = ~/.config/hypr/monitors.conf
+
+# Some default env vars.
+env = XCURSOR_SIZE,24
+
+# For all categories, see https://wiki.hyprland.org/Configuring/Variables/
+input {
+ kb_layout = us
+ kb_variant =
+ kb_model =
+ kb_options =
+ kb_rules =
+ numlock_by_default = true
+
+ follow_mouse = 1
+
+ touchpad {
+ natural_scroll = no
+ }
+
+ sensitivity = 0 # -1.0 - 1.0, 0 means no modification.
+}
+
+general {
+ # See https://wiki.hyprland.org/Configuring/Variables/ for more
+
+ gaps_in = 5
+ gaps_out = 10
+ border_size = 2
+ col.active_border = rgba(33ccffee) rgba(00ff99ee) 45deg
+ col.inactive_border = rgba(595959aa)
+
+ layout = dwindle
+}
+
+decoration {
+ # See https://wiki.hyprland.org/Configuring/Variables/ for more
+
+ rounding = 5
+ blur {
+ enabled = yes
+ size = 3
+ passes = 1
+ new_optimizations = on
+ }
+
+ drop_shadow = yes
+ shadow_range = 4
+ shadow_render_power = 3
+ col.shadow = rgba(1a1a1aee)
+}
+
+animations {
+ enabled = yes
+
+ # Some default animations, see https://wiki.hyprland.org/Configuring/Animations/ for more
+
+ bezier = myBezier, 0.05, 0.9, 0.1, 1.05
+
+ animation = windows, 1, 7, myBezier
+ animation = windowsOut, 1, 7, default, popin 80%
+ animation = border, 1, 10, default
+ animation = borderangle, 1, 8, default
+ animation = fade, 1, 7, default
+ animation = workspaces, 1, 6, default
+}
+
+dwindle {
+ # See https://wiki.hyprland.org/Configuring/Dwindle-Layout/ for more
+ pseudotile = yes # master switch for pseudotiling. Enabling is bound to mainMod + P in the keybinds section below
+ preserve_split = yes # you probably want this
+}
+
+master {
+ # See https://wiki.hyprland.org/Configuring/Master-Layout/ for more
+ new_is_master = true
+}
+
+gestures {
+ # See https://wiki.hyprland.org/Configuring/Variables/ for more
+ workspace_swipe = off
+}
+
+# Example per-device config
+# See https://wiki.hyprland.org/Configuring/Keywords/#executing for more
+device:epic-mouse-v1 {
+ sensitivity = -0.5
+}
+
+# Example windowrule v1
+# windowrule = float, ^(kitty)$
+# Example windowrule v2
+# windowrulev2 = float,class:^(kitty)$,title:^(kitty)$
+# See https://wiki.hyprland.org/Configuring/Window-Rules/ for more
+
+
+# See https://wiki.hyprland.org/Configuring/Keywords/ for more
+$mainMod = SUPER
+
+# Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more
+bind = $mainMod, Return, exec, alacritty
+bind = $mainMod SHIFT, Q, killactive
+bind = $mainMod SHIFT, E, exit
+bind = $mainMod SHIFT, Space, togglefloating
+bind = $mainMod, D, exec, fuzzel --width=35 --font='Hack:weight=bold:size=12' --background-color='282a36fa' --selection-color='3d4460fa' --line-height=20 --border-radius=20
+bind = $mainMod, P, pseudo, # dwindle
+bind = $mainMod, J, togglesplit, # dwindle
+bind = $mainMod, F, fullscreen, 1
+bind = $mainMod SHIFT, F, fullscreen
+bind = ,XF86MonBrightnessUp, exec, light -A 10
+bind = ,XF86MonBrightnessDown, exec, light -U 10
+bind = ,XF86AudioRaiseVolume, exec, pamixer -i 5
+bind = ,XF86AudioLowerVolume, exec, pamixer -d 5
+bind = ,XF86AudioMute, exec, pamixer -t
+bind = ,XF86AudioPlay, exec, playerctl play-pause
+bind = ,XF86AudioPause, exec, playerctl play-pause
+bind = ,XF86AudioNext, exec, playerctl next
+bind = ,XF86AudioPrev, exec, playerctl previous
+bind = ,XF86AudioStop, exec, playerctl stop
+
+# Move workspace between monitors
+bind = $mainMod CTRL SHIFT, left, movecurrentworkspacetomonitor, l
+bind = $mainMod CTRL SHIFT, right, movecurrentworkspacetomonitor, r
+bind = $mainMod CTRL SHIFT, up, movecurrentworkspacetomonitor, u
+bind = $mainMod CTRL SHIFT, down, movecurrentworkspacetomonitor, d
+
+# Move focus with mainMod + arrow keys
+bind = $mainMod, left, movefocus, l
+bind = $mainMod, right, movefocus, r
+bind = $mainMod, up, movefocus, u
+bind = $mainMod, down, movefocus, d
+
+# Move window with mainMod + SHIFT + arrow keys
+bind = $mainMod SHIFT, left, movewindow, l
+bind = $mainMod SHIFT, right, movewindow, r
+bind = $mainMod SHIFT, up, movewindow, u
+bind = $mainMod SHIFT, down, movewindow, d
+
+# Switch workspaces with mainMod + [0-9]
+bind = $mainMod, 1, workspace, 1
+bind = $mainMod, 2, workspace, 2
+bind = $mainMod, 3, workspace, 3
+bind = $mainMod, 4, workspace, 4
+bind = $mainMod, 5, workspace, 5
+bind = $mainMod, 6, workspace, 6
+bind = $mainMod, 7, workspace, 7
+bind = $mainMod, 8, workspace, 8
+bind = $mainMod, 9, workspace, 9
+bind = $mainMod, 0, workspace, 10
+
+# Move active window to a workspace with mainMod + SHIFT + [0-9]
+bind = $mainMod SHIFT, 1, movetoworkspace, 1
+bind = $mainMod SHIFT, 2, movetoworkspace, 2
+bind = $mainMod SHIFT, 3, movetoworkspace, 3
+bind = $mainMod SHIFT, 4, movetoworkspace, 4
+bind = $mainMod SHIFT, 5, movetoworkspace, 5
+bind = $mainMod SHIFT, 6, movetoworkspace, 6
+bind = $mainMod SHIFT, 7, movetoworkspace, 7
+bind = $mainMod SHIFT, 8, movetoworkspace, 8
+bind = $mainMod SHIFT, 9, movetoworkspace, 9
+bind = $mainMod SHIFT, 0, movetoworkspace, 10
+
+# Scroll through existing workspaces with mainMod + scroll
+bind = $mainMod, mouse_down, workspace, e+1
+bind = $mainMod, mouse_up, workspace, e-1
+
+# Move/resize windows with mainMod + LMB/RMB and dragging
+bindm = $mainMod, mouse:272, movewindow
+bindm = $mainMod, mouse:273, resizewindow
+
+# Bind mainMod + L to screenlocker
+bind = $mainMod, L, exec, swaylock --screenshots --clock --indicator --fade-in 1 --effect-blur 7x5 --effect-greyscale
+
+# Keybind for screenshot
+bind = $mainMod SHIFT, S, exec, grimblast copy area
+bind = $mainMod SHIFT, Print, exec, grimblast edit area
+
+# Notifications keybinds
+bind = $mainMod, N, exec, makoctl dismiss
+bind = $mainMod SHIFT, N, exec, makoctl dismiss -a
+
+# Window Rules
+
+# Firefox PiP
+windowrulev2 = float, class:^(firefox)$, title:^(Picture-in-Picture)$
+windowrulev2 = pin, class:^(firefox)$, title:^(Picture-in-Picture)$
+windowrulev2 = size 578 326, class:^(firefox)$, title:^(Picture-in-Picture)$
+
+# Firefox Sharing Indicator
+windowrulev2 = float, class:^(firefox)$, title:^(Firefox — Sharing Indicator)$
+windowrulev2 = size 56 31, class:^(firefox)$, title:^(Firefox — Sharing Indicator)$
+windowrulev2 = move 50% 0, class:^(firefox)$, title:^(Firefox — Sharing Indicator)$
+windowrulev2 = nomaximizerequest, class:^(firefox)$, title:^(Firefox — Sharing Indicator)$
+windowrulev2 = nofullscreenrequest, class:^(firefox)$, title:^(Firefox — Sharing Indicator)$
+
+# Weather
+windowrulev2 = float,class:^(ala-wttr)$
+windowrulev2 = size 740 712, class:^(ala-wttr)$
+
+exec-once = ~/.config/hypr/autostart.sh
+
+misc {
+ disable_hyprland_logo = true
+}
@@ -0,0 +1,2 @@
+monitor=eDP-1,1920x1080, 0x0, 1
+monitor=HDMI-A-1,1920x1080, 1920x0, 1
@@ -0,0 +1,2 @@
+https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
+https://nixos.org/channels/nixpkgs-unstable nixpkgs
@@ -0,0 +1,82 @@
+{ config, pkgs, ... }:
+
+{
+ # Home Manager needs a bit of information about you and the paths it should
+ # manage.
+ home.username = "ryan";
+ home.homeDirectory = "/home/ryan";
+
+ # This value determines the Home Manager release that your configuration is
+ # compatible with. This helps avoid breakage when a new Home Manager release
+ # introduces backwards incompatible changes.
+ #
+ # You should not change this value, even if you update Home Manager. If you do
+ # want to update the value, then make sure to first check the Home Manager
+ # release notes.
+ home.stateVersion = "22.11"; # Please read the comment before changing.
+
+ # This value will set some environment variables to allow home-manager to
+ # function better outside of NixOS
+ nixpkgs.config.allowUnfree = true;
+ targets.genericLinux.enable = true;
+ fonts.fontconfig.enable = true;
+
+ # The home.packages option allows you to install Nix packages into your
+ # environment.
+ home.packages = with pkgs; [
+ # # Adds the 'hello' command to your environment. It prints a friendly
+ # # "Hello, world!" when run.
+ # pkgs.hello
+ yt-dlp
+ xdg-desktop-portal-hyprland
+ pass
+ rustup
+ gcc
+ pkg-config
+
+ # # It is sometimes useful to fine-tune packages, for example, by applying
+ # # overrides. You can do that directly here, just don't forget the
+ # # parentheses. Maybe you want to install Nerd Fonts with a limited number of
+ # # fonts?
+ # (pkgs.nerdfonts.override { fonts = [ "FantasqueSansMono" ]; })
+
+ # # You can also create simple shell scripts directly inside your
+ # # configuration. For example, this adds a command 'my-hello' to your
+ # # environment:
+ # (pkgs.writeShellScriptBin "my-hello" ''
+ # echo "Hello, ${config.home.username}!"
+ # '')
+ ];
+
+ # Home Manager is pretty good at managing dotfiles. The primary way to manage
+ # plain files is through 'home.file'.
+ home.file = {
+ # # Building this configuration will create a copy of 'dotfiles/screenrc' in
+ # # the Nix store. Activating the configuration will then make '~/.screenrc' a
+ # # symlink to the Nix store copy.
+ # ".screenrc".source = dotfiles/screenrc;
+
+ # # You can also set the file content immediately.
+ # ".gradle/gradle.properties".text = ''
+ # org.gradle.console=verbose
+ # org.gradle.daemon.idletimeout=3600000
+ # '';
+ };
+
+ # You can also manage environment variables but you will have to manually
+ # source
+ #
+ # ~/.nix-profile/etc/profile.d/hm-session-vars.sh
+ #
+ # or
+ #
+ # /etc/profiles/per-user/ryan/etc/profile.d/hm-session-vars.sh
+ #
+ # if you don't want to manage your shell through Home Manager.
+ home.sessionVariables = {
+ # EDITOR = "emacs";
+ };
+
+ # Let Home Manager install and manage itself.
+ programs.home-manager.enable = true;
+}
@@ -0,0 +1,2 @@
+"Used to overwrite table behavior in markdown files
+let b:table_mode_corner='+'
@@ -0,0 +1,97 @@
+set nu rnu
+imap kj <Esc>
+set ts=4
+set sw=4
+set sts=4
+set et
+set mouse=
+set cursorline
+set cc=79
+
+call plug#begin(stdpath('data') . '/plugged')
+"Plug 'prabirshrestha/vim-lsp'
+"Plug 'mattn/vim-lsp-settings'
+"Plug 'prabirshrestha/asyncomplete.vim'
+"Plug 'prabirshrestha/asyncomplete-lsp.vim'
+"Plug 'Yggdroot/indentLine'
+Plug 'nvim-treesitter/nvim-treesitter', {'do':':TSUpdate'}
+Plug 'vim-pandoc/vim-pandoc'
+Plug 'vim-pandoc/vim-pandoc-syntax'
+Plug 'dhruvasagar/vim-table-mode'
+Plug '~/.config/nvim/after'
+Plug 'skywind3000/asyncrun.vim'
+Plug 'folke/tokyonight.nvim', {'branch':'main'}
+Plug 'nvim-lualine/lualine.nvim'
+Plug 'nvim-tree/nvim-web-devicons'
+Plug 'ms-jpq/coq_nvim', {'branch':'coq'}
+Plug 'ms-jpq/coq.artifacts', {'branch':'artifacts'}
+Plug 'williamboman/mason.nvim'
+Plug 'williamboman/mason-lspconfig.nvim'
+Plug 'neovim/nvim-lspconfig'
+Plug 'nvim-orgmode/orgmode'
+call plug#end()
+
+"Load Theme
+colorscheme tokyonight-night
+
+"Load COQ Autocomplete
+let g:coq_settings = {'auto_start':'shut-up'}
+
+"Load LuaLine, COQ, and nvim-orgmode
+lua << END
+require('lualine').setup()
+require('coq')
+require('orgmode').setup_ts_grammar()
+require("mason").setup()
+require("mason-lspconfig").setup {
+ ensure_installed = { "pyright" },
+}
+
+require("mason-lspconfig").setup_handlers {
+ function (server_name)
+ require("lspconfig")[server_name].setup {}
+ end,
+}
+
+require('nvim-treesitter.configs').setup {
+ highlight = {
+ enable = true,
+ additional_vim_regex_highlighting = {'org'},
+ },
+ ensure_installed = {'org', 'vim', 'python'},
+}
+
+require('orgmode').setup({
+ org_agenda_files = {'~/Sync/org/**/*'},
+ org_default_notes_file = '~/Sync/org/refile.org',
+ org_blank_before_new_entry = {
+ heading = false,
+ plain_list_item = false,
+ },
+})
+
+vim.opt.conceallevel = 2
+vim.opt.concealcursor = nc
+
+--local lspconfig = require('lspconfig')
+END
+
+"asynccomplete Auto Complete Config
+"inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
+"inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
+"inoremap <expr> <cr> pumvisible() ? asyncomplete#close_popup() : "\<cr>"
+
+"vim-pandoc config
+let g:pandoc#modules#disabled = ['spell', 'folding']
+
+"vim-table-mode config
+let g:table_mode_corner_corner='+'
+let g:table_mode_header_fillchar='='
+
+"pandoc render and open preview
+command Pv AsyncRun zathura '%:r.pdf'
+command Rd silent exec "!pandoc -t pdf -o %:r.pdf --from=markdown+escaped_line_breaks -V geometry:margin=1in %"
+command Rr exec "!pandoc -t pdf -o %:r.pdf --from=markdown+escaped_line_breaks -V geometry:margin=1in %"
+
+"Auto-rerender markdown files to pdf
+autocmd BufWritePost *.mkd :Rd
@@ -0,0 +1,2812 @@
+" vim-plug: Vim plugin manager
+" ============================
+"
+" Download plug.vim and put it in ~/.vim/autoload
+"
+" curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
+" https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
+"
+" Edit your .vimrc
+"
+" call plug#begin('~/.vim/plugged')
+"
+" " Make sure you use single quotes
+"
+" " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align
+" Plug 'junegunn/vim-easy-align'
+"
+" " Any valid git URL is allowed
+" Plug 'https://github.com/junegunn/vim-github-dashboard.git'
+"
+" " Multiple Plug commands can be written in a single line using | separators
+" Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'
+"
+" " On-demand loading
+" Plug 'preservim/nerdtree', { 'on': 'NERDTreeToggle' }
+" Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
+"
+" " Using a non-default branch
+" Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }
+"
+" " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)
+" Plug 'fatih/vim-go', { 'tag': '*' }
+"
+" " Plugin options
+" Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }
+"
+" " Plugin outside ~/.vim/plugged with post-update hook
+" Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
+"
+" " Unmanaged plugin (manually installed and updated)
+" Plug '~/my-prototype-plugin'
+"
+" " Initialize plugin system
+" call plug#end()
+"
+" Then reload .vimrc and :PlugInstall to install plugins.
+"
+" Plug options:
+"
+"| Option | Description |
+"| ----------------------- | ------------------------------------------------ |
+"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use |
+"| `rtp` | Subdirectory that contains Vim plugin |
+"| `dir` | Custom directory for the plugin |
+"| `as` | Use different name for the plugin |
+"| `do` | Post-update hook (string or funcref) |
+"| `on` | On-demand loading: Commands or `<Plug>`-mappings |
+"| `for` | On-demand loading: File types |
+"| `frozen` | Do not update unless explicitly specified |
+"
+" More information: https://github.com/junegunn/vim-plug
+"
+"
+" Copyright (c) 2017 Junegunn Choi
+"
+" MIT License
+"
+" Permission is hereby granted, free of charge, to any person obtaining
+" a copy of this software and associated documentation files (the
+" "Software"), to deal in the Software without restriction, including
+" without limitation the rights to use, copy, modify, merge, publish,
+" distribute, sublicense, and/or sell copies of the Software, and to
+" permit persons to whom the Software is furnished to do so, subject to
+" the following conditions:
+"
+" The above copyright notice and this permission notice shall be
+" included in all copies or substantial portions of the Software.
+"
+" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+" EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+if exists('g:loaded_plug')
+ finish
+endif
+let g:loaded_plug = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let s:plug_src = 'https://github.com/junegunn/vim-plug.git'
+let s:plug_tab = get(s:, 'plug_tab', -1)
+let s:plug_buf = get(s:, 'plug_buf', -1)
+let s:mac_gui = has('gui_macvim') && has('gui_running')
+let s:is_win = has('win32')
+let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)
+let s:vim8 = has('patch-8.0.0039') && exists('*job_start')
+if s:is_win && &shellslash
+ set noshellslash
+ let s:me = resolve(expand('<sfile>:p'))
+ set shellslash
+else
+ let s:me = resolve(expand('<sfile>:p'))
+endif
+let s:base_spec = { 'branch': '', 'frozen': 0 }
+let s:TYPE = {
+\ 'string': type(''),
+\ 'list': type([]),
+\ 'dict': type({}),
+\ 'funcref': type(function('call'))
+\ }
+let s:loaded = get(s:, 'loaded', {})
+let s:triggers = get(s:, 'triggers', {})
+
+function! s:is_powershell(shell)
+ return a:shell =~# 'powershell\(\.exe\)\?$' || a:shell =~# 'pwsh\(\.exe\)\?$'
+endfunction
+
+function! s:isabsolute(dir) abort
+ return a:dir =~# '^/' || (has('win32') && a:dir =~? '^\%(\\\|[A-Z]:\)')
+endfunction
+
+function! s:git_dir(dir) abort
+ let gitdir = s:trim(a:dir) . '/.git'
+ if isdirectory(gitdir)
+ return gitdir
+ endif
+ if !filereadable(gitdir)
+ return ''
+ endif
+ let gitdir = matchstr(get(readfile(gitdir), 0, ''), '^gitdir: \zs.*')
+ if len(gitdir) && !s:isabsolute(gitdir)
+ let gitdir = a:dir . '/' . gitdir
+ endif
+ return isdirectory(gitdir) ? gitdir : ''
+endfunction
+
+function! s:git_origin_url(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let config = gitdir . '/config'
+ if empty(gitdir) || !filereadable(config)
+ return ''
+ endif
+ return matchstr(join(readfile(config)), '\[remote "origin"\].\{-}url\s*=\s*\zs\S*\ze')
+endfunction
+
+function! s:git_revision(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+
+ let line = get(readfile(head), 0, '')
+ let ref = matchstr(line, '^ref: \zs.*')
+ if empty(ref)
+ return line
+ endif
+
+ if filereadable(gitdir . '/' . ref)
+ return get(readfile(gitdir . '/' . ref), 0, '')
+ endif
+
+ if filereadable(gitdir . '/packed-refs')
+ for line in readfile(gitdir . '/packed-refs')
+ if line =~# ' ' . ref
+ return matchstr(line, '^[0-9a-f]*')
+ endif
+ endfor
+ endif
+
+ return ''
+endfunction
+
+function! s:git_local_branch(dir) abort
+ let gitdir = s:git_dir(a:dir)
+ let head = gitdir . '/HEAD'
+ if empty(gitdir) || !filereadable(head)
+ return ''
+ endif
+ let branch = matchstr(get(readfile(head), 0, ''), '^ref: refs/heads/\zs.*')
+ return len(branch) ? branch : 'HEAD'
+endfunction
+
+function! s:git_origin_branch(spec)
+ if len(a:spec.branch)
+ return a:spec.branch
+ endif
+
+ " The file may not be present if this is a local repository
+ let gitdir = s:git_dir(a:spec.dir)
+ let origin_head = gitdir.'/refs/remotes/origin/HEAD'
+ if len(gitdir) && filereadable(origin_head)
+ return matchstr(get(readfile(origin_head), 0, ''),
+ \ '^ref: refs/remotes/origin/\zs.*')
+ endif
+
+ " The command may not return the name of a branch in detached HEAD state
+ let result = s:lines(s:system('git symbolic-ref --short HEAD', a:spec.dir))
+ return v:shell_error ? '' : result[-1]
+endfunction
+
+if s:is_win
+ function! s:plug_call(fn, ...)
+ let shellslash = &shellslash
+ try
+ set noshellslash
+ return call(a:fn, a:000)
+ finally
+ let &shellslash = shellslash
+ endtry
+ endfunction
+else
+ function! s:plug_call(fn, ...)
+ return call(a:fn, a:000)
+ endfunction
+endif
+
+function! s:plug_getcwd()
+ return s:plug_call('getcwd')
+endfunction
+
+function! s:plug_fnamemodify(fname, mods)
+ return s:plug_call('fnamemodify', a:fname, a:mods)
+endfunction
+
+function! s:plug_expand(fmt)
+ return s:plug_call('expand', a:fmt, 1)
+endfunction
+
+function! s:plug_tempname()
+ return s:plug_call('tempname')
+endfunction
+
+function! plug#begin(...)
+ if a:0 > 0
+ let s:plug_home_org = a:1
+ let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p'))
+ elseif exists('g:plug_home')
+ let home = s:path(g:plug_home)
+ elseif has('nvim')
+ let home = stdpath('data') . '/plugged'
+ elseif !empty(&rtp)
+ let home = s:path(split(&rtp, ',')[0]) . '/plugged'
+ else
+ return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
+ endif
+ if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp
+ return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')
+ endif
+
+ let g:plug_home = home
+ let g:plugs = {}
+ let g:plugs_order = []
+ let s:triggers = {}
+
+ call s:define_commands()
+ return 1
+endfunction
+
+function! s:define_commands()
+ command! -nargs=+ -bar Plug call plug#(<args>)
+ if !executable('git')
+ return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')
+ endif
+ if has('win32')
+ \ && &shellslash
+ \ && (&shell =~# 'cmd\(\.exe\)\?$' || s:is_powershell(&shell))
+ return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')
+ endif
+ if !has('nvim')
+ \ && (has('win32') || has('win32unix'))
+ \ && !has('multi_byte')
+ return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.')
+ endif
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])
+ command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update(<bang>0, [<f-args>])
+ command! -nargs=0 -bar -bang PlugClean call s:clean(<bang>0)
+ command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif
+ command! -nargs=0 -bar PlugStatus call s:status()
+ command! -nargs=0 -bar PlugDiff call s:diff()
+ command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(<bang>0, <f-args>)
+endfunction
+
+function! s:to_a(v)
+ return type(a:v) == s:TYPE.list ? a:v : [a:v]
+endfunction
+
+function! s:to_s(v)
+ return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
+endfunction
+
+function! s:glob(from, pattern)
+ return s:lines(globpath(a:from, a:pattern))
+endfunction
+
+function! s:source(from, ...)
+ let found = 0
+ for pattern in a:000
+ for vim in s:glob(a:from, pattern)
+ execute 'source' s:esc(vim)
+ let found = 1
+ endfor
+ endfor
+ return found
+endfunction
+
+function! s:assoc(dict, key, val)
+ let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)
+endfunction
+
+function! s:ask(message, ...)
+ call inputsave()
+ echohl WarningMsg
+ let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) '))
+ echohl None
+ call inputrestore()
+ echo "\r"
+ return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0
+endfunction
+
+function! s:ask_no_interrupt(...)
+ try
+ return call('s:ask', a:000)
+ catch
+ return 0
+ endtry
+endfunction
+
+function! s:lazy(plug, opt)
+ return has_key(a:plug, a:opt) &&
+ \ (empty(s:to_a(a:plug[a:opt])) ||
+ \ !isdirectory(a:plug.dir) ||
+ \ len(s:glob(s:rtp(a:plug), 'plugin')) ||
+ \ len(s:glob(s:rtp(a:plug), 'after/plugin')))
+endfunction
+
+function! plug#end()
+ if !exists('g:plugs')
+ return s:err('plug#end() called without calling plug#begin() first')
+ endif
+
+ if exists('#PlugLOD')
+ augroup PlugLOD
+ autocmd!
+ augroup END
+ augroup! PlugLOD
+ endif
+ let lod = { 'ft': {}, 'map': {}, 'cmd': {} }
+
+ if get(g:, 'did_load_filetypes', 0)
+ filetype off
+ endif
+ for name in g:plugs_order
+ if !has_key(g:plugs, name)
+ continue
+ endif
+ let plug = g:plugs[name]
+ if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for')
+ let s:loaded[name] = 1
+ continue
+ endif
+
+ if has_key(plug, 'on')
+ let s:triggers[name] = { 'map': [], 'cmd': [] }
+ for cmd in s:to_a(plug.on)
+ if cmd =~? '^<Plug>.\+'
+ if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
+ call s:assoc(lod.map, cmd, name)
+ endif
+ call add(s:triggers[name].map, cmd)
+ elseif cmd =~# '^[A-Z]'
+ let cmd = substitute(cmd, '!*$', '', '')
+ if exists(':'.cmd) != 2
+ call s:assoc(lod.cmd, cmd, name)
+ endif
+ call add(s:triggers[name].cmd, cmd)
+ else
+ call s:err('Invalid `on` option: '.cmd.
+ \ '. Should start with an uppercase letter or `<Plug>`.')
+ endif
+ endfor
+ endif
+
+ if has_key(plug, 'for')
+ let types = s:to_a(plug.for)
+ if !empty(types)
+ augroup filetypedetect
+ call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
+ augroup END
+ endif
+ for type in types
+ call s:assoc(lod.ft, type, name)
+ endfor
+ endif
+ endfor
+
+ for [cmd, names] in items(lod.cmd)
+ execute printf(
+ \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
+ \ cmd, string(cmd), string(names))
+ endfor
+
+ for [map, names] in items(lod.map)
+ for [mode, map_prefix, key_prefix] in
+ \ [['i', '<C-\><C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
+ execute printf(
+ \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, %s, "%s")<CR>',
+ \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix)
+ endfor
+ endfor
+
+ for [ft, names] in items(lod.ft)
+ augroup PlugLOD
+ execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
+ \ ft, string(ft), string(names))
+ augroup END
+ endfor
+
+ call s:reorg_rtp()
+ filetype plugin indent on
+ if has('vim_starting')
+ if has('syntax') && !exists('g:syntax_on')
+ syntax enable
+ end
+ else
+ call s:reload_plugins()
+ endif
+endfunction
+
+function! s:loaded_names()
+ return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')
+endfunction
+
+function! s:load_plugin(spec)
+ call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim')
+endfunction
+
+function! s:reload_plugins()
+ for name in s:loaded_names()
+ call s:load_plugin(g:plugs[name])
+ endfor
+endfunction
+
+function! s:trim(str)
+ return substitute(a:str, '[\/]\+$', '', '')
+endfunction
+
+function! s:version_requirement(val, min)
+ for idx in range(0, len(a:min) - 1)
+ let v = get(a:val, idx, 0)
+ if v < a:min[idx] | return 0
+ elseif v > a:min[idx] | return 1
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:git_version_requirement(...)
+ if !exists('s:git_version')
+ let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')
+ endif
+ return s:version_requirement(s:git_version, a:000)
+endfunction
+
+function! s:progress_opt(base)
+ return a:base && !s:is_win &&
+ \ s:git_version_requirement(1, 7, 1) ? '--progress' : ''
+endfunction
+
+function! s:rtp(spec)
+ return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
+endfunction
+
+if s:is_win
+ function! s:path(path)
+ return s:trim(substitute(a:path, '/', '\', 'g'))
+ endfunction
+
+ function! s:dirpath(path)
+ return s:path(a:path) . '\'
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo =~? '^[a-z]:\|^[%~]'
+ endfunction
+
+ " Copied from fzf
+ function! s:wrap_cmds(cmds)
+ let cmds = [
+ \ '@echo off',
+ \ 'setlocal enabledelayedexpansion']
+ \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds])
+ \ + ['endlocal']
+ if has('iconv')
+ if !exists('s:codepage')
+ let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0)
+ endif
+ return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage))
+ endif
+ return map(cmds, 'v:val."\r"')
+ endfunction
+
+ function! s:batchfile(cmd)
+ let batchfile = s:plug_tempname().'.bat'
+ call writefile(s:wrap_cmds(a:cmd), batchfile)
+ let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ return [batchfile, cmd]
+ endfunction
+else
+ function! s:path(path)
+ return s:trim(a:path)
+ endfunction
+
+ function! s:dirpath(path)
+ return substitute(a:path, '[/\\]*$', '/', '')
+ endfunction
+
+ function! s:is_local_plug(repo)
+ return a:repo[0] =~ '[/$~]'
+ endfunction
+endif
+
+function! s:err(msg)
+ echohl ErrorMsg
+ echom '[vim-plug] '.a:msg
+ echohl None
+endfunction
+
+function! s:warn(cmd, msg)
+ echohl WarningMsg
+ execute a:cmd 'a:msg'
+ echohl None
+endfunction
+
+function! s:esc(path)
+ return escape(a:path, ' ')
+endfunction
+
+function! s:escrtp(path)
+ return escape(a:path, ' ,')
+endfunction
+
+function! s:remove_rtp()
+ for name in s:loaded_names()
+ let rtp = s:rtp(g:plugs[name])
+ execute 'set rtp-='.s:escrtp(rtp)
+ let after = globpath(rtp, 'after')
+ if isdirectory(after)
+ execute 'set rtp-='.s:escrtp(after)
+ endif
+ endfor
+endfunction
+
+function! s:reorg_rtp()
+ if !empty(s:first_rtp)
+ execute 'set rtp-='.s:first_rtp
+ execute 'set rtp-='.s:last_rtp
+ endif
+
+ " &rtp is modified from outside
+ if exists('s:prtp') && s:prtp !=# &rtp
+ call s:remove_rtp()
+ unlet! s:middle
+ endif
+
+ let s:middle = get(s:, 'middle', &rtp)
+ let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
+ let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)')
+ let rtp = join(map(rtps, 'escape(v:val, ",")'), ',')
+ \ . ','.s:middle.','
+ \ . join(map(afters, 'escape(v:val, ",")'), ',')
+ let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
+ let s:prtp = &rtp
+
+ if !empty(s:first_rtp)
+ execute 'set rtp^='.s:first_rtp
+ execute 'set rtp+='.s:last_rtp
+ endif
+endfunction
+
+function! s:doautocmd(...)
+ if exists('#'.join(a:000, '#'))
+ execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)
+ endif
+endfunction
+
+function! s:dobufread(names)
+ for name in a:names
+ let path = s:rtp(g:plugs[name])
+ for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin']
+ if len(finddir(dir, path))
+ if exists('#BufRead')
+ doautocmd BufRead
+ endif
+ return
+ endif
+ endfor
+ endfor
+endfunction
+
+function! plug#load(...)
+ if a:0 == 0
+ return s:err('Argument missing: plugin name(s) required')
+ endif
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000
+ let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')
+ if !empty(unknowns)
+ let s = len(unknowns) > 1 ? 's' : ''
+ return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
+ end
+ let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')
+ if !empty(unloaded)
+ for name in unloaded
+ call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ endfor
+ call s:dobufread(unloaded)
+ return 1
+ end
+ return 0
+endfunction
+
+function! s:remove_triggers(name)
+ if !has_key(s:triggers, a:name)
+ return
+ endif
+ for cmd in s:triggers[a:name].cmd
+ execute 'silent! delc' cmd
+ endfor
+ for map in s:triggers[a:name].map
+ execute 'silent! unmap' map
+ execute 'silent! iunmap' map
+ endfor
+ call remove(s:triggers, a:name)
+endfunction
+
+function! s:lod(names, types, ...)
+ for name in a:names
+ call s:remove_triggers(name)
+ let s:loaded[name] = 1
+ endfor
+ call s:reorg_rtp()
+
+ for name in a:names
+ let rtp = s:rtp(g:plugs[name])
+ for dir in a:types
+ call s:source(rtp, dir.'/**/*.vim')
+ endfor
+ if a:0
+ if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))
+ execute 'runtime' a:1
+ endif
+ call s:source(rtp, a:2)
+ endif
+ call s:doautocmd('User', name)
+ endfor
+endfunction
+
+function! s:lod_ft(pat, names)
+ let syn = 'syntax/'.a:pat.'.vim'
+ call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)
+ execute 'autocmd! PlugLOD FileType' a:pat
+ call s:doautocmd('filetypeplugin', 'FileType')
+ call s:doautocmd('filetypeindent', 'FileType')
+endfunction
+
+function! s:lod_cmd(cmd, bang, l1, l2, args, names)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
+endfunction
+
+function! s:lod_map(map, names, with_prefix, prefix)
+ call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
+ call s:dobufread(a:names)
+ let extra = ''
+ while 1
+ let c = getchar(0)
+ if c == 0
+ break
+ endif
+ let extra .= nr2char(c)
+ endwhile
+
+ if a:with_prefix
+ let prefix = v:count ? v:count : ''
+ let prefix .= '"'.v:register.a:prefix
+ if mode(1) == 'no'
+ if v:operator == 'c'
+ let prefix = "\<esc>" . prefix
+ endif
+ let prefix .= v:operator
+ endif
+ call feedkeys(prefix, 'n')
+ endif
+ call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
+endfunction
+
+function! plug#(repo, ...)
+ if a:0 > 1
+ return s:err('Invalid number of arguments (1..2)')
+ endif
+
+ try
+ let repo = s:trim(a:repo)
+ let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec
+ let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??'))
+ let spec = extend(s:infer_properties(name, repo), opts)
+ if !has_key(g:plugs, name)
+ call add(g:plugs_order, name)
+ endif
+ let g:plugs[name] = spec
+ let s:loaded[name] = get(s:loaded, name, 0)
+ catch
+ return s:err(repo . ' ' . v:exception)
+ endtry
+endfunction
+
+function! s:parse_options(arg)
+ let opts = copy(s:base_spec)
+ let type = type(a:arg)
+ let opt_errfmt = 'Invalid argument for "%s" option of :Plug (expected: %s)'
+ if type == s:TYPE.string
+ if empty(a:arg)
+ throw printf(opt_errfmt, 'tag', 'string')
+ endif
+ let opts.tag = a:arg
+ elseif type == s:TYPE.dict
+ for opt in ['branch', 'tag', 'commit', 'rtp', 'dir', 'as']
+ if has_key(a:arg, opt)
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string')
+ endif
+ endfor
+ for opt in ['on', 'for']
+ if has_key(a:arg, opt)
+ \ && type(a:arg[opt]) != s:TYPE.list
+ \ && (type(a:arg[opt]) != s:TYPE.string || empty(a:arg[opt]))
+ throw printf(opt_errfmt, opt, 'string or list')
+ endif
+ endfor
+ if has_key(a:arg, 'do')
+ \ && type(a:arg.do) != s:TYPE.funcref
+ \ && (type(a:arg.do) != s:TYPE.string || empty(a:arg.do))
+ throw printf(opt_errfmt, 'do', 'string or funcref')
+ endif
+ call extend(opts, a:arg)
+ if has_key(opts, 'dir')
+ let opts.dir = s:dirpath(s:plug_expand(opts.dir))
+ endif
+ else
+ throw 'Invalid argument type (expected: string or dictionary)'
+ endif
+ return opts
+endfunction
+
+function! s:infer_properties(name, repo)
+ let repo = a:repo
+ if s:is_local_plug(repo)
+ return { 'dir': s:dirpath(s:plug_expand(repo)) }
+ else
+ if repo =~ ':'
+ let uri = repo
+ else
+ if repo !~ '/'
+ throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)
+ endif
+ let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')
+ let uri = printf(fmt, repo)
+ endif
+ return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri }
+ endif
+endfunction
+
+function! s:install(force, names)
+ call s:update_impl(0, a:force, a:names)
+endfunction
+
+function! s:update(force, names)
+ call s:update_impl(1, a:force, a:names)
+endfunction
+
+function! plug#helptags()
+ if !exists('g:plugs')
+ return s:err('plug#begin was not called')
+ endif
+ for spec in values(g:plugs)
+ let docd = join([s:rtp(spec), 'doc'], '/')
+ if isdirectory(docd)
+ silent! execute 'helptags' s:esc(docd)
+ endif
+ endfor
+ return 1
+endfunction
+
+function! s:syntax()
+ syntax clear
+ syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber
+ syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX
+ syn match plugNumber /[0-9]\+[0-9.]*/ contained
+ syn match plugBracket /[[\]]/ contained
+ syn match plugX /x/ contained
+ syn match plugDash /^-\{1}\ /
+ syn match plugPlus /^+/
+ syn match plugStar /^*/
+ syn match plugMessage /\(^- \)\@<=.*/
+ syn match plugName /\(^- \)\@<=[^ ]*:/
+ syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/
+ syn match plugTag /(tag: [^)]\+)/
+ syn match plugInstall /\(^+ \)\@<=[^:]*/
+ syn match plugUpdate /\(^* \)\@<=[^:]*/
+ syn match plugCommit /^ \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag
+ syn match plugEdge /^ \X\+$/
+ syn match plugEdge /^ \X*/ contained nextgroup=plugSha
+ syn match plugSha /[0-9a-f]\{7,9}/ contained
+ syn match plugRelDate /([^)]*)$/ contained
+ syn match plugNotLoaded /(not loaded)$/
+ syn match plugError /^x.*/
+ syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/
+ syn match plugH2 /^.*:\n-\+$/
+ syn match plugH2 /^-\{2,}/
+ syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
+ hi def link plug1 Title
+ hi def link plug2 Repeat
+ hi def link plugH2 Type
+ hi def link plugX Exception
+ hi def link plugBracket Structure
+ hi def link plugNumber Number
+
+ hi def link plugDash Special
+ hi def link plugPlus Constant
+ hi def link plugStar Boolean
+
+ hi def link plugMessage Function
+ hi def link plugName Label
+ hi def link plugInstall Function
+ hi def link plugUpdate Type
+
+ hi def link plugError Error
+ hi def link plugDeleted Ignore
+ hi def link plugRelDate Comment
+ hi def link plugEdge PreProc
+ hi def link plugSha Identifier
+ hi def link plugTag Constant
+
+ hi def link plugNotLoaded Comment
+endfunction
+
+function! s:lpad(str, len)
+ return a:str . repeat(' ', a:len - len(a:str))
+endfunction
+
+function! s:lines(msg)
+ return split(a:msg, "[\r\n]")
+endfunction
+
+function! s:lastline(msg)
+ return get(s:lines(a:msg), -1, '')
+endfunction
+
+function! s:new_window()
+ execute get(g:, 'plug_window', 'vertical topleft new')
+endfunction
+
+function! s:plug_window_exists()
+ let buflist = tabpagebuflist(s:plug_tab)
+ return !empty(buflist) && index(buflist, s:plug_buf) >= 0
+endfunction
+
+function! s:switch_in()
+ if !s:plug_window_exists()
+ return 0
+ endif
+
+ if winbufnr(0) != s:plug_buf
+ let s:pos = [tabpagenr(), winnr(), winsaveview()]
+ execute 'normal!' s:plug_tab.'gt'
+ let winnr = bufwinnr(s:plug_buf)
+ execute winnr.'wincmd w'
+ call add(s:pos, winsaveview())
+ else
+ let s:pos = [winsaveview()]
+ endif
+
+ setlocal modifiable
+ return 1
+endfunction
+
+function! s:switch_out(...)
+ call winrestview(s:pos[-1])
+ setlocal nomodifiable
+ if a:0 > 0
+ execute a:1
+ endif
+
+ if len(s:pos) > 1
+ execute 'normal!' s:pos[0].'gt'
+ execute s:pos[1] 'wincmd w'
+ call winrestview(s:pos[2])
+ endif
+endfunction
+
+function! s:finish_bindings()
+ nnoremap <silent> <buffer> R :call <SID>retry()<cr>
+ nnoremap <silent> <buffer> D :PlugDiff<cr>
+ nnoremap <silent> <buffer> S :PlugStatus<cr>
+ nnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ xnoremap <silent> <buffer> U :call <SID>status_update()<cr>
+ nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
+ nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
+endfunction
+
+function! s:prepare(...)
+ if empty(s:plug_getcwd())
+ throw 'Invalid current working directory. Cannot proceed.'
+ endif
+
+ for evar in ['$GIT_DIR', '$GIT_WORK_TREE']
+ if exists(evar)
+ throw evar.' detected. Cannot proceed.'
+ endif
+ endfor
+
+ call s:job_abort()
+ if s:switch_in()
+ if b:plug_preview == 1
+ pc
+ endif
+ enew
+ else
+ call s:new_window()
+ endif
+
+ nnoremap <silent> <buffer> q :call <SID>close_pane()<cr>
+ if a:0 == 0
+ call s:finish_bindings()
+ endif
+ let b:plug_preview = -1
+ let s:plug_tab = tabpagenr()
+ let s:plug_buf = winbufnr(0)
+ call s:assign_name()
+
+ for k in ['<cr>', 'L', 'o', 'X', 'd', 'dd']
+ execute 'silent! unmap <buffer>' k
+ endfor
+ setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell
+ if exists('+colorcolumn')
+ setlocal colorcolumn=
+ endif
+ setf vim-plug
+ if exists('g:syntax_on')
+ call s:syntax()
+ endif
+endfunction
+
+function! s:close_pane()
+ if b:plug_preview == 1
+ pc
+ let b:plug_preview = -1
+ else
+ bd
+ endif
+endfunction
+
+function! s:assign_name()
+ " Assign buffer name
+ let prefix = '[Plugins]'
+ let name = prefix
+ let idx = 2
+ while bufexists(name)
+ let name = printf('%s (%s)', prefix, idx)
+ let idx = idx + 1
+ endwhile
+ silent! execute 'f' fnameescape(name)
+endfunction
+
+function! s:chsh(swap)
+ let prev = [&shell, &shellcmdflag, &shellredir]
+ if !s:is_win
+ set shell=sh
+ endif
+ if a:swap
+ if s:is_powershell(&shell)
+ let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'
+ elseif &shell =~# 'sh' || &shell =~# 'cmd\(\.exe\)\?$'
+ set shellredir=>%s\ 2>&1
+ endif
+ endif
+ return prev
+endfunction
+
+function! s:bang(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(a:0)
+ " FIXME: Escaping is incomplete. We could use shellescape with eval,
+ " but it won't work on Windows.
+ let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')
+ execute "normal! :execute g:_plug_bang\<cr>\<cr>"
+ finally
+ unlet g:_plug_bang
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ return v:shell_error ? 'Exit status: ' . v:shell_error : ''
+endfunction
+
+function! s:regress_bar()
+ let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')
+ call s:progress_bar(2, bar, len(bar))
+endfunction
+
+function! s:is_updated(dir)
+ return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))
+endfunction
+
+function! s:do(pull, force, todo)
+ for [name, spec] in items(a:todo)
+ if !isdirectory(spec.dir)
+ continue
+ endif
+ let installed = has_key(s:update.new, name)
+ let updated = installed ? 0 :
+ \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))
+ if a:force || installed || updated
+ execute 'cd' s:esc(spec.dir)
+ call append(3, '- Post-update hook for '. name .' ... ')
+ let error = ''
+ let type = type(spec.do)
+ if type == s:TYPE.string
+ if spec.do[0] == ':'
+ if !get(s:loaded, name, 0)
+ let s:loaded[name] = 1
+ call s:reorg_rtp()
+ endif
+ call s:load_plugin(spec)
+ try
+ execute spec.do[1:]
+ catch
+ let error = v:exception
+ endtry
+ if !s:plug_window_exists()
+ cd -
+ throw 'Warning: vim-plug was terminated by the post-update hook of '.name
+ endif
+ else
+ let error = s:bang(spec.do)
+ endif
+ elseif type == s:TYPE.funcref
+ try
+ call s:load_plugin(spec)
+ let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')
+ call spec.do({ 'name': name, 'status': status, 'force': a:force })
+ catch
+ let error = v:exception
+ endtry
+ else
+ let error = 'Invalid hook type'
+ endif
+ call s:switch_in()
+ call setline(4, empty(error) ? (getline(4) . 'OK')
+ \ : ('x' . getline(4)[1:] . error))
+ if !empty(error)
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ endif
+ cd -
+ endif
+ endfor
+endfunction
+
+function! s:hash_match(a, b)
+ return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0
+endfunction
+
+function! s:checkout(spec)
+ let sha = a:spec.commit
+ let output = s:git_revision(a:spec.dir)
+ if !empty(output) && !s:hash_match(sha, s:lines(output)[0])
+ let credential_helper = s:git_version_requirement(2) ? '-c credential.helper= ' : ''
+ let output = s:system(
+ \ 'git '.credential_helper.'fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)
+ endif
+ return output
+endfunction
+
+function! s:finish(pull)
+ let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
+ if new_frozen
+ let s = new_frozen > 1 ? 's' : ''
+ call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
+ endif
+ call append(3, '- Finishing ... ') | 4
+ redraw
+ call plug#helptags()
+ call plug#end()
+ call setline(4, getline(4) . 'Done!')
+ redraw
+ let msgs = []
+ if !empty(s:update.errors)
+ call add(msgs, "Press 'R' to retry.")
+ endif
+ if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
+ \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'"))
+ call add(msgs, "Press 'D' to see the updated changes.")
+ endif
+ echo join(msgs, ' ')
+ call s:finish_bindings()
+endfunction
+
+function! s:retry()
+ if empty(s:update.errors)
+ return
+ endif
+ echo
+ call s:update_impl(s:update.pull, s:update.force,
+ \ extend(copy(s:update.errors), [s:update.threads]))
+endfunction
+
+function! s:is_managed(name)
+ return has_key(g:plugs[a:name], 'uri')
+endfunction
+
+function! s:names(...)
+ return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
+endfunction
+
+function! s:check_ruby()
+ silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'")
+ if !exists('g:plug_ruby')
+ redraw!
+ return s:warn('echom', 'Warning: Ruby interface is broken')
+ endif
+ let ruby_version = split(g:plug_ruby, '\.')
+ unlet g:plug_ruby
+ return s:version_requirement(ruby_version, [1, 8, 7])
+endfunction
+
+function! s:update_impl(pull, force, args) abort
+ let sync = index(a:args, '--sync') >= 0 || has('vim_starting')
+ let args = filter(copy(a:args), 'v:val != "--sync"')
+ let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
+ \ remove(args, -1) : get(g:, 'plug_threads', 16)
+
+ let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
+ let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
+ \ filter(managed, 'index(args, v:key) >= 0')
+
+ if empty(todo)
+ return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))
+ endif
+
+ if !s:is_win && s:git_version_requirement(2, 3)
+ let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''
+ let $GIT_TERMINAL_PROMPT = 0
+ for plug in values(todo)
+ let plug.uri = substitute(plug.uri,
+ \ '^https://git::@github\.com', 'https://github.com', '')
+ endfor
+ endif
+
+ if !isdirectory(g:plug_home)
+ try
+ call mkdir(g:plug_home, 'p')
+ catch
+ return s:err(printf('Invalid plug directory: %s. '.
+ \ 'Try to call plug#begin with a valid directory', g:plug_home))
+ endtry
+ endif
+
+ if has('nvim') && !exists('*jobwait') && threads > 1
+ call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')
+ endif
+
+ let use_job = s:nvim || s:vim8
+ let python = (has('python') || has('python3')) && !use_job
+ let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby()
+
+ let s:update = {
+ \ 'start': reltime(),
+ \ 'all': todo,
+ \ 'todo': copy(todo),
+ \ 'errors': [],
+ \ 'pull': a:pull,
+ \ 'force': a:force,
+ \ 'new': {},
+ \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1,
+ \ 'bar': '',
+ \ 'fin': 0
+ \ }
+
+ call s:prepare(1)
+ call append(0, ['', ''])
+ normal! 2G
+ silent! redraw
+
+ " Set remote name, overriding a possible user git config's clone.defaultRemoteName
+ let s:clone_opt = ['--origin', 'origin']
+ if get(g:, 'plug_shallow', 1)
+ call extend(s:clone_opt, ['--depth', '1'])
+ if s:git_version_requirement(1, 7, 10)
+ call add(s:clone_opt, '--no-single-branch')
+ endif
+ endif
+
+ if has('win32unix') || has('wsl')
+ call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input'])
+ endif
+
+ let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : ''
+
+ " Python version requirement (>= 2.7)
+ if python && !has('python3') && !ruby && !use_job && s:update.threads > 1
+ redir => pyv
+ silent python import platform; print platform.python_version()
+ redir END
+ let python = s:version_requirement(
+ \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
+ endif
+
+ if (python || ruby) && s:update.threads > 1
+ try
+ let imd = &imd
+ if s:mac_gui
+ set noimd
+ endif
+ if ruby
+ call s:update_ruby()
+ else
+ call s:update_python()
+ endif
+ catch
+ let lines = getline(4, '$')
+ let printed = {}
+ silent! 4,$d _
+ for line in lines
+ let name = s:extract_name(line, '.', '')
+ if empty(name) || !has_key(printed, name)
+ call append('$', line)
+ if !empty(name)
+ let printed[name] = 1
+ if line[0] == 'x' && index(s:update.errors, name) < 0
+ call add(s:update.errors, name)
+ end
+ endif
+ endif
+ endfor
+ finally
+ let &imd = imd
+ call s:update_finish()
+ endtry
+ else
+ call s:update_vim()
+ while use_job && sync
+ sleep 100m
+ if s:update.fin
+ break
+ endif
+ endwhile
+ endif
+endfunction
+
+function! s:log4(name, msg)
+ call setline(4, printf('- %s (%s)', a:msg, a:name))
+ redraw
+endfunction
+
+function! s:update_finish()
+ if exists('s:git_terminal_prompt')
+ let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
+ endif
+ if s:switch_in()
+ call append(3, '- Updating ...') | 4
+ for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))'))
+ let [pos, _] = s:logpos(name)
+ if !pos
+ continue
+ endif
+ if has_key(spec, 'commit')
+ call s:log4(name, 'Checking out '.spec.commit)
+ let out = s:checkout(spec)
+ elseif has_key(spec, 'tag')
+ let tag = spec.tag
+ if tag =~ '\*'
+ let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))
+ if !v:shell_error && !empty(tags)
+ let tag = tags[0]
+ call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))
+ call append(3, '')
+ endif
+ endif
+ call s:log4(name, 'Checking out '.tag)
+ let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)
+ else
+ let branch = s:git_origin_branch(spec)
+ call s:log4(name, 'Merging origin/'.s:esc(branch))
+ let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'
+ \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)
+ endif
+ if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&
+ \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))
+ call s:log4(name, 'Updating submodules. This may take a while.')
+ let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)
+ endif
+ let msg = s:format_message(v:shell_error ? 'x': '-', name, out)
+ if v:shell_error
+ call add(s:update.errors, name)
+ call s:regress_bar()
+ silent execute pos 'd _'
+ call append(4, msg) | 4
+ elseif !empty(out)
+ call setline(pos, msg[0])
+ endif
+ redraw
+ endfor
+ silent 4 d _
+ try
+ call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")'))
+ catch
+ call s:warn('echom', v:exception)
+ call s:warn('echo', '')
+ return
+ endtry
+ call s:finish(s:update.pull)
+ call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
+ call s:switch_out('normal! gg')
+ endif
+endfunction
+
+function! s:job_abort()
+ if (!s:nvim && !s:vim8) || !exists('s:jobs')
+ return
+ endif
+
+ for [name, j] in items(s:jobs)
+ if s:nvim
+ silent! call jobstop(j.jobid)
+ elseif s:vim8
+ silent! call job_stop(j.jobid)
+ endif
+ if j.new
+ call s:rm_rf(g:plugs[name].dir)
+ endif
+ endfor
+ let s:jobs = {}
+endfunction
+
+function! s:last_non_empty_line(lines)
+ let len = len(a:lines)
+ for idx in range(len)
+ let line = a:lines[len-idx-1]
+ if !empty(line)
+ return line
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:job_out_cb(self, data) abort
+ let self = a:self
+ let data = remove(self.lines, -1) . a:data
+ let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]')
+ call extend(self.lines, lines)
+ " To reduce the number of buffer updates
+ let self.tick = get(self, 'tick', -1) + 1
+ if !self.running || self.tick % len(s:jobs) == 0
+ let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-')
+ let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines)
+ call s:log(bullet, self.name, result)
+ endif
+endfunction
+
+function! s:job_exit_cb(self, data) abort
+ let a:self.running = 0
+ let a:self.error = a:data != 0
+ call s:reap(a:self.name)
+ call s:tick()
+endfunction
+
+function! s:job_cb(fn, job, ch, data)
+ if !s:plug_window_exists() " plug window closed
+ return s:job_abort()
+ endif
+ call call(a:fn, [a:job, a:data])
+endfunction
+
+function! s:nvim_cb(job_id, data, event) dict abort
+ return (a:event == 'stdout' || a:event == 'stderr') ?
+ \ s:job_cb('s:job_out_cb', self, 0, join(a:data, "\n")) :
+ \ s:job_cb('s:job_exit_cb', self, 0, a:data)
+endfunction
+
+function! s:spawn(name, cmd, opts)
+ let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],
+ \ 'new': get(a:opts, 'new', 0) }
+ let s:jobs[a:name] = job
+
+ if s:nvim
+ if has_key(a:opts, 'dir')
+ let job.cwd = a:opts.dir
+ endif
+ let argv = a:cmd
+ call extend(job, {
+ \ 'on_stdout': function('s:nvim_cb'),
+ \ 'on_stderr': function('s:nvim_cb'),
+ \ 'on_exit': function('s:nvim_cb'),
+ \ })
+ let jid = s:plug_call('jobstart', argv, job)
+ if jid > 0
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = [jid < 0 ? argv[0].' is not executable' :
+ \ 'Invalid arguments (or job table is full)']
+ endif
+ elseif s:vim8
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})'))
+ if has_key(a:opts, 'dir')
+ let cmd = s:with_cd(cmd, a:opts.dir, 0)
+ endif
+ let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]
+ let jid = job_start(s:is_win ? join(argv, ' ') : argv, {
+ \ 'out_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'err_cb': function('s:job_cb', ['s:job_out_cb', job]),
+ \ 'exit_cb': function('s:job_cb', ['s:job_exit_cb', job]),
+ \ 'err_mode': 'raw',
+ \ 'out_mode': 'raw'
+ \})
+ if job_status(jid) == 'run'
+ let job.jobid = jid
+ else
+ let job.running = 0
+ let job.error = 1
+ let job.lines = ['Failed to start job']
+ endif
+ else
+ let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]))
+ let job.error = v:shell_error != 0
+ let job.running = 0
+ endif
+endfunction
+
+function! s:reap(name)
+ let job = s:jobs[a:name]
+ if job.error
+ call add(s:update.errors, a:name)
+ elseif get(job, 'new', 0)
+ let s:update.new[a:name] = 1
+ endif
+ let s:update.bar .= job.error ? 'x' : '='
+
+ let bullet = job.error ? 'x' : '-'
+ let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines)
+ call s:log(bullet, a:name, empty(result) ? 'OK' : result)
+ call s:bar()
+
+ call remove(s:jobs, a:name)
+endfunction
+
+function! s:bar()
+ if s:switch_in()
+ let total = len(s:update.all)
+ call setline(1, (s:update.pull ? 'Updating' : 'Installing').
+ \ ' plugins ('.len(s:update.bar).'/'.total.')')
+ call s:progress_bar(2, s:update.bar, total)
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:logpos(name)
+ let max = line('$')
+ for i in range(4, max > 4 ? max : 4)
+ if getline(i) =~# '^[-+x*] '.a:name.':'
+ for j in range(i + 1, max > 5 ? max : 5)
+ if getline(j) !~ '^ '
+ return [i, j - 1]
+ endif
+ endfor
+ return [i, i]
+ endif
+ endfor
+ return [0, 0]
+endfunction
+
+function! s:log(bullet, name, lines)
+ if s:switch_in()
+ let [b, e] = s:logpos(a:name)
+ if b > 0
+ silent execute printf('%d,%d d _', b, e)
+ if b > winheight('.')
+ let b = 4
+ endif
+ else
+ let b = 4
+ endif
+ " FIXME For some reason, nomodifiable is set after :d in vim8
+ setlocal modifiable
+ call append(b - 1, s:format_message(a:bullet, a:name, a:lines))
+ call s:switch_out()
+ endif
+endfunction
+
+function! s:update_vim()
+ let s:jobs = {}
+
+ call s:bar()
+ call s:tick()
+endfunction
+
+function! s:tick()
+ let pull = s:update.pull
+ let prog = s:progress_opt(s:nvim || s:vim8)
+while 1 " Without TCO, Vim stack is bound to explode
+ if empty(s:update.todo)
+ if empty(s:jobs) && !s:update.fin
+ call s:update_finish()
+ let s:update.fin = 1
+ endif
+ return
+ endif
+
+ let name = keys(s:update.todo)[0]
+ let spec = remove(s:update.todo, name)
+ let new = empty(globpath(spec.dir, '.git', 1))
+
+ call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
+ redraw
+
+ let has_tag = has_key(spec, 'tag')
+ if !new
+ let [error, _] = s:git_validate(spec, 0)
+ if empty(error)
+ if pull
+ let cmd = s:git_version_requirement(2) ? ['git', '-c', 'credential.helper=', 'fetch'] : ['git', 'fetch']
+ if has_tag && !empty(globpath(spec.dir, '.git/shallow'))
+ call extend(cmd, ['--depth', '99999999'])
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, cmd, { 'dir': spec.dir })
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 }
+ endif
+ else
+ let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 }
+ endif
+ else
+ let cmd = ['git', 'clone']
+ if !has_tag
+ call extend(cmd, s:clone_opt)
+ endif
+ if !empty(prog)
+ call add(cmd, prog)
+ endif
+ call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 })
+ endif
+
+ if !s:jobs[name].running
+ call s:reap(name)
+ endif
+ if len(s:jobs) >= s:update.threads
+ break
+ endif
+endwhile
+endfunction
+
+function! s:update_python()
+let py_exe = has('python') ? 'python' : 'python3'
+execute py_exe "<< EOF"
+import datetime
+import functools
+import os
+try:
+ import queue
+except ImportError:
+ import Queue as queue
+import random
+import re
+import shutil
+import signal
+import subprocess
+import tempfile
+import threading as thr
+import time
+import traceback
+import vim
+
+G_NVIM = vim.eval("has('nvim')") == '1'
+G_PULL = vim.eval('s:update.pull') == '1'
+G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
+G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
+G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt'))
+G_PROGRESS = vim.eval('s:progress_opt(1)')
+G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
+G_STOP = thr.Event()
+G_IS_WIN = vim.eval('s:is_win') == '1'
+
+class PlugError(Exception):
+ def __init__(self, msg):
+ self.msg = msg
+class CmdTimedOut(PlugError):
+ pass
+class CmdFailed(PlugError):
+ pass
+class InvalidURI(PlugError):
+ pass
+class Action(object):
+ INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']
+
+class Buffer(object):
+ def __init__(self, lock, num_plugs, is_pull):
+ self.bar = ''
+ self.event = 'Updating' if is_pull else 'Installing'
+ self.lock = lock
+ self.maxy = int(vim.eval('winheight(".")'))
+ self.num_plugs = num_plugs
+
+ def __where(self, name):
+ """ Find first line with name in current buffer. Return line num. """
+ found, lnum = False, 0
+ matcher = re.compile('^[-+x*] {0}:'.format(name))
+ for line in vim.current.buffer:
+ if matcher.search(line) is not None:
+ found = True
+ break
+ lnum += 1
+
+ if not found:
+ lnum = -1
+ return lnum
+
+ def header(self):
+ curbuf = vim.current.buffer
+ curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)
+
+ num_spaces = self.num_plugs - len(self.bar)
+ curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
+
+ with self.lock:
+ vim.command('normal! 2G')
+ vim.command('redraw')
+
+ def write(self, action, name, lines):
+ first, rest = lines[0], lines[1:]
+ msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
+ msg.extend([' ' + line for line in rest])
+
+ try:
+ if action == Action.ERROR:
+ self.bar += 'x'
+ vim.command("call add(s:update.errors, '{0}')".format(name))
+ elif action == Action.DONE:
+ self.bar += '='
+
+ curbuf = vim.current.buffer
+ lnum = self.__where(name)
+ if lnum != -1: # Found matching line num
+ del curbuf[lnum]
+ if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):
+ lnum = 3
+ else:
+ lnum = 3
+ curbuf.append(msg, lnum)
+
+ self.header()
+ except vim.error:
+ pass
+
+class Command(object):
+ CD = 'cd /d' if G_IS_WIN else 'cd'
+
+ def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None):
+ self.cmd = cmd
+ if cmd_dir:
+ self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd)
+ self.timeout = timeout
+ self.callback = cb if cb else (lambda msg: None)
+ self.clean = clean if clean else (lambda: None)
+ self.proc = None
+
+ @property
+ def alive(self):
+ """ Returns true only if command still running. """
+ return self.proc and self.proc.poll() is None
+
+ def execute(self, ntries=3):
+ """ Execute the command with ntries if CmdTimedOut.
+ Returns the output of the command if no Exception.
+ """
+ attempt, finished, limit = 0, False, self.timeout
+
+ while not finished:
+ try:
+ attempt += 1
+ result = self.try_command()
+ finished = True
+ return result
+ except CmdTimedOut:
+ if attempt != ntries:
+ self.notify_retry()
+ self.timeout += limit
+ else:
+ raise
+
+ def notify_retry(self):
+ """ Retry required for command, notify user. """
+ for count in range(3, 0, -1):
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+ msg = 'Timeout. Will retry in {0} second{1} ...'.format(
+ count, 's' if count != 1 else '')
+ self.callback([msg])
+ time.sleep(1)
+ self.callback(['Retrying ...'])
+
+ def try_command(self):
+ """ Execute a cmd & poll for callback. Returns list of output.
+ Raises CmdFailed -> return code for Popen isn't 0
+ Raises CmdTimedOut -> command exceeded timeout without new output
+ """
+ first_line = True
+
+ try:
+ tfile = tempfile.NamedTemporaryFile(mode='w+b')
+ preexec_fn = not G_IS_WIN and os.setsid or None
+ self.proc = subprocess.Popen(self.cmd, stdout=tfile,
+ stderr=subprocess.STDOUT,
+ stdin=subprocess.PIPE, shell=True,
+ preexec_fn=preexec_fn)
+ thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,))
+ thrd.start()
+
+ thread_not_started = True
+ while thread_not_started:
+ try:
+ thrd.join(0.1)
+ thread_not_started = False
+ except RuntimeError:
+ pass
+
+ while self.alive:
+ if G_STOP.is_set():
+ raise KeyboardInterrupt
+
+ if first_line or random.random() < G_LOG_PROB:
+ first_line = False
+ line = '' if G_IS_WIN else nonblock_read(tfile.name)
+ if line:
+ self.callback([line])
+
+ time_diff = time.time() - os.path.getmtime(tfile.name)
+ if time_diff > self.timeout:
+ raise CmdTimedOut(['Timeout!'])
+
+ thrd.join(0.5)
+
+ tfile.seek(0)
+ result = [line.decode('utf-8', 'replace').rstrip() for line in tfile]
+
+ if self.proc.returncode != 0:
+ raise CmdFailed([''] + result)
+
+ return result
+ except:
+ self.terminate()
+ raise
+
+ def terminate(self):
+ """ Terminate process and cleanup. """
+ if self.alive:
+ if G_IS_WIN:
+ os.kill(self.proc.pid, signal.SIGINT)
+ else:
+ os.killpg(self.proc.pid, signal.SIGTERM)
+ self.clean()
+
+class Plugin(object):
+ def __init__(self, name, args, buf_q, lock):
+ self.name = name
+ self.args = args
+ self.buf_q = buf_q
+ self.lock = lock
+ self.tag = args.get('tag', 0)
+
+ def manage(self):
+ try:
+ if os.path.exists(self.args['dir']):
+ self.update()
+ else:
+ self.install()
+ with self.lock:
+ thread_vim_command("let s:update.new['{0}'] = 1".format(self.name))
+ except PlugError as exc:
+ self.write(Action.ERROR, self.name, exc.msg)
+ except KeyboardInterrupt:
+ G_STOP.set()
+ self.write(Action.ERROR, self.name, ['Interrupted!'])
+ except:
+ # Any exception except those above print stack trace
+ msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())
+ self.write(Action.ERROR, self.name, msg.split('\n'))
+ raise
+
+ def install(self):
+ target = self.args['dir']
+ if target[-1] == '\\':
+ target = target[0:-1]
+
+ def clean(target):
+ def _clean():
+ try:
+ shutil.rmtree(target)
+ except OSError:
+ pass
+ return _clean
+
+ self.write(Action.INSTALL, self.name, ['Installing ...'])
+ callback = functools.partial(self.write, Action.INSTALL, self.name)
+ cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(
+ '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],
+ esc(target))
+ com = Command(cmd, None, G_TIMEOUT, callback, clean(target))
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+
+ def repo_uri(self):
+ cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'
+ command = Command(cmd, self.args['dir'], G_TIMEOUT,)
+ result = command.execute(G_RETRIES)
+ return result[-1]
+
+ def update(self):
+ actual_uri = self.repo_uri()
+ expect_uri = self.args['uri']
+ regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$')
+ ma = regex.match(actual_uri)
+ mb = regex.match(expect_uri)
+ if ma is None or mb is None or ma.groups() != mb.groups():
+ msg = ['',
+ 'Invalid URI: {0}'.format(actual_uri),
+ 'Expected {0}'.format(expect_uri),
+ 'PlugClean required.']
+ raise InvalidURI(msg)
+
+ if G_PULL:
+ self.write(Action.UPDATE, self.name, ['Updating ...'])
+ callback = functools.partial(self.write, Action.UPDATE, self.name)
+ fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''
+ cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)
+ com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)
+ result = com.execute(G_RETRIES)
+ self.write(Action.DONE, self.name, result[-1:])
+ else:
+ self.write(Action.DONE, self.name, ['Already installed'])
+
+ def write(self, action, name, msg):
+ self.buf_q.put((action, name, msg))
+
+class PlugThread(thr.Thread):
+ def __init__(self, tname, args):
+ super(PlugThread, self).__init__()
+ self.tname = tname
+ self.args = args
+
+ def run(self):
+ thr.current_thread().name = self.tname
+ buf_q, work_q, lock = self.args
+
+ try:
+ while not G_STOP.is_set():
+ name, args = work_q.get_nowait()
+ plug = Plugin(name, args, buf_q, lock)
+ plug.manage()
+ work_q.task_done()
+ except queue.Empty:
+ pass
+
+class RefreshThread(thr.Thread):
+ def __init__(self, lock):
+ super(RefreshThread, self).__init__()
+ self.lock = lock
+ self.running = True
+
+ def run(self):
+ while self.running:
+ with self.lock:
+ thread_vim_command('noautocmd normal! a')
+ time.sleep(0.33)
+
+ def stop(self):
+ self.running = False
+
+if G_NVIM:
+ def thread_vim_command(cmd):
+ vim.session.threadsafe_call(lambda: vim.command(cmd))
+else:
+ def thread_vim_command(cmd):
+ vim.command(cmd)
+
+def esc(name):
+ return '"' + name.replace('"', '\"') + '"'
+
+def nonblock_read(fname):
+ """ Read a file with nonblock flag. Return the last line. """
+ fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)
+ buf = os.read(fread, 100000).decode('utf-8', 'replace')
+ os.close(fread)
+
+ line = buf.rstrip('\r\n')
+ left = max(line.rfind('\r'), line.rfind('\n'))
+ if left != -1:
+ left += 1
+ line = line[left:]
+
+ return line
+
+def main():
+ thr.current_thread().name = 'main'
+ nthreads = int(vim.eval('s:update.threads'))
+ plugs = vim.eval('s:update.todo')
+ mac_gui = vim.eval('s:mac_gui') == '1'
+
+ lock = thr.Lock()
+ buf = Buffer(lock, len(plugs), G_PULL)
+ buf_q, work_q = queue.Queue(), queue.Queue()
+ for work in plugs.items():
+ work_q.put(work)
+
+ start_cnt = thr.active_count()
+ for num in range(nthreads):
+ tname = 'PlugT-{0:02}'.format(num)
+ thread = PlugThread(tname, (buf_q, work_q, lock))
+ thread.start()
+ if mac_gui:
+ rthread = RefreshThread(lock)
+ rthread.start()
+
+ while not buf_q.empty() or thr.active_count() != start_cnt:
+ try:
+ action, name, msg = buf_q.get(True, 0.25)
+ buf.write(action, name, ['OK'] if not msg else msg)
+ buf_q.task_done()
+ except queue.Empty:
+ pass
+ except KeyboardInterrupt:
+ G_STOP.set()
+
+ if mac_gui:
+ rthread.stop()
+ rthread.join()
+
+main()
+EOF
+endfunction
+
+function! s:update_ruby()
+ ruby << EOF
+ module PlugStream
+ SEP = ["\r", "\n", nil]
+ def get_line
+ buffer = ''
+ loop do
+ char = readchar rescue return
+ if SEP.include? char.chr
+ buffer << $/
+ break
+ else
+ buffer << char
+ end
+ end
+ buffer
+ end
+ end unless defined?(PlugStream)
+
+ def esc arg
+ %["#{arg.gsub('"', '\"')}"]
+ end
+
+ def killall pid
+ pids = [pid]
+ if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil }
+ else
+ unless `which pgrep 2> /dev/null`.empty?
+ children = pids
+ until children.empty?
+ children = children.map { |pid|
+ `pgrep -P #{pid}`.lines.map { |l| l.chomp }
+ }.flatten
+ pids += children
+ end
+ end
+ pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
+ end
+ end
+
+ def compare_git_uri a, b
+ regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$}
+ regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1)
+ end
+
+ require 'thread'
+ require 'fileutils'
+ require 'timeout'
+ running = true
+ iswin = VIM::evaluate('s:is_win').to_i == 1
+ pull = VIM::evaluate('s:update.pull').to_i == 1
+ base = VIM::evaluate('g:plug_home')
+ all = VIM::evaluate('s:update.todo')
+ limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
+ tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
+ nthr = VIM::evaluate('s:update.threads').to_i
+ maxy = VIM::evaluate('winheight(".")').to_i
+ vim7 = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/
+ cd = iswin ? 'cd /d' : 'cd'
+ tot = VIM::evaluate('len(s:update.todo)') || 0
+ bar = ''
+ skip = 'Already installed'
+ mtx = Mutex.new
+ take1 = proc { mtx.synchronize { running && all.shift } }
+ logh = proc {
+ cnt = bar.length
+ $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
+ $curbuf[2] = '[' + bar.ljust(tot) + ']'
+ VIM::command('normal! 2G')
+ VIM::command('redraw')
+ }
+ where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }
+ log = proc { |name, result, type|
+ mtx.synchronize do
+ ing = ![true, false].include?(type)
+ bar += type ? '=' : 'x' unless ing
+ b = case type
+ when :install then '+' when :update then '*'
+ when true, nil then '-' else
+ VIM::command("call add(s:update.errors, '#{name}')")
+ 'x'
+ end
+ result =
+ if type || type.nil?
+ ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]
+ elsif result =~ /^Interrupted|^Timeout/
+ ["#{b} #{name}: #{result}"]
+ else
+ ["#{b} #{name}"] + result.lines.map { |l| " " << l }
+ end
+ if lnum = where.call(name)
+ $curbuf.delete lnum
+ lnum = 4 if ing && lnum > maxy
+ end
+ result.each_with_index do |line, offset|
+ $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)
+ end
+ logh.call
+ end
+ }
+ bt = proc { |cmd, name, type, cleanup|
+ tried = timeout = 0
+ begin
+ tried += 1
+ timeout += limit
+ fd = nil
+ data = ''
+ if iswin
+ Timeout::timeout(timeout) do
+ tmp = VIM::evaluate('tempname()')
+ system("(#{cmd}) > #{tmp}")
+ data = File.read(tmp).chomp
+ File.unlink tmp rescue nil
+ end
+ else
+ fd = IO.popen(cmd).extend(PlugStream)
+ first_line = true
+ log_prob = 1.0 / nthr
+ while line = Timeout::timeout(timeout) { fd.get_line }
+ data << line
+ log.call name, line.chomp, type if name && (first_line || rand < log_prob)
+ first_line = false
+ end
+ fd.close
+ end
+ [$? == 0, data.chomp]
+ rescue Timeout::Error, Interrupt => e
+ if fd && !fd.closed?
+ killall fd.pid
+ fd.close
+ end
+ cleanup.call if cleanup
+ if e.is_a?(Timeout::Error) && tried < tries
+ 3.downto(1) do |countdown|
+ s = countdown > 1 ? 's' : ''
+ log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type
+ sleep 1
+ end
+ log.call name, 'Retrying ...', type
+ retry
+ end
+ [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
+ end
+ }
+ main = Thread.current
+ threads = []
+ watcher = Thread.new {
+ if vim7
+ while VIM::evaluate('getchar(1)')
+ sleep 0.1
+ end
+ else
+ require 'io/console' # >= Ruby 1.9
+ nil until IO.console.getch == 3.chr
+ end
+ mtx.synchronize do
+ running = false
+ threads.each { |t| t.raise Interrupt } unless vim7
+ end
+ threads.each { |t| t.join rescue nil }
+ main.kill
+ }
+ refresh = Thread.new {
+ while true
+ mtx.synchronize do
+ break unless running
+ VIM::command('noautocmd normal! a')
+ end
+ sleep 0.2
+ end
+ } if VIM::evaluate('s:mac_gui') == 1
+
+ clone_opt = VIM::evaluate('s:clone_opt').join(' ')
+ progress = VIM::evaluate('s:progress_opt(1)')
+ nthr.times do
+ mtx.synchronize do
+ threads << Thread.new {
+ while pair = take1.call
+ name = pair.first
+ dir, uri, tag = pair.last.values_at *%w[dir uri tag]
+ exists = File.directory? dir
+ ok, result =
+ if exists
+ chdir = "#{cd} #{iswin ? dir : esc(dir)}"
+ ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil
+ current_uri = data.lines.to_a.last
+ if !ret
+ if data =~ /^Interrupted|^Timeout/
+ [false, data]
+ else
+ [false, [data.chomp, "PlugClean required."].join($/)]
+ end
+ elsif !compare_git_uri(current_uri, uri)
+ [false, ["Invalid URI: #{current_uri}",
+ "Expected: #{uri}",
+ "PlugClean required."].join($/)]
+ else
+ if pull
+ log.call name, 'Updating ...', :update
+ fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''
+ bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil
+ else
+ [true, skip]
+ end
+ end
+ else
+ d = esc dir.sub(%r{[\\/]+$}, '')
+ log.call name, 'Installing ...', :install
+ bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {
+ FileUtils.rm_rf dir
+ }
+ end
+ mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
+ log.call name, result, ok
+ end
+ } if running
+ end
+ end
+ threads.each { |t| t.join rescue nil }
+ logh.call
+ refresh.kill if refresh
+ watcher.kill
+EOF
+endfunction
+
+function! s:shellesc_cmd(arg, script)
+ let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g')
+ return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g')
+endfunction
+
+function! s:shellesc_ps1(arg)
+ return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'"
+endfunction
+
+function! s:shellesc_sh(arg)
+ return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"
+endfunction
+
+" Escape the shell argument based on the shell.
+" Vim and Neovim's shellescape() are insufficient.
+" 1. shellslash determines whether to use single/double quotes.
+" Double-quote escaping is fragile for cmd.exe.
+" 2. It does not work for powershell.
+" 3. It does not work for *sh shells if the command is executed
+" via cmd.exe (ie. cmd.exe /c sh -c command command_args)
+" 4. It does not support batchfile syntax.
+"
+" Accepts an optional dictionary with the following keys:
+" - shell: same as Vim/Neovim 'shell' option.
+" If unset, fallback to 'cmd.exe' on Windows or 'sh'.
+" - script: If truthy and shell is cmd.exe, escape for batchfile syntax.
+function! plug#shellescape(arg, ...)
+ if a:arg =~# '^[A-Za-z0-9_/:.-]\+$'
+ return a:arg
+ endif
+ let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}
+ let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')
+ let script = get(opts, 'script', 1)
+ if shell =~# 'cmd\(\.exe\)\?$'
+ return s:shellesc_cmd(a:arg, script)
+ elseif s:is_powershell(shell)
+ return s:shellesc_ps1(a:arg)
+ endif
+ return s:shellesc_sh(a:arg)
+endfunction
+
+function! s:glob_dir(path)
+ return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
+endfunction
+
+function! s:progress_bar(line, bar, total)
+ call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')
+endfunction
+
+function! s:compare_git_uri(a, b)
+ " See `git help clone'
+ " https:// [user@] github.com[:port] / junegunn/vim-plug [.git]
+ " [git@] github.com[:port] : junegunn/vim-plug [.git]
+ " file:// / junegunn/vim-plug [/]
+ " / junegunn/vim-plug [/]
+ let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$'
+ let ma = matchlist(a:a, pat)
+ let mb = matchlist(a:b, pat)
+ return ma[1:2] ==# mb[1:2]
+endfunction
+
+function! s:format_message(bullet, name, message)
+ if a:bullet != 'x'
+ return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
+ else
+ let lines = map(s:lines(a:message), '" ".v:val')
+ return extend([printf('x %s:', a:name)], lines)
+ endif
+endfunction
+
+function! s:with_cd(cmd, dir, ...)
+ let script = a:0 > 0 ? a:1 : 1
+ return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd)
+endfunction
+
+function! s:system(cmd, ...)
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ if type(a:cmd) == s:TYPE.list
+ " Neovim's system() supports list argument to bypass the shell
+ " but it cannot set the working directory for the command.
+ " Assume that the command does not rely on the shell.
+ if has('nvim') && a:0 == 0
+ return system(a:cmd)
+ endif
+ let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))
+ if s:is_powershell(&shell)
+ let cmd = '& ' . cmd
+ endif
+ else
+ let cmd = a:cmd
+ endif
+ if a:0 > 0
+ let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)
+ endif
+ if s:is_win && type(a:cmd) != s:TYPE.list
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ return system(cmd)
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+endfunction
+
+function! s:system_chomp(...)
+ let ret = call('s:system', a:000)
+ return v:shell_error ? '' : substitute(ret, '\n$', '', '')
+endfunction
+
+function! s:git_validate(spec, check_branch)
+ let err = ''
+ if isdirectory(a:spec.dir)
+ let result = [s:git_local_branch(a:spec.dir), s:git_origin_url(a:spec.dir)]
+ let remote = result[-1]
+ if empty(remote)
+ let err = join([remote, 'PlugClean required.'], "\n")
+ elseif !s:compare_git_uri(remote, a:spec.uri)
+ let err = join(['Invalid URI: '.remote,
+ \ 'Expected: '.a:spec.uri,
+ \ 'PlugClean required.'], "\n")
+ elseif a:check_branch && has_key(a:spec, 'commit')
+ let sha = s:git_revision(a:spec.dir)
+ if empty(sha)
+ let err = join(add(result, 'PlugClean required.'), "\n")
+ elseif !s:hash_match(sha, a:spec.commit)
+ let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',
+ \ a:spec.commit[:6], sha[:6]),
+ \ 'PlugUpdate required.'], "\n")
+ endif
+ elseif a:check_branch
+ let current_branch = result[0]
+ " Check tag
+ let origin_branch = s:git_origin_branch(a:spec)
+ if has_key(a:spec, 'tag')
+ let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
+ if a:spec.tag !=# tag && a:spec.tag !~ '\*'
+ let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
+ \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
+ endif
+ " Check branch
+ elseif origin_branch !=# current_branch
+ let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
+ \ current_branch, origin_branch)
+ endif
+ if empty(err)
+ let [ahead, behind] = split(s:lastline(s:system([
+ \ 'git', 'rev-list', '--count', '--left-right',
+ \ printf('HEAD...origin/%s', origin_branch)
+ \ ], a:spec.dir)), '\t')
+ if !v:shell_error && ahead
+ if behind
+ " Only mention PlugClean if diverged, otherwise it's likely to be
+ " pushable (and probably not that messed up).
+ let err = printf(
+ \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"
+ \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', origin_branch, ahead, behind)
+ else
+ let err = printf("Ahead of origin/%s by %d commit(s).\n"
+ \ .'Cannot update until local changes are pushed.',
+ \ origin_branch, ahead)
+ endif
+ endif
+ endif
+ endif
+ else
+ let err = 'Not found'
+ endif
+ return [err, err =~# 'PlugClean']
+endfunction
+
+function! s:rm_rf(dir)
+ if isdirectory(a:dir)
+ return s:system(s:is_win
+ \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)
+ \ : ['rm', '-rf', a:dir])
+ endif
+endfunction
+
+function! s:clean(force)
+ call s:prepare()
+ call append(0, 'Searching for invalid plugins in '.g:plug_home)
+ call append(1, '')
+
+ " List of valid directories
+ let dirs = []
+ let errs = {}
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ if !s:is_managed(name)
+ call add(dirs, spec.dir)
+ else
+ let [err, clean] = s:git_validate(spec, 1)
+ if clean
+ let errs[spec.dir] = s:lines(err)[0]
+ else
+ call add(dirs, spec.dir)
+ endif
+ endif
+ let cnt += 1
+ call s:progress_bar(2, repeat('=', cnt), total)
+ normal! 2G
+ redraw
+ endfor
+
+ let allowed = {}
+ for dir in dirs
+ let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1
+ let allowed[dir] = 1
+ for child in s:glob_dir(dir)
+ let allowed[child] = 1
+ endfor
+ endfor
+
+ let todo = []
+ let found = sort(s:glob_dir(g:plug_home))
+ while !empty(found)
+ let f = remove(found, 0)
+ if !has_key(allowed, f) && isdirectory(f)
+ call add(todo, f)
+ call append(line('$'), '- ' . f)
+ if has_key(errs, f)
+ call append(line('$'), ' ' . errs[f])
+ endif
+ let found = filter(found, 'stridx(v:val, f) != 0')
+ end
+ endwhile
+
+ 4
+ redraw
+ if empty(todo)
+ call append(line('$'), 'Already clean.')
+ else
+ let s:clean_count = 0
+ call append(3, ['Directories to delete:', ''])
+ redraw!
+ if a:force || s:ask_no_interrupt('Delete all directories?')
+ call s:delete([6, line('$')], 1)
+ else
+ call setline(4, 'Cancelled.')
+ nnoremap <silent> <buffer> d :set opfunc=<sid>delete_op<cr>g@
+ nmap <silent> <buffer> dd d_
+ xnoremap <silent> <buffer> d :<c-u>call <sid>delete_op(visualmode(), 1)<cr>
+ echo 'Delete the lines (d{motion}) to delete the corresponding directories'
+ endif
+ endif
+ 4
+ setlocal nomodifiable
+endfunction
+
+function! s:delete_op(type, ...)
+ call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0)
+endfunction
+
+function! s:delete(range, force)
+ let [l1, l2] = a:range
+ let force = a:force
+ let err_count = 0
+ while l1 <= l2
+ let line = getline(l1)
+ if line =~ '^- ' && isdirectory(line[2:])
+ execute l1
+ redraw!
+ let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)
+ let force = force || answer > 1
+ if answer
+ let err = s:rm_rf(line[2:])
+ setlocal modifiable
+ if empty(err)
+ call setline(l1, '~'.line[1:])
+ let s:clean_count += 1
+ else
+ delete _
+ call append(l1 - 1, s:format_message('x', line[1:], err))
+ let l2 += len(s:lines(err))
+ let err_count += 1
+ endif
+ let msg = printf('Removed %d directories.', s:clean_count)
+ if err_count > 0
+ let msg .= printf(' Failed to remove %d directories.', err_count)
+ endif
+ call setline(4, msg)
+ setlocal nomodifiable
+ endif
+ endif
+ let l1 += 1
+ endwhile
+endfunction
+
+function! s:upgrade()
+ echo 'Downloading the latest version of vim-plug'
+ redraw
+ let tmp = s:plug_tempname()
+ let new = tmp . '/plug.vim'
+
+ try
+ let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])
+ if v:shell_error
+ return s:err('Error upgrading vim-plug: '. out)
+ endif
+
+ if readfile(s:me) ==# readfile(new)
+ echo 'vim-plug is already up-to-date'
+ return 0
+ else
+ call rename(s:me, s:me . '.old')
+ call rename(new, s:me)
+ unlet g:loaded_plug
+ echo 'vim-plug has been upgraded'
+ return 1
+ endif
+ finally
+ silent! call s:rm_rf(tmp)
+ endtry
+endfunction
+
+function! s:upgrade_specs()
+ for spec in values(g:plugs)
+ let spec.frozen = get(spec, 'frozen', 0)
+ endfor
+endfunction
+
+function! s:status()
+ call s:prepare()
+ call append(0, 'Checking plugins')
+ call append(1, '')
+
+ let ecnt = 0
+ let unloaded = 0
+ let [cnt, total] = [0, len(g:plugs)]
+ for [name, spec] in items(g:plugs)
+ let is_dir = isdirectory(spec.dir)
+ if has_key(spec, 'uri')
+ if is_dir
+ let [err, _] = s:git_validate(spec, 1)
+ let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]
+ else
+ let [valid, msg] = [0, 'Not found. Try PlugInstall.']
+ endif
+ else
+ if is_dir
+ let [valid, msg] = [1, 'OK']
+ else
+ let [valid, msg] = [0, 'Not found.']
+ endif
+ endif
+ let cnt += 1
+ let ecnt += !valid
+ " `s:loaded` entry can be missing if PlugUpgraded
+ if is_dir && get(s:loaded, name, -1) == 0
+ let unloaded = 1
+ let msg .= ' (not loaded)'
+ endif
+ call s:progress_bar(2, repeat('=', cnt), total)
+ call append(3, s:format_message(valid ? '-' : 'x', name, msg))
+ normal! 2G
+ redraw
+ endfor
+ call setline(1, 'Finished. '.ecnt.' error(s).')
+ normal! gg
+ setlocal nomodifiable
+ if unloaded
+ echo "Press 'L' on each line to load plugin, or 'U' to update"
+ nnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ xnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>
+ end
+endfunction
+
+function! s:extract_name(str, prefix, suffix)
+ return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$')
+endfunction
+
+function! s:status_load(lnum)
+ let line = getline(a:lnum)
+ let name = s:extract_name(line, '-', '(not loaded)')
+ if !empty(name)
+ call plug#load(name)
+ setlocal modifiable
+ call setline(a:lnum, substitute(line, ' (not loaded)$', '', ''))
+ setlocal nomodifiable
+ endif
+endfunction
+
+function! s:status_update() range
+ let lines = getline(a:firstline, a:lastline)
+ let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)')
+ if !empty(names)
+ echo
+ execute 'PlugUpdate' join(names)
+ endif
+endfunction
+
+function! s:is_preview_window_open()
+ silent! wincmd P
+ if &previewwindow
+ wincmd p
+ return 1
+ endif
+endfunction
+
+function! s:find_name(lnum)
+ for lnum in reverse(range(1, a:lnum))
+ let line = getline(lnum)
+ if empty(line)
+ return ''
+ endif
+ let name = s:extract_name(line, '-', '')
+ if !empty(name)
+ return name
+ endif
+ endfor
+ return ''
+endfunction
+
+function! s:preview_commit()
+ if b:plug_preview < 0
+ let b:plug_preview = !s:is_preview_window_open()
+ endif
+
+ let sha = matchstr(getline('.'), '^ \X*\zs[0-9a-f]\{7,9}')
+ if empty(sha)
+ let name = matchstr(getline('.'), '^- \zs[^:]*\ze:$')
+ if empty(name)
+ return
+ endif
+ let title = 'HEAD@{1}..'
+ let command = 'git diff --no-color HEAD@{1}'
+ else
+ let title = sha
+ let command = 'git show --no-color --pretty=medium '.sha
+ let name = s:find_name(line('.'))
+ endif
+
+ if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir)
+ return
+ endif
+
+ if exists('g:plug_pwindow') && !s:is_preview_window_open()
+ execute g:plug_pwindow
+ execute 'e' title
+ else
+ execute 'pedit' title
+ wincmd P
+ endif
+ setlocal previewwindow filetype=git buftype=nofile bufhidden=wipe nobuflisted modifiable
+ let batchfile = ''
+ try
+ let [sh, shellcmdflag, shrd] = s:chsh(1)
+ let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && '.command
+ if s:is_win
+ let [batchfile, cmd] = s:batchfile(cmd)
+ endif
+ execute 'silent %!' cmd
+ finally
+ let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]
+ if s:is_win && filereadable(batchfile)
+ call delete(batchfile)
+ endif
+ endtry
+ setlocal nomodifiable
+ nnoremap <silent> <buffer> q :q<cr>
+ wincmd p
+endfunction
+
+function! s:section(flags)
+ call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
+endfunction
+
+function! s:format_git_log(line)
+ let indent = ' '
+ let tokens = split(a:line, nr2char(1))
+ if len(tokens) != 5
+ return indent.substitute(a:line, '\s*$', '', '')
+ endif
+ let [graph, sha, refs, subject, date] = tokens
+ let tag = matchstr(refs, 'tag: [^,)]\+')
+ let tag = empty(tag) ? ' ' : ' ('.tag.') '
+ return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)
+endfunction
+
+function! s:append_ul(lnum, text)
+ call append(a:lnum, ['', a:text, repeat('-', len(a:text))])
+endfunction
+
+function! s:diff()
+ call s:prepare()
+ call append(0, ['Collecting changes ...', ''])
+ let cnts = [0, 0]
+ let bar = ''
+ let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')
+ call s:progress_bar(2, bar, len(total))
+ for origin in [1, 0]
+ let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))
+ if empty(plugs)
+ continue
+ endif
+ call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')
+ for [k, v] in plugs
+ let branch = s:git_origin_branch(v)
+ if len(branch)
+ let range = origin ? '..origin/'.branch : 'HEAD@{1}..'
+ let cmd = ['git', 'log', '--graph', '--color=never']
+ if s:git_version_requirement(2, 10, 0)
+ call add(cmd, '--no-show-signature')
+ endif
+ call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])
+ if has_key(v, 'rtp')
+ call extend(cmd, ['--', v.rtp])
+ endif
+ let diff = s:system_chomp(cmd, v.dir)
+ if !empty(diff)
+ let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''
+ call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))
+ let cnts[origin] += 1
+ endif
+ endif
+ let bar .= '='
+ call s:progress_bar(2, bar, len(total))
+ normal! 2G
+ redraw
+ endfor
+ if !cnts[origin]
+ call append(5, ['', 'N/A'])
+ endif
+ endfor
+ call setline(1, printf('%d plugin(s) updated.', cnts[0])
+ \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : ''))
+
+ if cnts[0] || cnts[1]
+ nnoremap <silent> <buffer> <plug>(plug-preview) :silent! call <SID>preview_commit()<cr>
+ if empty(maparg("\<cr>", 'n'))
+ nmap <buffer> <cr> <plug>(plug-preview)
+ endif
+ if empty(maparg('o', 'n'))
+ nmap <buffer> o <plug>(plug-preview)
+ endif
+ endif
+ if cnts[0]
+ nnoremap <silent> <buffer> X :call <SID>revert()<cr>
+ echo "Press 'X' on each block to revert the update"
+ endif
+ normal! gg
+ setlocal nomodifiable
+endfunction
+
+function! s:revert()
+ if search('^Pending updates', 'bnW')
+ return
+ endif
+
+ let name = s:find_name(line('.'))
+ if empty(name) || !has_key(g:plugs, name) ||
+ \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
+ return
+ endif
+
+ call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir)
+ setlocal modifiable
+ normal! "_dap
+ setlocal nomodifiable
+ echo 'Reverted'
+endfunction
+
+function! s:snapshot(force, ...) abort
+ call s:prepare()
+ setf vim
+ call append(0, ['" Generated by vim-plug',
+ \ '" '.strftime("%c"),
+ \ '" :source this file in vim to restore the snapshot',
+ \ '" or execute: vim -S snapshot.vim',
+ \ '', '', 'PlugUpdate!'])
+ 1
+ let anchor = line('$') - 3
+ let names = sort(keys(filter(copy(g:plugs),
+ \'has_key(v:val, "uri") && isdirectory(v:val.dir)')))
+ for name in reverse(names)
+ let sha = has_key(g:plugs[name], 'commit') ? g:plugs[name].commit : s:git_revision(g:plugs[name].dir)
+ if !empty(sha)
+ call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))
+ redraw
+ endif
+ endfor
+
+ if a:0 > 0
+ let fn = s:plug_expand(a:1)
+ if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?'))
+ return
+ endif
+ call writefile(getline(1, '$'), fn)
+ echo 'Saved as '.a:1
+ silent execute 'e' s:esc(fn)
+ setf vim
+ endif
+endfunction
+
+function! s:split_rtp()
+ return split(&rtp, '\\\@<!,')
+endfunction
+
+let s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))
+let s:last_rtp = s:escrtp(get(s:split_rtp(), -1, ''))
+
+if exists('g:plugs')
+ let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))
+ call s:upgrade_specs()
+ call s:define_commands()
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
@@ -0,0 +1,9 @@
+# Quick hack to ensure user d-bus has proper env vars
+export XDG_CURRENT_DESKTOP=sway
+export XDG_SESSION_DESKTOP=sway
+export _JAVA_AWT_WM_NONREPEATING=1
+
+# Proper stuff
+HOME_ENVIRONMENT=$HOME/.guix-home
+. $HOME_ENVIRONMENT/setup-environment
+$HOME_ENVIRONMENT/on-first-login
@@ -0,0 +1,16 @@
+Match host * exec "gpg-connect-agent UPDATESTARTUPTTY /bye"
+
+Host rocApex
+ HostName 129.158.232.104
+ User root
+
+Host linode
+ HostName 97.107.142.58
+ User root
+
+Host hetzner
+ HostName 5.161.207.21
+ User root
+
+Host *
+ KexAlgorithms -sntrup761x25519-sha512@openssh.com
Binary files /dev/null and b/home-config/sway/Wallpapers/mountains.jpg differ
@@ -0,0 +1,326 @@
+# Ryan's config for sway
+#
+# Dependencies:
+# waybar
+# fuzzel
+# light (with proper udev setting for backlight control)
+# alacritty
+# swaylock-effects
+# swayidle
+# dejavu-fonts-ttf
+# nerd-fonts-otf
+# noto-fonts-cjk
+# mako / libnotify
+# grim / slurp / wl-clipboard
+# swaybg
+# pipewire / pipewire-pulse / pipewire-jack / wireplumber
+# blueman
+# spotifyd
+# syslog-ng
+# OPTIONAL: wdisplays (monitor layout)
+# ...
+
+### Variables
+exec sh ~/.profile
+
+# Load up the user session dbus
+#exec dbus-daemon --session --address=unix:path=$XDG_RUNTIME_DIR/bus
+
+exec hash dbus-update-activation-environment 2>/dev/null && dbus-update-activation-environment DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
+
+#
+# Logo key. Use Mod1 for Alt.
+set $mod Mod4
+# Home row direction keys, like vim
+set $left h
+set $down j
+set $up k
+set $right l
+# Your preferred terminal emulator
+set $term alacritty
+# Your preferred application launcher
+# Note: pass the final command to swaymsg so that the resulting window can be opened
+# on the original workspace that the command was run on.
+#set $menu bemenu-run --no-exec | xargs swaymsg exec --
+set $menu fuzzel --width=35 --font='Hack:weight=bold:size=12' --background-color='282a36fa' --selection-color='3d4460fa' --line-height=20 --border-radius=20
+
+# Set lock screen settings
+set $lock 'swaylock --screenshots --clock --indicator --grace 3 --fade-in 1 --effect-blur 7x5 --effect-greyscale'
+# Same as above but no grace period
+set $lock_now 'swaylock --screenshots --clock --indicator --fade-in 1 --effect-blur 7x5 --effect-greyscale'
+### Output configuration
+#
+# Default wallpaper (more resolutions are available in /usr/share/backgrounds/sway/)
+output * bg ~/.config/sway/Wallpapers/mountains.jpg fill
+#
+# Example configuration:
+#
+# output HDMI-A-1 resolution 1920x1080 position 1920,0
+#
+# You can get the names of your outputs by running: swaymsg -t get_outputs (moved to ~/.config/sway/monitors)
+
+include ~/.config/sway/monitors
+
+#output eDP-1 mode 1920x1080@60.008Hz pos 1920 590
+#output HDMI-A-1 mode 1920x1080@74.972Hz pos 0 0
+
+### Idle configuration
+#
+# Example configuration:
+#
+exec swayidle -w \
+ timeout 300 $lock \
+ timeout 600 'swaymsg "output * dpms off"' resume 'swaymsg "output * dpms on"' \
+ before-sleep 'swaylock -f -c 000000'
+
+# Winkey+L lock key combo
+bindsym $mod+l exec $lock_now
+#
+#Winkey+Shift+L to lock then go to sleep. zzz must run with no passwd
+bindsym $mod+Shift+l exec 'swaylock --screenshots --clock --indicator --effect-blur 7x5 --effect-greyscale & sleep 0.5; doas zzz'
+
+# This will lock your screen after 300 seconds of inactivity, then turn off
+# your displays after another 300 seconds, and turn your screens back on when
+# resumed. It will also lock your screen before your computer goes to sleep.
+
+### Input configuration
+#
+# Example configuration:
+#
+# input "2:14:SynPS/2_Synaptics_TouchPad" {
+# dwt enabled
+# tap enabled
+# natural_scroll enabled
+# middle_emulation enabled
+# }
+#
+# You can get the names of your inputs by running: swaymsg -t get_inputs
+# Read `man 5 sway-input` for more information about this section.
+
+gaps inner 10
+
+### Key bindings
+#
+# Basics:
+#
+ # Start a terminal
+ bindsym $mod+Return exec $term
+
+ # Kill focused window
+ bindsym $mod+Shift+q kill
+
+ # Start your launcher
+ bindsym $mod+d exec $menu
+
+ # Drag floating windows by holding down $mod and left mouse button.
+ # Resize them with right mouse button + $mod.
+ # Despite the name, also works for non-floating windows.
+ # Change normal to inverse to use left mouse button for resizing and right
+ # mouse button for dragging.
+ floating_modifier $mod normal
+
+ # Reload the configuration file
+ bindsym $mod+Shift+c reload
+ #Restart your session
+ bindsym $mod+Shift+r restart
+
+ # Exit sway (logs you out of your Wayland session)
+ bindsym $mod+Shift+e exec swaynag -t warning -m 'You pressed the exit shortcut. Do you really want to exit sway? This will end your Wayland session.' -B 'Yes, exit sway' 'swaymsg exit'
+#
+# Moving around:
+#
+ # Move your focus around
+ bindsym $mod+$left focus left
+ bindsym $mod+$down focus down
+ bindsym $mod+$up focus up
+ #bindsym $mod+$right focus right
+ # Or use $mod+[up|down|left|right]
+ bindsym $mod+Left focus left
+ bindsym $mod+Down focus down
+ bindsym $mod+Up focus up
+ bindsym $mod+Right focus right
+
+ # Move the focused window with the same, but add Shift
+ bindsym $mod+Shift+$left move left
+ bindsym $mod+Shift+$down move down
+ bindsym $mod+Shift+$up move up
+ #bindsym $mod+Shift+$right move right
+ # Ditto, with arrow keys
+ bindsym $mod+Shift+Left move left
+ bindsym $mod+Shift+Down move down
+ bindsym $mod+Shift+Up move up
+ bindsym $mod+Shift+Right move right
+
+ # Since I run more than one monitor most of the time, these let me move
+ # workspaces between physical screens
+ bindsym $mod+Control+Shift+Right move workspace to output right
+ bindsym $mod+Control+Shift+Left move workspace to output left
+ # Now I could do the same with up and down but I don't have any of those
+#
+# Workspaces:
+#
+ # Switch to workspace
+ bindsym $mod+1 workspace number 1
+ bindsym $mod+2 workspace number 2
+ bindsym $mod+3 workspace number 3
+ bindsym $mod+4 workspace number 4
+ bindsym $mod+5 workspace number 5
+ bindsym $mod+6 workspace number 6
+ bindsym $mod+7 workspace number 7
+ bindsym $mod+8 workspace number 8
+ bindsym $mod+9 workspace number 9
+ bindsym $mod+0 workspace number 10
+ # Move focused container to workspace
+ bindsym $mod+Shift+1 move container to workspace number 1
+ bindsym $mod+Shift+2 move container to workspace number 2
+ bindsym $mod+Shift+3 move container to workspace number 3
+ bindsym $mod+Shift+4 move container to workspace number 4
+ bindsym $mod+Shift+5 move container to workspace number 5
+ bindsym $mod+Shift+6 move container to workspace number 6
+ bindsym $mod+Shift+7 move container to workspace number 7
+ bindsym $mod+Shift+8 move container to workspace number 8
+ bindsym $mod+Shift+9 move container to workspace number 9
+ bindsym $mod+Shift+0 move container to workspace number 10
+ # Note: workspaces can have any name you want, not just numbers.
+ # We just use 1-10 as the default.
+#
+# Layout stuff:
+#
+ # You can "split" the current object of your focus with
+ # $mod+b or $mod+v, for horizontal and vertical splits
+ # respectively.
+ bindsym $mod+b splith
+ bindsym $mod+v splitv
+
+ # Switch the current container between different layout styles
+ bindsym $mod+s layout stacking
+ bindsym $mod+w layout tabbed
+ bindsym $mod+e layout toggle split
+
+ # Make the current focus fullscreen
+ bindsym $mod+f fullscreen
+
+ # Toggle the current focus between tiling and floating mode
+ bindsym $mod+Shift+space floating toggle
+
+ # Swap focus between the tiling area and the floating area
+ bindsym $mod+space focus mode_toggle
+
+ # Move focus to the parent container
+ bindsym $mod+a focus parent
+
+ bindsym $mod+Ctrl+Right focus sibling next
+
+#
+# Misc. button bindings
+#
+ # Some custom keybinds for various keys on my laptop
+ bindsym XF86MonBrightnessUp exec light -A 10
+ bindsym XF86MonBrightnessDown exec light -U 10
+
+#
+# Scratchpad:
+#
+ # Sway has a "scratchpad", which is a bag of holding for windows.
+ # You can send windows there and get them back later.
+
+ # Move the currently focused window to the scratchpad
+ bindsym $mod+Shift+minus move scratchpad
+
+ # Show the next scratchpad window or hide the focused scratchpad window.
+ # If there are multiple scratchpad windows, this command cycles through them.
+ bindsym $mod+minus scratchpad show
+#
+# Resizing containers:
+#
+mode "resize" {
+ # left will shrink the containers width
+ # right will grow the containers width
+ # up will shrink the containers height
+ # down will grow the containers height
+ bindsym $left resize shrink width 10px
+ bindsym $down resize grow height 10px
+ bindsym $up resize shrink height 10px
+ bindsym $right resize grow width 10px
+
+ # Ditto, with arrow keys
+ bindsym Left resize shrink width 10px
+ bindsym Down resize grow height 10px
+ bindsym Up resize shrink height 10px
+ bindsym Right resize grow width 10px
+
+ # Return to default mode
+ bindsym Return mode "default"
+ bindsym Escape mode "default"
+}
+bindsym $mod+r mode "resize"
+
+#
+# Status Bar:
+#
+# Read `man 5 sway-bar` for more information about this section.
+#bar {
+# position top
+#
+# # When the status_command prints a new line to stdout, swaybar updates.
+# # The default just shows the current date and time.
+# status_command while date +'%Y-%m-%d %I:%M:%S %p'; do sleep 1; done
+#
+# colors {
+# statusline #ffffff
+# background #323232
+# inactive_workspace #32323200 #32323200 #5c5c5c
+# }
+#}
+
+bar {
+ swaybar_command waybar
+}
+
+
+# Numlock on startup
+input * xkb_numlock enabled
+
+# Bluetooth
+exec blueman-applet
+
+# Audio Server
+#exec pipewire
+#exec wireplumber
+#exec pipewire-pulse
+
+# Spotifyd
+#exec spotifyd
+
+# Notification controls
+exec mako
+bindsym $mod+n exec makoctl dismiss
+bindsym $mod+Shift+n exec makoctl dismiss -a
+
+# Flameshot position fix and autostart
+#exec QT_QPA_PLATFORM=wayland flameshot
+#for_window [app_id="flameshot"] border pixel 0, floating enable, fullscreen disable, move absolute position 0 0
+
+# Screenshots to clipboard
+bindsym $mod+Shift+S exec grim -g "$(slurp)" - | wl-copy -t image/png
+bindsym $mod+Print exec grim - | wl-copy -t image/png
+#bindsym $mod+Ctrl+Shift+S exec grim -g "$(slurp)" $(echo "$HOME/Pictures/Screenshot_$(date +'%Y%m%d')_$(date +'%H%M%S').png")
+bindsym $mod+Ctrl+Print exec grim -o $(swaymsg -t get_outputs | jq -r '.[] | select(.focused) | .name') - | wl-copy -t image/png
+
+# Zathura notes window resize
+for_window [app_id="org.pwmt.zathura" title="^.*notes.pdf$"] resize set width 775
+
+# Syncthing start
+exec syncthing serve --no-browser
+
+# Force various windows to be floating
+# Firefox PIP YT Player
+for_window [app_id="firefox" title="^Picture-in-Picture$"] floating enable, resize set 578 326, border none, sticky enable
+# Duo 2FA
+for_window [app_id="firefox" title="^Activate Security Key — Mozilla Firefox$"] floating enable
+for_window [app_id="firefox" title="^Firefox — Sharing Indicator$"] floating enable, resize set 18 52, border none, move position center, move y 0px
+# Qjackctl
+for_window [app_id="qjackctl"] floating enable
+# Weather Window
+for_window [app_id="ala-wttr"] border none, floating enable, resize set 740 712
+include /etc/sway/config.d/*
@@ -0,0 +1,129 @@
+{
+ "layer": "top",
+ "position": "top",
+ "height": 30,
+
+ "modules-left": ["hyprland/workspaces", "hyprland/submap"],
+ "modules-center": ["hyprland/window"],
+ "modules-right": ["tray", "custom/spotify", "custom/weather", "custom/mail", "custom/storage", "backlight", "bluetooth", "pulseaudio", "network", "idle_inhibitor", "battery", "clock"],
+ "hyprland/submap": {
+ "format": " {}"
+ },
+ "hyprland/workspaces": {
+ "format": "{id}",
+ "all-outputs": false,
+ "disable-scroll": true
+ },
+ "hyprland/window": {
+ "max-length": 80,
+ "tooltip": false,
+ "separate-outputs": true
+ },
+ "clock": {
+ "format": "{:%a %d %b %H:%M}",
+ "tooltip": false
+ },
+ "battery": {
+ "format": "{capacity}% {icon}",
+ "format-alt": "{time} {icon}",
+ "format-icons": ["", "", "", "", ""],
+ "format-charging": "{capacity}% ",
+ "interval": 30,
+ "states": {
+ "warning": 25,
+ "critical": 10
+ },
+ "tooltip": false,
+ "bat":"BAT1"
+ },
+ "bluetooth": {
+ "format": "",
+ "format-disabled": "",
+ "format-connected": "",
+ "format-connected-battery": " {device_battery_percentage}%",
+ "on-click": "blueman-manager",
+ "tooltip-format": "{controller_alias}\t{controller_address}\n\n{num_connections} connected",
+ "tooltip-format-connected": "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}",
+ "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}",
+ "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%"
+ },
+ "network": {
+ "format-alt": "{ipaddr}/{cidr} {icon} {bandwidthTotalBytes}",
+ "format": "{ipaddr}/{cidr} {icon}",
+ "format-alt-click": "click-right",
+ "format-icons": {
+ "wifi": ["", "" ,"", ""],
+ "ethernet": [""],
+ "disconnected": [""]
+ },
+ "on-click": "alacritty -e doas nmtui",
+ "tooltip": false
+ },
+ "pulseaudio": {
+ "format-alt": "{icon}",
+ "format": "{volume} {icon}",
+ "format-alt-click": "click-right",
+ "format-muted": "",
+ "format-icons": {
+ "phone": [" ", " ", " ", " "],
+ "default": ["", "", "", ""]
+ },
+ "scroll-step": 1,
+ "on-click": "pavucontrol",
+ "tooltip": false
+ },
+ "custom/spotify": {
+ "interval": 2,
+ "return-type": "json",
+ "exec": "~/.config/waybar/modules/spotify.sh",
+ "exec-if": "~/.config/waybar/modules/check-for-music.sh",
+ "escape": true,
+ "on-click": "playerctl play-pause"
+ },
+ "custom/storage": {
+ "format-alt": "{} ",
+ "format": "{percentage}% ",
+ "format-alt-click": "click-right",
+ "return-type": "json",
+ "interval": 60,
+ "exec": "~/.config/waybar/modules/storage.sh"
+ },
+ "backlight": {
+ "format-alt": "{icon}",
+ "format": "{percent}% {icon}",
+ "format-alt-click": "click-right",
+ "format-icons": ["", ""],
+ "on-scroll-down": "light -A 1",
+ "on-scroll-up": "light -U 1"
+ },
+ "custom/weather": {
+ "format-alt": "{}",
+ "format": "{alt}: {}",
+ "format-alt-click": "click-right",
+ "interval": 1800,
+ "return-type": "json",
+ "on-click": "alacritty --class ala-wttr --hold -e curl https://v2.wttr.in",
+ "exec": "~/.config/waybar/modules/weather.sh",
+ "exec-if": "ping wttr.in -c1"
+ },
+ "idle_inhibitor": {
+ "format": "{icon}",
+ "format-icons": {
+ "activated": "",
+ "deactivated": ""
+ },
+ "tooltip": false
+ },
+ "custom/mail": {
+ "format": "",
+ "format-alt": "{alt} ",
+ "format-alt-click": "click-right",
+ "interval": 60,
+ "return-type": "json",
+ "exec": "~/.config/waybar/modules/mail.py",
+ "tooltip": false
+ },
+ "tray": {
+ "icon-size": 18
+ }
+}
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [[ $(playerctl metadata --format '{{lc(status)}}' | grep playing) -eq 0 ]]; then
+ exit 0
+else
+ exit 1
+fi
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+class=$(playerctl metadata --format '{{lc(status)}}')
+icon=""
+
+if [[ $class == "playing" ]]; then
+ info=$(playerctl metadata --format '{{artist}} - {{title}}')
+ if [[ ${#info} > 40 ]]; then
+ info=$(playerctl metadata --format '{{title}}' | cut -c1-40)"..."
+ fi
+ text=$info" "$icon
+elif [[ $class == "paused" ]]; then
+ text=$icon
+elif [[ $class == "stopped" ]]; then
+ text=""
+fi
+
+echo -e "{\"text\":\""$text"\", \"class\":\""$class"\"}"
+
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+mount="/"
+warning=20
+critical=10
+
+df -h -P -l "$mount" | awk -v warning=$warning -v critical=$critical '
+/\/.*/ {
+ text=$4
+ tooltip="Filesystem: "$1"\rSize: "$2"\rUsed: "$3"\rAvail: "$4"\rUse%: "$5"\rMounted on: "$6
+ use=$5
+ exit 0
+}
+END {
+ class=""
+ gsub(/%$/,"",use)
+ if ((100 - use) < critical) {
+ class="critical"
+ } else if ((100 - use) < warning) {
+ class="warning"
+ }
+ print "{\"text\":\""text"\", \"percentage\":"use",\"tooltip\":\""tooltip"\", \"class\":\""class"\"}"
+}
+'
+
@@ -0,0 +1,77 @@
+cachedir=~/.cache/rbn
+cachefile=${0##*/}-$1
+
+if [ ! -d $cachedir ]; then
+ mkdir -p $cachedir
+fi
+
+if [ ! -f $cachedir/$cachefile ]; then
+ touch $cachedir/$cachefile
+fi
+
+# Save current IFS
+SAVEIFS=$IFS
+# Change IFS to new line.
+IFS=$'\n'
+
+cacheage=$(($(date +%s) - $(stat -c '%Y' "$cachedir/$cachefile")))
+if [ $cacheage -gt 1740 ] || [ ! -s $cachedir/$cachefile ]; then
+ data=($(curl -s https://en.wttr.in/$1\?0qnT 2>&1))
+ echo ${data[0]} | cut -f1 -d, > $cachedir/$cachefile
+ echo ${data[1]} | sed -E 's/^.{15}//' >> $cachedir/$cachefile
+ echo ${data[2]} | sed -E 's/^.{15}//' >> $cachedir/$cachefile
+fi
+
+weather=($(cat $cachedir/$cachefile))
+
+# Restore IFSClear
+IFS=$SAVEIFS
+
+temperature=$(echo ${weather[2]} | sed -E 's/([[:digit:]]+)\.\./\1 to /g')
+
+#echo ${weather[1]##*,}
+
+# https://fontawesome.com/icons?s=solid&c=weather
+case $(echo ${weather[1]##*,} | tr '[:upper:]' '[:lower:]') in
+"clear" | "sunny")
+ condition=""
+ ;;
+"partly cloudy")
+ condition=""
+ ;;
+"cloudy")
+ condition=""
+ ;;
+"overcast")
+ condition=""
+ ;;
+"mist" | "fog" | "freezing fog")
+ condition="敖"
+ ;;
+"patchy rain possible" | "patchy light drizzle" | "light drizzle" | "patchy light rain" | "light rain" | "light rain shower" | "rain")
+ condition="殺"
+ ;;
+"moderate rain at times" | "moderate rain" | "heavy rain at times" | "heavy rain" | "moderate or heavy rain shower" | "torrential rain shower" | "rain shower")
+ condition=""
+ ;;
+"patchy snow possible" | "patchy sleet possible" | "patchy freezing drizzle possible" | "freezing drizzle" | "heavy freezing drizzle" | "light freezing rain" | "moderate or heavy freezing rain" | "light sleet" | "ice pellets" | "light sleet showers" | "moderate or heavy sleet showers")
+ condition="流"
+ ;;
+"blowing snow" | "moderate or heavy sleet" | "patchy light snow" | "light snow" | "light snow showers")
+ condition="ﰕ"
+ ;;
+"blizzard" | "patchy moderate snow" | "moderate snow" | "patchy heavy snow" | "heavy snow" | "moderate or heavy snow with thunder" | "moderate or heavy snow showers")
+ condition=""
+ ;;
+"thundery outbreaks possible" | "patchy light rain with thunder" | "moderate or heavy rain with thunder" | "patchy light snow with thunder")
+ condition=""
+ ;;
+*)
+ condition=""
+ echo -e "{\"text\":\""$condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature ${weather[1]}"\"}"
+ ;;
+esac
+
+#echo $temp $condition
+
+echo -e "{\"text\":\""$temperature $condition"\", \"alt\":\""${weather[0]}"\", \"tooltip\":\""${weather[0]}: $temperature ${weather[1]}"\"}"
@@ -0,0 +1,77 @@
+* {
+ border: none;
+ border-radius: 0;
+ font-family: AnonymicePro Nerd Font;
+ font-size: 15px;
+ box-shadow: none;
+ text-shadow: none;
+ transition-duration: 0s;
+ color: white;
+}
+
+#waybar {
+ background-color:rgba(0,0,0,0.25);
+ color: white;
+}
+
+window {
+ color: rgba(217, 216, 216, 1);
+ background: rgba(35, 31, 32, 0.00);
+}
+
+window#waybar.solo {
+ color: rgba(217, 216, 216, 1);
+ background: rgba(35, 31, 32, 0.85);
+}
+
+#workspaces {
+ margin: 0 5px;
+}
+
+#workspaces button {
+ padding: 0 5px;
+ color: rgba(217, 216, 216, 0.4);
+}
+
+#workspaces button.visible {
+ color: rgba(217, 216, 216, 1);
+}
+
+#workspaces button.active {
+ border-top: 3px solid rgba(217, 216, 216, 1);
+ border-bottom: 3px solid rgba(217, 216, 216, 0);
+}
+
+#workspaces button.urgent {
+ color: rgba(238, 46, 36, 1);
+}
+
+#mode, #battery, #cpu, #memory, #network, #bluetooth, #pulseaudio, #idle_inhibitor, #backlight, #custom-storage, #custom-spotify, #custom-weather, #custom-mail {
+ margin: 0px 6px 0px 10px;
+ min-width: 25px;
+}
+
+#clock {
+ margin: 0px 16px 0px 10px;
+ min-width: 140px;
+}
+
+#battery.warning {
+ color: rgba(255, 210, 4, 1);
+}
+
+#battery.critical {
+ color: rgba(238, 46, 36, 1);
+}
+
+#battery.charging {
+ color: rgba(217, 216, 216, 1);
+}
+
+#custom-storage.warning {
+ color: rgba(255, 210, 4, 1);
+}
+
+#custom-storage.critical {
+ color: rgba(238, 46, 36, 1);
+}
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBmDCCAT2gAwIBAgIQIq6m5IB0yZ1181RHpL6jyjAKBggqhkjOPQQDAjAqMQ8w
+DQYDVQQKEwZSeWFuQ0ExFzAVBgNVBAMTDlJ5YW5DQSBSb290IENBMB4XDTIyMTAx
+OTIzMjIxNFoXDTMyMTAxNjIzMjIxNFowKjEPMA0GA1UEChMGUnlhbkNBMRcwFQYD
+VQQDEw5SeWFuQ0EgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABAhR
+Z3X7MTDDzvPAuW9JM8Rn4MU283Y3Wa2a1RiyTxo2XGlEB8HPgfL7MwRccUlCiABl
+zPHkaYUvrjJrq7PjsuejRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAG
+AQH/AgEBMB0GA1UdDgQWBBS4/S97d94NQoK+G+Lh9T76LVCxXDAKBggqhkjOPQQD
+AgNJADBGAiEA5WVKjNUN1x4+X17XnD+H5QKLgs+M/mFfyk3yPY1aMtoCIQCnGAu9
+wrKUglPbAPcQ1Qs47qeBubJu5um1v+mi0+MGPg==
+-----END CERTIFICATE-----
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBvzCCAWagAwIBAgIQTAcDSgrzfeM2tDg4FXLYUDAKBggqhkjOPQQDAjAqMQ8w
+DQYDVQQKEwZSeWFuQ0ExFzAVBgNVBAMTDlJ5YW5DQSBSb290IENBMB4XDTIyMTAx
+OTIzMjIxNVoXDTMyMTAxNjIzMjIxNVowMjEPMA0GA1UEChMGUnlhbkNBMR8wHQYD
+VQQDExZSeWFuQ0EgSW50ZXJtZWRpYXRlIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0D
+AQcDQgAEuJ0LEw+nrX80WlNv1wys+X/jmlpUcEFVGPHy+p2V7qsjSod+xnnRmxwp
+IF3KIH+w7b5bS/ExDupPedFxLx6ibKNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1Ud
+EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFFvK0qjRbUUOQKe/GY1P1YM44Vl1MB8G
+A1UdIwQYMBaAFLj9L3t33g1Cgr4b4uH1PvotULFcMAoGCCqGSM49BAMCA0cAMEQC
+IHZMrux3MJVYlCbv3O3c68Rtt12l//9209AhaA5HZ4ujAiAnJj5lKNbpYBvNFtUW
+2f6D5vWcd3LhQPQ4u0pxeCARNA==
+-----END CERTIFICATE-----
@@ -0,0 +1,239 @@
+(define-module (ryan-config base-system)
+ #:use-module (gnu)
+ #:use-module (nongnu packages linux)
+ #:use-module (gnu system setuid)
+ #:use-module (gnu packages admin)
+ #:use-module (gnu packages avahi)
+ #:use-module (guix packages)
+ #:use-module (gnu packages shells)
+ #:use-module (guix build-system trivial)
+ #:use-module (guix licenses)
+ #:use-module (gnu packages tls)
+ #:use-module (srfi srfi-1)
+ #:use-module (ryan-packages freedesktop)
+ #:use-module (ryan-packages wm)
+ #:use-module (ryan-packages virtualization)
+ #:use-module (rosenthal packages wm)
+ #:use-module (gnu packages security-token)
+ #:use-module (gnu services security-token)
+ #:use-module (gnu services cups)
+ #:use-module (gnu services desktop)
+ #:use-module (gnu services networking)
+ #:use-module (gnu services xorg)
+ #:use-module (gnu services ssh)
+ #:use-module (gnu services nix)
+ #:use-module (gnu services sound)
+ #:use-module (gnu services docker)
+ #:use-module (gnu services avahi)
+ #:use-module (gnu services virtualization))
+
+; Define package that installs my root ca public keys
+(define my-ca-certs
+ (package
+ (name "my-ca-certs")
+ (version "1")
+ (source (local-file "./CACerts"
+ #:recursive? #t))
+ (build-system trivial-build-system)
+ (license mpl2.0)
+ (home-page "https://rschanz.org")
+ (arguments
+ `(#:modules
+ ((guix build utils))
+ #:builder
+ (begin
+ (use-modules (guix build utils)
+ (srfi srfi-1)
+ (srfi srfi-26)
+ (ice-9 ftw))
+ (let* ((ca-certificates (assoc-ref %build-inputs "source"))
+ (crt-suffix ".crt")
+ (is-certificate? (cut string-suffix? crt-suffix <>))
+ (certificates (filter is-certificate?
+ (scandir ca-certificates)))
+ (out (assoc-ref %outputs "out"))
+ (certificate-directory (string-append out "/etc/ssl/certs"))
+ (openssl (string-append (assoc-ref %build-inputs "openssl") "/bin/openssl")))
+ (mkdir-p certificate-directory)
+ (for-each
+ (lambda (cert)
+ (invoke
+ openssl "x509"
+ "-in" (string-append ca-certificates "/" cert)
+ "-outform" "PEM"
+ "-out" (string-append certificate-directory "/" cert ".pem")))
+ certificates)
+ #t))))
+ (native-inputs
+ (list openssl))
+ (synopsis "My CA Certs")
+ (description synopsis)))
+
+; Re-define the base packages to remove sudo
+(define %my-base-packages
+ (remove (lambda (package)
+ (member (package-name package)
+ (list "sudo" "nano")))
+ %base-packages ))
+
+(define %backlight-udev-rule
+ (udev-rule
+ "90-backlight.rules"
+ (string-append "ACTION==\"add\", SUBSYSTEM==\"backlight\", "
+ "RUN+=\"/run/current-system/profile/bin/chgrp video /sys/class/backlight/%k/brightness\""
+ "\n"
+ "ACTION==\"add\", SUBSYSTEM==\"backlight\", "
+ "RUN+=\"/run/current-system/profile/bin/chmod g+w /sys/class/backlight/%k/brightness\"")))
+
+(define-public base-operating-system
+ (operating-system
+ (kernel linux)
+ (firmware (list linux-firmware))
+ (locale "en_US.utf8")
+ (timezone "America/New_York")
+ (keyboard-layout (keyboard-layout "us"))
+ (host-name "ThisWillChange")
+
+ ;; The list of user accounts ('root' is implicit).
+ (users (cons* (user-account
+ (name "ryan")
+ (comment "Ryan")
+ (group "users")
+ ;(shell (file-append zsh "/bin/zsh"))
+ (home-directory "/home/ryan")
+ (supplementary-groups '("wheel" "netdev" "audio" "video" "lp" "plugdev" "docker" "libvirt" "kvm")))
+ %base-user-accounts))
+
+ ;; Packages installed system-wide. Users can also install packages
+ ;; under their own account: use 'guix search KEYWORD' to search
+ ;; for packages and 'guix install PACKAGE' to install a package.
+ (packages (append (map specification->package (list "sway"
+ "hyprland"
+ "swaybg"
+ "swayidle"
+ ;"swaylock-effects"
+ "fuzzel"
+ "alacritty"
+ "pinentry-qt"
+ "adwaita-icon-theme"
+ "hicolor-icon-theme"
+ "git"
+ "nss-certs"
+ ;"waybar"
+ "gnupg"
+ "light"
+ "avahi"
+ "mako"
+ "grim"
+ "grimblast"
+ "slurp"
+ "wl-clipboard"
+ "bluez"
+ "blueman"
+ "ldacbt"
+ "libfreeaptx"
+ "libfdk"
+ "opendoas"
+ ;"xdg-desktop-portal-wlr"
+ "xdg-desktop-portal"
+ "xdg-desktop-portal-gtk"
+ "v4l2loopback-linux-module"
+ "pipewire"
+ "docker"
+ ;"libvirt" ;New version inherited from service
+ ;"virt-manager"
+ "dconf"
+ "wireplumber"
+ "wireshark"
+ "zsh"))
+ (list my-ca-certs swaylock-effects-new waybar-new xdg-desktop-portal-hyprland virt-manager-ovmf)
+ %my-base-packages ))
+
+ ;; Below is the list of system services. To search for available
+ ;; services, run 'guix system search KEYWORD' in a terminal.
+ (services
+ (append (list
+
+ ;; To configure OpenSSH, pass an 'openssh-configuration'
+ ;; record as a second argument to 'service' below.
+ (service openssh-service-type)
+ (service pcscd-service-type)
+ (service cups-service-type
+ (cups-configuration
+ (web-interface? #t)))
+ ;; Avahi is only present for CUPS to support "automagic" printing
+ (service avahi-service-type
+ (avahi-configuration
+ (publish? #f) ;; do not advertise this machine
+ (publish-workstation? #f))) ;; do not advertise, I want this to be as silent as possible
+ (service docker-service-type)
+ (service nix-service-type)
+ (service libvirt-service-type
+ (libvirt-configuration
+ (libvirt libvirt-ovmf)
+ (unix-sock-group "libvirt")))
+ (service virtlog-service-type)
+ (service bluetooth-service-type
+ (bluetooth-configuration
+ (experimental #t)
+ (fast-connectable? #t)))
+ (udev-rules-service 'fido2 libfido2 #:groups '("plugdev")))
+
+ ;; This is the default list of services we
+ ;; are appending to.
+ (modify-services %desktop-services
+ (guix-service-type config =>
+ (guix-configuration
+ (inherit config)
+ (substitute-urls
+ (append (list "https://substitutes.nonguix.org")
+ %default-substitute-urls))
+ (authorized-keys
+ (cons* (plain-file "non-guix.pub"
+ "(public-key
+ (ecc
+ (curve Ed25519)
+ (q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#)
+ )
+ )" ) %default-authorized-guix-keys))))
+ (udev-service-type config =>
+ (udev-configuration
+ (inherit config)
+ (rules (cons %backlight-udev-rule
+ (udev-configuration-rules config)))))
+ (delete pulseaudio-service-type)
+ (delete gdm-service-type)
+ (delete avahi-service-type)
+ ;(delete xorg-server-service-type)
+ (delete alsa-service-type) )))
+ (name-service-switch %mdns-host-lookup-nss) ;; Enable .local lookup
+ (setuid-programs
+ (append (list (file-like->setuid-program
+ (file-append
+ ;(specification->package "swaylock-effects")
+ swaylock-effects-new
+ "/bin/swaylock"))
+ (file-like->setuid-program
+ (file-append
+ (specification->package "wireshark")
+ "/bin/dumpcap"))
+ (file-like->setuid-program
+ (file-append
+ (specification->package "spice-gtk")
+ "/libexec/spice-client-glib-usb-acl-helper"))
+ (file-like->setuid-program
+ (file-append
+ (specification->package "opendoas")
+ "/bin/doas")))
+ (delete sudo %setuid-programs)))
+ (file-systems (cons*
+ (file-system
+ (mount-point "/tmp")
+ (device "none")
+ (type "tmpfs")
+ (check? #f))
+ %base-file-systems))
+ (bootloader (bootloader-configuration
+ (bootloader grub-efi-bootloader)
+ (targets (list "/boot/efi"))
+ (keyboard-layout keyboard-layout)))))
@@ -0,0 +1,19 @@
+(use-modules (ryan-config base-system)
+ (gnu))
+
+(operating-system
+ (inherit base-operating-system)
+ (host-name "ChangeMe_HOST")
+ (file-systems (cons* (file-system
+ (mount-point "/")
+ (device (uuid "ChangeMe_ROOT"
+ 'ext4))
+ (type "ext4"))
+ (file-system
+ (mount-point "/boot/efi")
+ (device (uuid "ChangeMe_BOOTEFI"
+ 'fat32))
+ (type "vfat")) %base-file-systems))
+ (swap-devices
+ (list
+ (swap-space (target (uuid "ChangeMe_SWAP"))))))
@@ -0,0 +1,24 @@
+(use-modules (ryan-config base-system)
+ (gnu))
+
+(operating-system
+ (inherit base-operating-system)
+ (host-name "ChangeMe_HOST")
+ (mapped-devices (list (mapped-device
+ (source (uuid
+ "ChangeMe_ROOT"))
+ (target "sysroot")
+ (type luks-device-mapping))))
+ (file-systems (cons* (file-system
+ (mount-point "/")
+ (device "/dev/mapper/sysroot")
+ (type "ext4")
+ (dependencies mapped-devices))
+ (file-system
+ (mount-point "/boot/efi")
+ (device (uuid "ChangeMe_BOOTEFI"
+ 'fat32))
+ (type "vfat")) %base-file-systems))
+ (swap-devices
+ (list
+ (swap-space (target (uuid "ChangeMe_SWAP"))))))
@@ -0,0 +1,20 @@
+#!/run/current-system/profile/bin/bash
+
+# This should run on user first logon, so let's a go!
+# First, we should run a guix pull
+
+guix pull
+
+hash guix
+
+guix home -L ~/.config/guix/modules reconfigure ~/.config/guix/home-config/home-configuration.scm
+
+sudo herd restart nix-daemon
+
+nix-channel --update
+
+nix-shell '<home-manager>' -A install
+
+source ~/.bashrc
+
+home-manager switch
@@ -0,0 +1,81 @@
+(define-module (ryan-packages audio)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix gexp)
+ #:use-module (guix build-system meson)
+ #:use-module (guix packages)
+ #:use-module (guix download)
+ #:use-module (guix utils)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages glib)
+ #:use-module (gnu packages audio)
+ #:use-module (gnu packages pulseaudio)
+ #:use-module (gnu packages gtk)
+ #:use-module (gnu packages xiph)
+ #:use-module (gnu packages tbb)
+ #:use-module (gnu packages gettext)
+ #:use-module (gnu packages gnome)
+ #:use-module (gnu packages pretty-print)
+ #:use-module (gnu packages algebra)
+ #:use-module (gnu packages cpp)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages cmake)
+ #:use-module (gnu packages maths)
+ #:use-module (gnu packages pkg-config))
+
+(define-public easyeffects
+ (package
+ (name "easyeffects")
+ (version "7.0.1")
+ (arguments
+ (list
+ #:modules
+ '((guix build utils)
+ (guix build meson-build-system))
+ #:imported-modules
+ (append %meson-build-system-modules)
+ #:tests? #f))
+ (native-inputs (list gettext-minimal
+ itstool
+ desktop-file-utils
+ `(,glib "bin")
+ `(,gtk+ "bin")
+ pkg-config
+ cmake
+ appstream-glib))
+ (inputs (list zita-convolver
+ rnnoise
+ tbb
+ fftwf
+ lilv
+ fmt
+ rubberband
+ speexdsp
+ nlohmann-json
+ pipewire
+ libadwaita
+ libsigc++
+ libbs2b
+ libsndfile
+ libsamplerate
+ libebur128
+ libportal
+ gsl
+ speex
+ `(,util-linux "lib")))
+ (source (origin
+ (method url-fetch)
+ (uri (string-append "https://github.com/wwmm/easyeffects/archive/refs/tags/v" version
+ ".tar.gz"))
+ (sha256
+ (base32
+ "05j52fy51zjai7n0j23chydfgkfq9n82h2ih806z3b47zhk2h2j2"))))
+ (build-system meson-build-system)
+ (synopsis "Limiter, compressor, convolver, equalizer and auto volume and many other plugins for PipeWire applications")
+ (description "This package provides @code{easyeffects}, which is an audio application for use atop of @code{pipewire}
+ that allows effects that modify sound sources and sinks. This cannot be updated to the latest version (7.0.8) because
+ the packaged version of @code{gtk} is too old.")
+ (home-page "https://github.com/wwmm/easyeffects")
+ (license license:gpl3+)))
+
+easyeffects
@@ -0,0 +1,211 @@
+(define-module (ryan-packages freedesktop)
+ #:use-module (guix download)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (guix gexp)
+ #:use-module (guix build-system meson)
+ #:use-module (guix build-system qt)
+ #:use-module (guix build-system cmake)
+ #:use-module (guix build utils)
+ #:use-module (guix build glib-or-gtk-build-system)
+ #:use-module (guix packages)
+ #:use-module (guix git-download)
+ #:use-module (guix utils)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages gl)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu packages image)
+ #:use-module (gnu packages qt)
+ #:use-module (gnu packages cmake)
+ #:use-module (gnu packages pkg-config)
+ #:use-module (gnu packages freedesktop)
+ #:use-module (gnu packages bash)
+ #:use-module (gnu packages xorg)
+ #:use-module (gnu packages glib)
+ #:use-module (gnu packages man)
+ #:use-module (rosenthal packages wm)
+ #:use-module (gnu packages wm))
+
+(define-public xdg-desktop-portal-wlr-new
+ (package
+ (inherit xdg-desktop-portal-wlr)
+ (version "0.7.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/emersion/xdg-desktop-portal-wlr")
+ (commit (string-append "v" version))))
+ (sha256
+ (base32
+ "1b3hpp3ybjgnnmnwsyb5bsnvz9q5nr3zz0j1alh02g24f68lf00k"))
+ (patches (search-patches "xdg-desktop-portal-wlr-harcoded-length.patch"))))
+ (native-inputs (modify-inputs (package-native-inputs xdg-desktop-portal-wlr)
+ (append wlroots)))))
+
+(define xdg-desktop-portal-hyprland-old-original
+ (package
+ (name "xdg-desktop-portal-hyprland")
+ (version "0.5.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/hyprwm/xdg-desktop-portal-hyprland")
+ (commit (string-append "v" version))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "1dmgc0w4wjj9hwqg17wg529v8sbxr6czp9s319d5407jm780x40b"))))
+ (build-system meson-build-system)
+ (arguments
+ (list
+ #:modules
+ '((guix build utils)
+ (guix build meson-build-system)
+ ((guix build qt-build-system) #:prefix qt:))
+ #:imported-modules
+ (append %meson-build-system-modules
+ %qt-build-system-modules)
+ #:tests? #f
+ #:configure-flags #~(list "-Dsystemd=disabled")
+ #:phases
+ ;; After building the portal, we need to build the share selector using qt
+ #~(modify-phases %standard-phases
+ (add-after 'install 'chdir
+ (lambda _ (chdir "../source/hyprland-share-picker/")))
+ (add-after 'chdir 'check-setup
+ (assoc-ref qt:%standard-phases 'check-setup))
+ (add-after 'check-setup 'qt-build
+ (lambda* (#:key inputs outputs #:allow-other-keys)
+ ((assoc-ref qt:%standard-phases 'build)
+ #:inputs inputs
+ #:outputs outputs
+ #:configure-flags '()
+ #:qtbase #$(this-package-native-input "qtbase-5"))))
+ (add-after 'qt-build 'qt-install
+ (lambda* (#:key inputs outputs #:allow-other-keys)
+ (let ((share-picker (string-append (assoc-ref outputs "out")
+ "/bin")))
+ (install-file "build/hyprland-share-picker" share-picker)
+ #t)))
+ (add-after 'qt-install 'qt-wrap
+ (assoc-ref qt:%standard-phases 'qt-wrap))
+ (add-after 'qt-wrap 'dep-wrap
+ (lambda* (#:key inputs #:allow-other-keys)
+ (let ((hyprland-share-picker (string-append #$output "/bin/hyprland-share-picker")))
+ (wrap-program hyprland-share-picker
+ `("PATH" suffix
+ ,(map (lambda (program)
+ (dirname (search-input-file
+ inputs (string-append "/bin/" program))))
+ '("slurp"))))))))))
+ (native-inputs (list cmake pkg-config qtbase-5))
+ (inputs (list elogind hyprland hyprland-protocols slurp pipewire wayland-protocols wayland libinih mesa qtwayland-5 `(,util-linux "lib")))
+ (home-page "")
+ (synopsis "test")
+ (description "test")
+ (license license:bsd-3)))
+
+(define-public wl-mirror
+ (package
+ (name "wl-mirror")
+ (version "0.13.2")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/Ferdi265/wl-mirror")
+ (commit (string-append "v" version))
+ (recursive? #t)))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "0vkd73x5r2585s3w1ckvslc2mq9qbzrm5xkwg8gpy9ydaxhn8hmp"))))
+ (inputs (list wayland egl-wayland mesa))
+ (native-inputs (list pkg-config scdoc wayland-protocols))
+ (build-system cmake-build-system)
+ (arguments (list
+ #:tests? #f
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-before 'configure 'touch
+ (lambda _
+ (invoke "touch" "proto/wayland-protocols/.git")
+ (invoke "touch" "proto/wlr-protocols/.git"))))))
+ (home-page "bleh")
+ (synopsis "mirror displays")
+ (description "mirror displays")
+ (license license:expat)))
+
+(define-public xdg-desktop-portal-hyprland
+ (package
+ (name "xdg-desktop-portal-hyprland")
+ (version "1.1.0")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/hyprwm/xdg-desktop-portal-hyprland")
+ (commit (string-append "v" version))))
+ (file-name (git-file-name name version))
+ (sha256
+ (base32
+ "05gcdg3fw7plc9fri6rpq9la1xjij93jqkqmq57mrqjgwg3jlmrb"))))
+ (build-system meson-build-system)
+ (arguments
+ (list #:imported-modules
+ (append %meson-build-system-modules
+ %qt-build-system-modules)
+ #:modules
+ '((guix build utils)
+ (guix build meson-build-system)
+ ((guix build qt-build-system) #:prefix qt:))
+ #:tests? #f ;No tests
+ #:phases
+ #~(modify-phases %standard-phases
+ (add-after 'unpack 'fix-path
+ (lambda* (#:key inputs #:allow-other-keys)
+ (substitute* (find-files "." "\\.cp?*$")
+ (("/bin/sh") "sh")
+ (("\\<(sh|grim|slurp)\\>" _ cmd)
+ (search-input-file inputs (string-append "/bin/" cmd)))
+ (("\"(hyprland-share-picker)\"" _ cmd)
+ (string-append "\"" #$output "/bin/" cmd "\"")))))
+ ;; After building the portal, we need to build the share selector
+ ;; using qt
+ (add-after 'install 'chdir
+ (lambda _
+ (chdir "../source/hyprland-share-picker/")))
+ (add-after 'chdir 'qt-build
+ (lambda* (#:key (make-flags '()) (parallel-build? #t)
+ #:allow-other-keys)
+ ((assoc-ref qt:%standard-phases 'build)
+ #:make-flags make-flags
+ #:parallel-build? parallel-build?)))
+ (add-after 'qt-build 'install-hyprland-share-picker
+ (lambda _
+ (install-file "build/hyprland-share-picker"
+ (string-append #$output "/bin"))))
+ (add-after 'install-hyprland-share-picker 'qt-wrap
+ (assoc-ref qt:%standard-phases 'qt-wrap)))))
+ (native-inputs (list cmake-minimal pkg-config))
+ (inputs
+ (list bash-minimal
+ basu
+ grim
+ hyprland-protocols
+ libinih
+ mesa
+ pipewire
+ sdbus-c++
+ qtbase-5
+ slurp
+ `(,util-linux "lib")
+ wayland
+ wayland-protocols))
+ (home-page "https://github.com/hyprwm/xdg-desktop-portal-hyprland")
+ (synopsis "XDG Desktop Portal backend for Hyprland")
+ (description
+ "This package provides @code{xdg-desktop-portal-hyprland}, which extends
+@code{xdg-desktop-portal-wlr} for Hyprland with support for
+@code{xdg-desktop-portal} screenshot and casting interfaces, while adding a few
+extra portals specific to Hyprland, mostly for window sharing.")
+ (license license:expat)))
+
+xdg-desktop-portal-hyprland
@@ -0,0 +1,62 @@
+(define-module (ryan-packages mozilla)
+ #:use-module (gnu)
+ #:use-module (guix download)
+ #:use-module (guix packages)
+ #:use-module ((guix licenses) #:prefix license:)
+ #:use-module (gnu packages bash)
+ #:use-module (gnu packages linux)
+ #:use-module (nonguix build-system binary)
+ #:use-module (guix build-system trivial)
+ #:use-module (nongnu packages mozilla))
+
+(define firefox*
+ (package/inherit
+ firefox
+ (inputs
+ (modify-inputs
+ (package-inputs firefox)
+ (delete "pipewire")
+ (append pipewire)))))
+
+(define-public firefox-wayland-new
+ (package
+ (inherit firefox*)
+ (name "firefox-wayland-new")
+ (native-inputs '())
+ (inputs
+ `(("bash" ,bash-minimal)
+ ("pipewire" ,pipewire)
+ ("firefox" ,firefox*)))
+ (build-system trivial-build-system)
+ (arguments
+ '(#:modules ((guix build utils))
+ #:builder
+ (begin
+ (use-modules (guix build utils))
+ (let* ((bash (assoc-ref %build-inputs "bash"))
+ (firefox (assoc-ref %build-inputs "firefox"))
+ (pipewire (assoc-ref %build-inputs "pipewire"))
+ (out (assoc-ref %outputs "out"))
+ (exe (string-append out "/bin/firefox")))
+ (mkdir-p (dirname exe))
+
+ (call-with-output-file exe
+ (lambda (port)
+ ;; NOTE: added "export LD_LIBRARY_PATH=pipewire"
+ ;; maybe this can be done better with `wrap-programm'
+ (format port "#!~a \n
+export LD_LIBRARY_PATH=~a \n
+export MOZ_ENABLE_WAYLAND=1 \n
+exec ~a $@\n"
+ (string-append bash "/bin/bash")
+ (string-append pipewire "/lib")
+ (string-append firefox "/bin/firefox"))))
+ (chmod exe #o555)
+
+ ;; Provide the manual and .desktop file.
+ (copy-recursively (string-append firefox "/share")
+ (string-append out "/share"))
+ (substitute* (string-append
+ out "/share/applications/firefox.desktop")
+ ((firefox) out))
+ #t))))))
@@ -0,0 +1,45 @@
+;;; Stolen from https://g.tylerm.dev/tylerm/dotfiles/raw/branch/main/modules/home-packages/virtualization.scm
+
+(define-module (ryan-packages virtualization)
+ #:use-module (guix packages)
+ #:use-module (guix utils)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages package-management)
+ #:use-module (gnu packages build-tools)
+ #:use-module (gnu packages virtualization)
+ #:use-module (gnu packages firmware)
+ #:use-module (guix gexp))
+
+(define-public libvirt-ovmf
+ (package
+ (inherit libvirt)
+ (name "libvirt-ovmf")
+ (inputs
+ (modify-inputs (package-inputs libvirt)
+ (append qemu)))
+ (arguments
+ (substitute-keyword-arguments (package-arguments libvirt)
+ ((#:phases phases)
+ #~(modify-phases #$phases
+ (add-after 'install 'install-firmware
+ (lambda _
+ (let ((fmw (string-append #$output "/share/qemu")))
+ (mkdir-p fmw)
+ (copy-recursively #$(file-append qemu "/share/qemu") fmw))))))))))
+
+(define-public virt-manager-ovmf
+ (package
+ (inherit virt-manager)
+ (name "virt-manager-ovmf")
+ (inputs
+ (modify-inputs (package-inputs virt-manager)
+ (append qemu)))
+ (arguments
+ (substitute-keyword-arguments (package-arguments virt-manager)
+ ((#:phases phases)
+ #~(modify-phases #$phases
+ (add-after 'install 'install-firmware
+ (lambda _
+ (let ((fmw (string-append #$output "/share/qemu")))
+ (mkdir-p fmw)
+ (copy-recursively #$(file-append qemu "/share/firmware") fmw))))))))))
@@ -0,0 +1,29 @@
+(define-module (ryan-packages wm)
+ #:use-module (guix download)
+ #:use-module (guix packages)
+ #:use-module (guix gexp)
+ #:use-module (gnu packages)
+ #:use-module (guix git-download)
+ #:use-module (guix utils)
+ #:use-module (gnu packages wm))
+
+(define-public swaylock-effects-new
+ (package
+ (inherit swaylock-effects)
+ (version "1.6.11")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/jirutka/swaylock-effects")
+ (commit (string-append "v" version))))
+ (sha256
+ (base32
+ "0j7dxn66xqlf6iv2arqzz7mxlh7nf85anvpyf30d2frcidarda9h"))))
+ (inputs (modify-inputs (package-inputs swaylock-effects) (delete "linux-pam")))))
+
+(define-public waybar-new
+ (package
+ (inherit waybar)
+ (arguments (list #:configure-flags #~(list "-Dexperimental=true")))))
+
+waybar-new
@@ -0,0 +1,99 @@
+(define-module (ryan-services pipewire)
+ #:use-module (gnu packages)
+ #:use-module (gnu packages linux)
+ #:use-module (gnu services)
+ #:use-module (gnu services configuration)
+ #:use-module (gnu home services)
+ #:use-module (gnu home services shepherd)
+ #:use-module (guix gexp))
+
+(define (home-pipewire-profile-service config)
+ (map specification->package
+ (list "pipewire"
+ "wireplumber")))
+
+(define (home-pipewire-shepherd-service config)
+ (list
+ ;; Pipewire daemon
+ (shepherd-service
+ (requirement '(dbus))
+ (provision '(pipewire))
+ (stop #~(make-kill-destructor))
+ (start #~(make-forkexec-constructor
+ (list #$(file-append pipewire "/bin/pipewire"))
+ #:log-file (string-append
+ (or (getenv "XDG_LOG_HOME")
+ (format #f "~a/.local/var/log"
+ (getenv "HOME")))
+ "/pipewire.log")
+ #:environment-variables
+ (append (list "DISABLE_RTKIT=0")
+ (default-environment-variables)))))
+ ;; Pipewire-pulse
+ (shepherd-service
+ (requirement '(pipewire))
+ (provision '(pipewire-pulse))
+ (stop #~(make-kill-destructor))
+ (start #~(make-forkexec-constructor
+ (list #$(file-append pipewire "/bin/pipewire-pulse"))
+ #:log-file (string-append
+ (or (getenv "XDG_LOG_HOME")
+ (format #f "~a/.local/var/log"
+ (getenv "HOME")))
+ "/pipewire-pulse.log")
+ #:environment-variables
+ (append (list "DISABLE_RTKIT=0")
+ (default-environment-variables)))))
+ ;; Wireplumber
+ (shepherd-service
+ (requirement '(pipewire))
+ (provision '(wireplumber))
+ (stop #~(make-kill-destructor))
+ (start #~(make-forkexec-constructor
+ (list #$(file-append wireplumber "/bin/wireplumber"))
+ #:log-file (string-append
+ (or (getenv "XDG_LOG_HOME")
+ (format #f "~a/.local/var/log"
+ (getenv "HOME")))
+ "/wireplumber.log")
+ #:environment-variables
+ (append (list "DISABLE_RTKIT=0")
+ (default-environment-variables)))))))
+
+(define (home-pipewire-xdg-configuration-service config)
+ `(("alsa/asoundrc"
+ ,(mixed-text-file
+ "asoundrc"
+ #~(string-append
+ "<"
+ #$(file-append
+ pipewire "/share/alsa/alsa.conf.d/50-pipewire.conf")
+ ">\n<"
+ #$(file-append
+ pipewire "/share/alsa/alsa.conf.d/99-pipewire-default.conf")
+ ">\n"
+ "
+ pcm_type.pipewire {
+ lib " #$(file-append pipewire "/lib/alsa-lib/libasound_module_pcm_pipewire.so")
+ "
+ }
+ ctl_type.pipewire {
+ lib " #$(file-append pipewire "/lib/alsa-lib/libasound_module_ctl_pipewire.so")
+ "
+ }
+ ")))))
+
+(define-public home-pipewire-service-type
+ (service-type (name 'home-pipewire)
+ (extensions
+ (list (service-extension
+ home-profile-service-type
+ home-pipewire-profile-service)
+ (service-extension
+ home-shepherd-service-type
+ home-pipewire-shepherd-service)
+ (service-extension
+ home-xdg-configuration-files-service-type
+ home-pipewire-xdg-configuration-service)))
+ (default-value #f)
+ (description "Configures and runs Pipewire and Wireplumber")))
@@ -1,148 +0,0 @@
-;; This is an operating system configuration generated
-;; by the graphical installer.
-;;
-;; Once installation is complete, you can learn and modify
-;; this file to tweak the system configuration, and pass it
-;; to the 'guix system reconfigure' command to effect your
-;; changes.
-
-
-;; Indicate which modules to import to access the variables
-;; used in this configuration.
-(use-modules (gnu) (nongnu packages linux))
-(use-modules (gnu system setuid))
-(use-modules (gnu packages admin))
-(use-modules (guix packages))
-(use-modules (gnu services authentication))
-(use-modules (gnu packages shells))
-(use-modules (srfi srfi-1))
-(use-package-modules security-token)
-(use-service-modules cups desktop networking ssh xorg sound security-token)
-
-; Re-define the base packages to remove sudo
-(define %my-base-packages
- (remove (lambda (package)
- (member (package-name package)
- (list "sudo" "nano")))
- %base-packages ))
-
-(operating-system
- (kernel linux)
- (firmware (list linux-firmware))
- (locale "en_US.utf8")
- (timezone "America/New_York")
- (keyboard-layout (keyboard-layout "us"))
- (host-name "RyanThinkpad")
-
- ;; The list of user accounts ('root' is implicit).
- (users (cons* (user-account
- (name "ryan")
- (comment "Ryan")
- (group "users")
- ;(shell (file-append zsh "/bin/zsh"))
- (home-directory "/home/ryan")
- (supplementary-groups '("wheel" "netdev" "audio" "video" "lp" "plugdev")))
- %base-user-accounts))
-
- ;; Packages installed system-wide. Users can also install packages
- ;; under their own account: use 'guix search KEYWORD' to search
- ;; for packages and 'guix install PACKAGE' to install a package.
- (packages (append (map specification->package (list "sway"
- "swaybg"
- "swayidle"
- "swaylock-effects"
- "fuzzel"
- "alacritty"
- "pinentry-qt"
- "adwaita-icon-theme"
- "hicolor-icon-theme"
- "git"
- "nss-certs"
- "waybar"
- "gnupg"
- "light"
- "mako"
- "grim"
- "slurp"
- "wl-clipboard"
- "bluez"
- "blueman"
- "opendoas"
- "xdg-desktop-portal-wlr"
- "xdg-desktop-portal"
- "pipewire"
- "fprintd"
- "wireplumber"
- "zsh"))
- %my-base-packages ))
-
- ;; Below is the list of system services. To search for available
- ;; services, run 'guix system search KEYWORD' in a terminal.
- (services
- (append (list
-
- ;; To configure OpenSSH, pass an 'openssh-configuration'
- ;; record as a second argument to 'service' below.
- (service openssh-service-type)
- (service pcscd-service-type)
- (service fprintd-service-type)
- (service bluetooth-service-type)
- (udev-rules-service 'fido2 libfido2 #:groups '("plugdev"))
- (set-xorg-configuration
- (xorg-configuration (keyboard-layout keyboard-layout))))
-
- ;; This is the default list of services we
- ;; are appending to.
- (modify-services %desktop-services
- (guix-service-type config =>
- (guix-configuration
- (inherit config)
- (substitute-urls
- (append (list "https://substitutes.nonguix.org")
- %default-substitute-urls))
- (authorized-keys
- (cons* (plain-file "non-guix.pub"
- "(public-key
- (ecc
- (curve Ed25519)
- (q #C1FD53E5D4CE971933EC50C9F307AE2171A2D3B52C804642A7A35F84F3A4EA98#)
- )
- )" ) %default-authorized-guix-keys))))
- (delete pulseaudio-service-type)
- (delete gdm-service-type) )))
- (setuid-programs
- (append (list (file-like->setuid-program
- (file-append
- (specification->package "swaylock-effects")
- "/bin/swaylock"))
- (file-like->setuid-program
- (file-append
- (specification->package "opendoas")
- "/bin/doas")))
- (delete sudo %setuid-programs)))
- (bootloader (bootloader-configuration
- (bootloader grub-efi-bootloader)
- (targets (list "/boot/efi"))
- (keyboard-layout keyboard-layout)))
- (mapped-devices (list (mapped-device
- (source (uuid
- "adcaf322-7ee5-48ec-abf6-4a9b10643878"))
- (target "sysroot")
- (type luks-device-mapping))))
-
- ;; The list of file systems that get "mounted". The unique
- ;; file system identifiers there ("UUIDs") can be obtained
- ;; by running 'blkid' in a terminal.
- (file-systems (cons* (file-system
- (mount-point "/")
- (device "/dev/mapper/sysroot")
- (type "ext4")
- (dependencies mapped-devices))
- (file-system
- (mount-point "/boot/efi")
- (device (uuid "DFE8-32EF"
- 'fat32))
- (type "vfat")) %base-file-systems))
- (swap-devices
- (list
- (swap-space (target (uuid "7e1bb7c5-da2a-4509-8263-f707fc752993"))) )))
@@ -0,0 +1,24 @@
+(use-modules (ryan-config base-system)
+ (gnu))
+
+(operating-system
+ (inherit base-operating-system)
+ (host-name "GuixVM")
+ (mapped-devices (list (mapped-device
+ (source (uuid
+ "0b98fe74-ed99-424e-b7d7-514284190528"))
+ (target "sysroot")
+ (type luks-device-mapping))))
+ (file-systems (cons* (file-system
+ (mount-point "/")
+ (device "/dev/mapper/sysroot")
+ (type "ext4")
+ (dependencies mapped-devices))
+ (file-system
+ (mount-point "/boot/efi")
+ (device (uuid "74F2-CFDC"
+ 'fat32))
+ (type "vfat")) %base-file-systems))
+ (swap-devices
+ (list
+ (swap-space (target (uuid "277a198e-a3bf-4dba-9077-b1a95cb34869"))))))
\ No newline at end of file