mirror of
https://github.com/nikdoof/dotfiles.git
synced 2025-12-13 17:52:26 +00:00
Compare commits
24 Commits
27e07944c3
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
e46d6b0dd3
|
|||
|
2c404cf540
|
|||
|
1bb76e4b24
|
|||
|
088491234b
|
|||
|
b2b326544c
|
|||
|
04206a5471
|
|||
|
|
4115692e51 | ||
|
|
d27de08a5c | ||
|
|
7b493cbfde | ||
|
b66a25ef26
|
|||
| 8ca8ea5a41 | |||
| 08dde00b3a | |||
| 633203a69c | |||
|
|
3620c5cf4d | ||
|
|
8838fe8f42 | ||
|
|
9e8e39db66 | ||
|
|
2b3f64646c | ||
|
|
fcc7918f7f | ||
|
|
ce9bfd8224 | ||
|
b475182c1e
|
|||
|
1c279bede4
|
|||
|
949daf1fd7
|
|||
|
|
5fa8925daa | ||
|
e048cc4a06
|
286
bin/bin/stowage
286
bin/bin/stowage
@@ -27,148 +27,180 @@ SOFTWARE.
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import fnmatch
|
import fnmatch
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from os import path
|
|
||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Callable, List
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def add(args):
|
def add(args: argparse.Namespace) -> None:
|
||||||
target = path.realpath(args.target)
|
"""Add a file to a package by moving it and creating a symlink."""
|
||||||
file_path = path.realpath(args.file)
|
target = Path(args.target).resolve()
|
||||||
package = path.realpath(path.join(args.repository, args.packages[0]))
|
file_path = Path(args.file).resolve()
|
||||||
if path.commonprefix([target, file_path]) != target:
|
package = Path(args.repository, args.packages[0]).resolve()
|
||||||
print(f"error: '{args.add}' not under '{args.target}'",
|
|
||||||
file=sys.stderr)
|
if not file_path.is_relative_to(target):
|
||||||
|
logger.error("'%s' not under '%s'", args.file, args.target)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
rest = file_path[len(target) + 1:]
|
|
||||||
dest_path = path.join(package, rest)
|
rest = file_path.relative_to(target)
|
||||||
dest = path.dirname(dest_path)
|
dest_path = package / rest
|
||||||
if not path.exists(dest):
|
dest_dir = dest_path.parent
|
||||||
if args.verbose:
|
|
||||||
print("DIR", dest)
|
if dest_path.exists():
|
||||||
os.makedirs(dest, mode=0o755)
|
logger.error("file already exists in package: %s", dest_path)
|
||||||
if args.verbose:
|
sys.exit(1)
|
||||||
print("SWAP", dest_path, file_path)
|
|
||||||
|
if not dest_dir.exists():
|
||||||
|
logger.info("DIR %s", dest_dir)
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
shutil.move(file_path, dest)
|
dest_dir.mkdir(parents=True, mode=0o755, exist_ok=True)
|
||||||
# TODO Should really check if the symlink fails here.
|
|
||||||
os.symlink(dest_path, file_path)
|
logger.info("SWAP %s %s", dest_path, file_path)
|
||||||
|
if not args.dry_run:
|
||||||
|
shutil.move(str(file_path), str(dest_path))
|
||||||
|
try:
|
||||||
|
file_path.symlink_to(dest_path)
|
||||||
|
except OSError as e:
|
||||||
|
logger.error("failed to create symlink: %s", e)
|
||||||
|
# Attempt to restore the file
|
||||||
|
try:
|
||||||
|
shutil.move(str(dest_path), str(file_path))
|
||||||
|
except Exception as restore_error:
|
||||||
|
logger.error("failed to restore file: %s", restore_error)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def install(args, is_excluded):
|
def install(args: argparse.Namespace, is_excluded: Callable[[str], bool]) -> None:
|
||||||
|
"""Install packages by creating symlinks from repository to target."""
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
package_dir = path.join(args.repository, package)
|
package_dir = Path(args.repository, package)
|
||||||
if not path.isdir(package_dir):
|
if not package_dir.is_dir():
|
||||||
print(f"no such package: {package}; skipping", file=sys.stderr)
|
logger.warning("no such package: %s; skipping", package)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Walk the package
|
# Walk the package
|
||||||
for root, _, files in os.walk(package_dir, followlinks=True):
|
for root, _, files in os.walk(package_dir, followlinks=True):
|
||||||
|
root_path = Path(root)
|
||||||
files = [filename for filename in files if not is_excluded(filename)]
|
files = [filename for filename in files if not is_excluded(filename)]
|
||||||
if len(files) == 0:
|
if not files:
|
||||||
continue
|
continue
|
||||||
rest = root[len(package_dir) + 1:]
|
|
||||||
dest = path.join(args.target, rest)
|
rest = root_path.relative_to(package_dir)
|
||||||
|
dest = Path(args.target) / rest
|
||||||
|
|
||||||
# Create the directory path
|
# Create the directory path
|
||||||
if rest != "":
|
if rest != Path("."):
|
||||||
# If a non-directory exists with the same name and clobber is enabled, get rid of it.
|
# If a non-directory exists with the same name and clobber is enabled, get rid of it.
|
||||||
if path.exists(dest) and not path.isdir(dest) and args.clobber:
|
if dest.exists() and not dest.is_dir() and args.clobber:
|
||||||
if args.verbose:
|
logger.info("UNLINK %s", dest)
|
||||||
print("UNLINK", dest)
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
os.unlink(dest)
|
dest.unlink()
|
||||||
|
|
||||||
# Make directory
|
# Make directory
|
||||||
if args.verbose:
|
if not dest.exists():
|
||||||
print("DIR", dest)
|
logger.info("DIR %s", dest)
|
||||||
if not args.dry_run and not path.exists(dest):
|
if not args.dry_run:
|
||||||
os.makedirs(dest, mode=0o755)
|
dest.mkdir(parents=True, mode=0o755, exist_ok=True)
|
||||||
|
|
||||||
# Process files
|
# Process files
|
||||||
for filename in files:
|
for filename in files:
|
||||||
src_path = path.realpath(path.join(root, filename))
|
src_path = (root_path / filename).resolve()
|
||||||
dest_path = path.join(dest, filename)
|
dest_path = dest / filename
|
||||||
|
|
||||||
# Skip if the file exists and we're not clobbering
|
# Skip if the file exists and we're not clobbering
|
||||||
if path.exists(dest_path) and not args.clobber:
|
if dest_path.exists() and not args.clobber:
|
||||||
if args.verbose:
|
logger.info("SKIP %s", dest_path)
|
||||||
print("SKIP", dest_path)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Does the file already exist?
|
# Does the file already exist?
|
||||||
if path.isfile(dest_path):
|
if dest_path.is_file() or dest_path.is_symlink():
|
||||||
if args.verbose:
|
logger.info("UNLINK %s", dest_path)
|
||||||
print("UNLINK", dest_path)
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
os.unlink(dest_path)
|
dest_path.unlink()
|
||||||
|
|
||||||
# Link the file
|
# Link the file
|
||||||
if args.verbose:
|
logger.info("LINK %s %s", src_path, dest_path)
|
||||||
print("LINK", src_path, dest_path)
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
os.symlink(src_path, dest_path)
|
try:
|
||||||
|
dest_path.symlink_to(src_path)
|
||||||
|
except OSError as e:
|
||||||
|
logger.error("failed to create symlink %s: %s", dest_path, e)
|
||||||
|
|
||||||
|
|
||||||
def uninstall(args, is_excluded):
|
def uninstall(args: argparse.Namespace, is_excluded: Callable[[str], bool]) -> None:
|
||||||
dirs = []
|
"""Uninstall packages by removing symlinks."""
|
||||||
|
dirs: List[Path] = []
|
||||||
for package in args.packages:
|
for package in args.packages:
|
||||||
package_dir = path.join(args.repository, package)
|
package_dir = Path(args.repository, package)
|
||||||
if not path.isdir(package_dir):
|
if not package_dir.is_dir():
|
||||||
print(f"no such package: {package}; skipping", file=sys.stderr)
|
logger.warning("no such package: %s; skipping", package)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for root, _, files in os.walk(package_dir, followlinks=True):
|
for root, _, files in os.walk(package_dir, followlinks=True):
|
||||||
files = [
|
root_path = Path(root)
|
||||||
filename for filename in files if not is_excluded(filename)]
|
files = [filename for filename in files if not is_excluded(filename)]
|
||||||
if len(files) == 0:
|
if not files:
|
||||||
continue
|
continue
|
||||||
rest = root[len(package_dir) + 1:]
|
|
||||||
dest = path.join(args.target, rest)
|
rest = root_path.relative_to(package_dir)
|
||||||
if rest != "":
|
dest = Path(args.target) / rest
|
||||||
|
|
||||||
|
if rest != Path("."):
|
||||||
dirs.append(dest)
|
dirs.append(dest)
|
||||||
|
|
||||||
for filename in files:
|
for filename in files:
|
||||||
dest_path = path.join(dest, filename)
|
dest_path = dest / filename
|
||||||
if path.islink(dest_path):
|
if not dest_path.exists():
|
||||||
src_path = path.realpath(path.join(root, filename))
|
logger.debug("does not exist: %s", dest_path)
|
||||||
if path.realpath(dest_path) == src_path:
|
continue
|
||||||
if args.verbose:
|
|
||||||
print("UNLINK", dest_path)
|
if dest_path.is_symlink():
|
||||||
|
src_path = (root_path / filename).resolve()
|
||||||
|
try:
|
||||||
|
if dest_path.resolve() == src_path:
|
||||||
|
logger.info("UNLINK %s", dest_path)
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
os.unlink(dest_path)
|
dest_path.unlink()
|
||||||
elif args.verbose:
|
else:
|
||||||
print("SKIP", dest_path)
|
logger.info("SKIP %s (points elsewhere)", dest_path)
|
||||||
elif args.verbose:
|
except (OSError, RuntimeError) as e:
|
||||||
print("SKIP", dest_path)
|
logger.warning("error checking symlink %s: %s", dest_path, e)
|
||||||
|
else:
|
||||||
|
logger.info("SKIP %s (not a symlink)", dest_path)
|
||||||
|
|
||||||
# Delete the directories if empty.
|
# Delete the directories if empty.
|
||||||
for dir_path in sorted(dirs, key=len, reverse=True):
|
for dir_path in sorted(dirs, key=lambda p: len(str(p)), reverse=True):
|
||||||
|
if not dir_path.exists():
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
if args.verbose:
|
logger.info("RMDIR %s", dir_path)
|
||||||
print("RMDIR", dir_path)
|
|
||||||
if not args.dry_run:
|
if not args.dry_run:
|
||||||
os.rmdir(dir_path)
|
dir_path.rmdir()
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
logger.debug("directory not empty: %s", dir_path)
|
||||||
|
|
||||||
|
|
||||||
def make_argparser():
|
def make_argparser() -> argparse.ArgumentParser:
|
||||||
|
"""Create and configure the argument parser."""
|
||||||
parser = argparse.ArgumentParser(description="A dotfile package manager.")
|
parser = argparse.ArgumentParser(description="A dotfile package manager.")
|
||||||
parser.add_argument("--verbose", "-v",
|
parser.add_argument("--verbose", "-v", action="store_true", help="Verbose output")
|
||||||
action="store_true", help="Verbose output")
|
parser.add_argument("--dry-run", "-n", action="store_true", help="Dry run.")
|
||||||
parser.add_argument("--dry-run", "-n",
|
|
||||||
action="store_true", help="Dry run.")
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--target",
|
"--target",
|
||||||
"-t",
|
"-t",
|
||||||
default=path.expanduser('~'),
|
default=str(Path.home()),
|
||||||
help="Target directory in which to place symlinks",
|
help="Target directory in which to place symlinks",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--repository",
|
"--repository",
|
||||||
"-r",
|
"-r",
|
||||||
default=path.expanduser('~/.dotfiles'),
|
default=str(Path.home() / ".dotfiles"),
|
||||||
help="The location of the dotfile repository",
|
help="The location of the dotfile repository",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
@@ -185,55 +217,95 @@ def make_argparser():
|
|||||||
help="Replace files even if they exist.",
|
help="Replace files even if they exist.",
|
||||||
)
|
)
|
||||||
|
|
||||||
subparsers = parser.add_subparsers(dest='command', help='sub-command help')
|
subparsers = parser.add_subparsers(dest="command", help="sub-command help")
|
||||||
|
|
||||||
# List
|
# List
|
||||||
parser_add = subparsers.add_parser('list', help='List packages in the repository')
|
subparsers.add_parser("list", help="List packages in the repository")
|
||||||
|
|
||||||
# Add
|
# Add
|
||||||
parser_add = subparsers.add_parser('add', help='Add a file to a package')
|
parser_add = subparsers.add_parser("add", help="Add a file to a package")
|
||||||
|
parser_add.add_argument("file", metavar="FILE", help="File to stow")
|
||||||
parser_add.add_argument(
|
parser_add.add_argument(
|
||||||
"file", metavar="FILE", help="File to stow"
|
"packages", metavar="PACKAGE", nargs="+", help="Packages to install"
|
||||||
)
|
)
|
||||||
parser_add.add_argument("packages", metavar="PACKAGE", nargs="+", help="Packages to install")
|
|
||||||
|
|
||||||
# Uninstall
|
# Uninstall
|
||||||
parser_uninstall = subparsers.add_parser('uninstall', help='Remove a package')
|
parser_uninstall = subparsers.add_parser("uninstall", help="Remove a package")
|
||||||
parser_uninstall.add_argument("packages", metavar="PACKAGE", nargs="+", help="Packages to uninstall")
|
parser_uninstall.add_argument(
|
||||||
|
"packages", metavar="PACKAGE", nargs="+", help="Packages to uninstall"
|
||||||
|
)
|
||||||
|
|
||||||
# Install
|
# Install
|
||||||
parser_install = subparsers.add_parser('install', help='Install packages')
|
parser_install = subparsers.add_parser("install", help="Install packages")
|
||||||
parser_install.add_argument("packages", metavar="PACKAGE", nargs="+", help="Packages to install")
|
parser_install.add_argument(
|
||||||
|
"packages", metavar="PACKAGE", nargs="+", help="Packages to install"
|
||||||
|
)
|
||||||
|
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main() -> None:
|
||||||
|
"""Main entry point for the stowage script."""
|
||||||
parser = make_argparser()
|
parser = make_argparser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.dry_run:
|
|
||||||
args.verbose = True
|
|
||||||
exclude = [re.compile(fnmatch.translate(pattern))
|
|
||||||
for pattern in args.exclude]
|
|
||||||
|
|
||||||
def is_excluded(filename):
|
# Configure logging
|
||||||
|
log_level = logging.INFO if args.verbose or args.dry_run else logging.WARNING
|
||||||
|
logging.basicConfig(
|
||||||
|
level=log_level,
|
||||||
|
format='%(message)s',
|
||||||
|
stream=sys.stdout
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate repository exists
|
||||||
|
repo_path = Path(args.repository)
|
||||||
|
if not repo_path.exists():
|
||||||
|
logger.error("repository does not exist: %s", args.repository)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Validate target exists
|
||||||
|
target_path = Path(args.target)
|
||||||
|
if not target_path.exists():
|
||||||
|
logger.error("target directory does not exist: %s", args.target)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
exclude = [re.compile(fnmatch.translate(pattern)) for pattern in args.exclude]
|
||||||
|
|
||||||
|
def is_excluded(filename: str) -> bool:
|
||||||
|
"""Check if a filename matches any exclusion pattern."""
|
||||||
return any(pattern.match(filename) for pattern in exclude)
|
return any(pattern.match(filename) for pattern in exclude)
|
||||||
|
|
||||||
if args.command == 'list':
|
if args.command == "list":
|
||||||
for dir in os.listdir(args.repository):
|
if not repo_path.is_dir():
|
||||||
if path.isdir(path.join(args.repository, dir)) and dir[0] != '.':
|
logger.error("repository is not a directory: %s", args.repository)
|
||||||
print(dir)
|
sys.exit(1)
|
||||||
elif args.command == 'add':
|
packages = sorted([
|
||||||
|
item.name for item in repo_path.iterdir()
|
||||||
|
if item.is_dir() and not item.name.startswith(".")
|
||||||
|
])
|
||||||
|
if packages:
|
||||||
|
for package in packages:
|
||||||
|
print(package)
|
||||||
|
else:
|
||||||
|
logger.info("no packages found in repository")
|
||||||
|
elif args.command == "add":
|
||||||
if len(args.packages) > 1:
|
if len(args.packages) > 1:
|
||||||
parser.error("--add only works with a single package")
|
parser.error("add only works with a single package")
|
||||||
args.file = path.normpath(path.join(args.target, args.file))
|
file_path = Path(args.file)
|
||||||
if not path.isfile(args.file):
|
# Handle both absolute and relative paths
|
||||||
|
if not file_path.is_absolute():
|
||||||
|
file_path = Path(args.target) / file_path
|
||||||
|
if not file_path.is_file():
|
||||||
parser.error(f"no such file: {args.file}")
|
parser.error(f"no such file: {args.file}")
|
||||||
|
args.file = str(file_path)
|
||||||
add(args)
|
add(args)
|
||||||
elif args.command == 'install':
|
elif args.command == "install":
|
||||||
install(args, is_excluded)
|
install(args, is_excluded)
|
||||||
elif args.command == 'uninstall':
|
elif args.command == "uninstall":
|
||||||
uninstall(args, is_excluded)
|
uninstall(args, is_excluded)
|
||||||
|
else:
|
||||||
|
parser.print_help()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -1,5 +1,26 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
Usage: $(basename "$0") [LOCATION]
|
||||||
|
|
||||||
|
Fetch weather information from wttr.in for the specified location.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
LOCATION Location to get weather for (default: St Helens)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Show this help message
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") # Get weather for St Helens
|
||||||
|
$(basename "$0") "New York" # Get weather for New York
|
||||||
|
$(basename "$0") "London,UK" # Get weather for London, UK
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
urlencode() {
|
urlencode() {
|
||||||
# urlencode <string>
|
# urlencode <string>
|
||||||
old_lc_collate=$LC_COLLATE
|
old_lc_collate=$LC_COLLATE
|
||||||
@@ -9,7 +30,7 @@ urlencode() {
|
|||||||
for ((i = 0; i < length; i++)); do
|
for ((i = 0; i < length; i++)); do
|
||||||
local c="${1:i:1}"
|
local c="${1:i:1}"
|
||||||
case $c in
|
case $c in
|
||||||
[a-zA-Z0-9.~_-]) printf "$c" ;;
|
[a-zA-Z0-9.~_-]) printf "%s" "$c" ;;
|
||||||
*) printf '%%%02X' "'$c" ;;
|
*) printf '%%%02X' "'$c" ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
@@ -17,5 +38,15 @@ urlencode() {
|
|||||||
LC_COLLATE=$old_lc_collate
|
LC_COLLATE=$old_lc_collate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Handle help flag
|
||||||
|
if [[ "${1:-}" == "-h" ]] || [[ "${1:-}" == "--help" ]]; then
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
location=$(urlencode "${1:-St Helens}")
|
location=$(urlencode "${1:-St Helens}")
|
||||||
curl -s https://wttr.in/$location
|
|
||||||
|
if ! curl -sf "https://wttr.in/$location"; then
|
||||||
|
echo "Error: Failed to fetch weather data. Please check your internet connection or location name." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|||||||
@@ -11,10 +11,6 @@
|
|||||||
rh = reset --hard
|
rh = reset --hard
|
||||||
dist = "!git archive --format=tar -v --prefix=$(git describe HEAD)/ $(git describe HEAD) | gzip -9 > ../$(git describe HEAD).tar.gz"
|
dist = "!git archive --format=tar -v --prefix=$(git describe HEAD)/ $(git describe HEAD) | gzip -9 > ../$(git describe HEAD).tar.gz"
|
||||||
|
|
||||||
[include]
|
|
||||||
path = ~/.gitconfig-gpg
|
|
||||||
path = ~/.gitconfig-local
|
|
||||||
|
|
||||||
[init]
|
[init]
|
||||||
defaultBranch = main
|
defaultBranch = main
|
||||||
|
|
||||||
@@ -52,3 +48,8 @@
|
|||||||
|
|
||||||
[url "ssh://git@github.com/2315-Media"]
|
[url "ssh://git@github.com/2315-Media"]
|
||||||
insteadOf = "https://github.com/2315-Media"
|
insteadOf = "https://github.com/2315-Media"
|
||||||
|
|
||||||
|
[include]
|
||||||
|
path = ~/.gitconfig-gpg
|
||||||
|
path = ~/.gitconfig-work
|
||||||
|
path = ~/.gitconfig-local
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
[user]
|
|
||||||
signingkey = 86DAB9F71FF20A3A
|
|
||||||
|
|
||||||
[commit]
|
|
||||||
gpgsign = true
|
|
||||||
1
irssi/.irssi/.gitignore
vendored
1
irssi/.irssi/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
away.log
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
# For irssi 0.8.4 by marmot
|
|
||||||
|
|
||||||
replaces = { };
|
|
||||||
|
|
||||||
abstracts = {
|
|
||||||
##
|
|
||||||
## generic
|
|
||||||
##
|
|
||||||
|
|
||||||
# text to insert at the beginning of each non-message line
|
|
||||||
line_start = "<%b*%n> ";
|
|
||||||
|
|
||||||
# timestamp styling, nothing by default
|
|
||||||
# timestamp = "$0";
|
|
||||||
timestamp = "%K$0-%n";
|
|
||||||
# any kind of text that needs hilighting, default is to bold
|
|
||||||
hilight = "$0";
|
|
||||||
|
|
||||||
# any kind of error message, default is bright red
|
|
||||||
error = "%R$0-%n";
|
|
||||||
|
|
||||||
# channel name is printed
|
|
||||||
channel = "%b$0-%n";
|
|
||||||
|
|
||||||
# nick is printed
|
|
||||||
nick = "%_$0-%_";
|
|
||||||
|
|
||||||
# nick host is printed
|
|
||||||
nickhost = "[$0-]";
|
|
||||||
|
|
||||||
# server name is printed
|
|
||||||
server = "$0-";
|
|
||||||
|
|
||||||
# some kind of comment is printed
|
|
||||||
comment = "[$0-]";
|
|
||||||
|
|
||||||
# reason for something is printed (part, quit, kick, ..)
|
|
||||||
reason = "[$0-]";
|
|
||||||
|
|
||||||
# mode change is printed ([+o nick])
|
|
||||||
mode = "%_($0-)%_";
|
|
||||||
|
|
||||||
##
|
|
||||||
## channel specific messages
|
|
||||||
##
|
|
||||||
|
|
||||||
# highlighted nick/host is printed (joins)
|
|
||||||
channick_hilight = "%b$0-%n";
|
|
||||||
chanhost_hilight = "{nickhost %b$0-%n}";
|
|
||||||
|
|
||||||
# nick/host is printed (parts, quits, etc.)
|
|
||||||
channick = "%b$0-%n";
|
|
||||||
chanhost = "{nickhost %b$0-%n}";
|
|
||||||
|
|
||||||
# highlighted channel name is printed
|
|
||||||
channelhilight = "%_$0-%_";
|
|
||||||
|
|
||||||
# ban/ban exception/invite list mask is printed
|
|
||||||
ban = "$0-";
|
|
||||||
|
|
||||||
##
|
|
||||||
## messages
|
|
||||||
##
|
|
||||||
|
|
||||||
# the basic styling of how to print message, $0 = nick mode, $1 = nick
|
|
||||||
msgnick = "%B<%n%_$0%_%b$1-%B>%n %|";
|
|
||||||
|
|
||||||
# message from you is printed. "msgownnick" specifies the styling of the
|
|
||||||
# nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
|
|
||||||
# whole line.
|
|
||||||
|
|
||||||
# Example1: You want the message text to be green:
|
|
||||||
# ownmsgnick = "{msgnick $0 $1-}%g";
|
|
||||||
# Example2.1: You want < and > chars to be yellow:
|
|
||||||
# ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
|
|
||||||
# (you'll also have to remove <> from replaces list above)
|
|
||||||
# Example2.2: But you still want to keep <> grey for other messages:
|
|
||||||
# pubmsgnick = "%K{msgnick $0 $1-%K}%n";
|
|
||||||
# pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
|
|
||||||
# pubmsghinick = "%K{msgnick $1 $0$2-%K}%n";
|
|
||||||
# ownprivmsgnick = "%K{msgnick $0-%K}%n";
|
|
||||||
# privmsgnick = "%K{msgnick %R$0-%K}%n";
|
|
||||||
|
|
||||||
# $0 = nick mode, $1 = nick
|
|
||||||
ownmsgnick = "%W<%n%_%_%b$1%n%W>%n%b %|";
|
|
||||||
ownnick = "$0-";
|
|
||||||
|
|
||||||
# public message in channel, $0 = nick mode, $1 = nick
|
|
||||||
pubmsgnick = "{msgnick $0 $1-}";
|
|
||||||
pubnick = "$0-";
|
|
||||||
|
|
||||||
# public message in channel meant for me, $0 = nick mode, $1 = nick
|
|
||||||
pubmsgmenick = "%Y<$0$1-> %|";
|
|
||||||
menick = "$0-";
|
|
||||||
|
|
||||||
# public highlighted message in channel
|
|
||||||
# $0 = highlight color, $1 = nick mode, $2 = nick
|
|
||||||
pubmsghinick = "%Y<$1$2-> %|";
|
|
||||||
|
|
||||||
# channel name is printed with message
|
|
||||||
msgchannel = "%w|%b$0-";
|
|
||||||
|
|
||||||
# private message, $0 = nick, $1 = host
|
|
||||||
privmsg = "<-%b$0%n[%b$1%n] ";
|
|
||||||
|
|
||||||
# private message from you, $0 = "msg", $1 = target nick
|
|
||||||
ownprivmsg = "->[%b$1-%n] $0";
|
|
||||||
|
|
||||||
# own private message in query
|
|
||||||
ownprivmsgnick = "%B<%n%_$0%_%b$1%B>%n%_ %|";
|
|
||||||
ownprivnick = "$0-";
|
|
||||||
|
|
||||||
# private message in query
|
|
||||||
privmsgnick = "{msgnick %b$0-%n}";
|
|
||||||
|
|
||||||
##
|
|
||||||
## Actions (/ME stuff)
|
|
||||||
##
|
|
||||||
|
|
||||||
# used internally by this theme
|
|
||||||
action_core = "%B $0-%b";
|
|
||||||
|
|
||||||
# generic one that's used by most actions
|
|
||||||
action = "{action_core $0-} ";
|
|
||||||
|
|
||||||
# own action, both private/public
|
|
||||||
ownaction = "{action $0-}";
|
|
||||||
|
|
||||||
# own action with target, both private/public
|
|
||||||
ownaction_target = "{action_core $0}{msgchannel $1} ";
|
|
||||||
|
|
||||||
# private action sent by others
|
|
||||||
pvtaction = " %g(*) $0- ";
|
|
||||||
pvtaction_query = "{action $0-}";
|
|
||||||
|
|
||||||
# public action sent by others
|
|
||||||
pubaction = "{action $0-}";
|
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
## other IRC events
|
|
||||||
##
|
|
||||||
|
|
||||||
# notices
|
|
||||||
ownnotice = "-> %gnotice%n[%G$1%n] ";
|
|
||||||
notice = "<- %Gnotice%n[%g$0%n] ";
|
|
||||||
pubnotice_channel = "{msgchannel $0}";
|
|
||||||
pvtnotice_host = "";
|
|
||||||
servernotice = "{notice $0-}";
|
|
||||||
|
|
||||||
# CTCPs
|
|
||||||
ownctcp = "-> %b$0%n[%B$1-%n] ";
|
|
||||||
ctcp = "%B$0-";
|
|
||||||
|
|
||||||
# wallops
|
|
||||||
wallop = "%y$0-: %n";
|
|
||||||
wallop_nick = "%y$0-%n";
|
|
||||||
wallop_action = "%y * $0-%n ";
|
|
||||||
|
|
||||||
# netsplits
|
|
||||||
netsplit = "%b$0-%n";
|
|
||||||
netjoin = "%b$0-%n";
|
|
||||||
|
|
||||||
# /names list
|
|
||||||
names_nick = "%b[%_$0%_$1-]%n ";
|
|
||||||
names_users = "[$0-]";
|
|
||||||
names_channel = "{channel $0-}";
|
|
||||||
|
|
||||||
# DCC
|
|
||||||
dcc = "$0-";
|
|
||||||
dccfile = "%_$0-%_";
|
|
||||||
|
|
||||||
# DCC chat, own msg/action
|
|
||||||
dccownmsg = "*%b=$1-%n*> %g";
|
|
||||||
dccownaction = "{action $0-}";
|
|
||||||
dccownaction_target = "{ownaction_target $0-}";
|
|
||||||
|
|
||||||
# DCC chat, others
|
|
||||||
dccmsg = "*%b=$1-%n* ";
|
|
||||||
dccquerynick = "$0-";
|
|
||||||
dccaction = " (*dcc*) $0- %|";
|
|
||||||
##
|
|
||||||
## statusbar
|
|
||||||
##
|
|
||||||
|
|
||||||
# default background for all statusbars. You can also give
|
|
||||||
# the default foreground color for statusbar items.
|
|
||||||
sb_background = "%4%k";
|
|
||||||
|
|
||||||
# default backround for "default" statusbar group
|
|
||||||
#sb_default_bg = "%4";
|
|
||||||
# background for prompt / input line
|
|
||||||
sb_prompt_bg = "%n";
|
|
||||||
# background for info statusbar
|
|
||||||
sb_info_bg = "%4";
|
|
||||||
# background for topicbar (same default)
|
|
||||||
sb_topic_bg = "%4%k";
|
|
||||||
#sb_topic_fg = "%k";
|
|
||||||
|
|
||||||
# text at the beginning of statusbars. sb-item already puts
|
|
||||||
# space there,so we don't use anything by default.
|
|
||||||
sbstart = "";
|
|
||||||
# text at the end of statusbars. Use space so that it's never
|
|
||||||
# used for anything.
|
|
||||||
sbend = " ";
|
|
||||||
|
|
||||||
prompt = "[$*] ";
|
|
||||||
|
|
||||||
sb = " %W[%n$*%W]%n";
|
|
||||||
sbmode = "(%W+%n$*)";
|
|
||||||
sbaway = " (%GzZzZ%n)";
|
|
||||||
sbservertag = ":$0 (change with ^X)";
|
|
||||||
|
|
||||||
# activity in statusbar
|
|
||||||
|
|
||||||
# ',' separator
|
|
||||||
sb_act_sep = "%k$*";
|
|
||||||
# normal text
|
|
||||||
sb_act_text = "%k$*";
|
|
||||||
# public message
|
|
||||||
sb_act_msg = "%W$*";
|
|
||||||
# hilight
|
|
||||||
sb_act_hilight = "%M$*";
|
|
||||||
# hilight with specified color, $0 = color, $1 = text
|
|
||||||
sb_act_hilight_color = "$0$1-%n";
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
formats = {
|
|
||||||
"fe-common/core" = {
|
|
||||||
join = "%bJoins%n[{channel $2}] %b->%n{channick_hilight $0} {chanhost_hilight $1}";
|
|
||||||
part = "%bParts%n[{channel $2}] %B->%n{channick $0} {chanhost $1} {reason $3}";
|
|
||||||
kick = "{channick $0} was kicked from {channel $1} by {nick $2} {reason $3}";
|
|
||||||
quit = "%bQuits%n %B->%n{channick $0} {chanhost $1} {reason $2}";
|
|
||||||
};
|
|
||||||
"fe-common/irc" = {
|
|
||||||
chanmode_change = "mode[{channel $0}] {mode $1} by {nick $2}";
|
|
||||||
whois = "{nick $0} {nickhost $1@$2}%: ircname : $3";
|
|
||||||
server_chanmode_change = "{netsplit ServerMode}/{channelhilight $0}: {mode $1} by {nick $2}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
servers = (
|
|
||||||
{
|
|
||||||
address = "irc.tilde.chat";
|
|
||||||
chatnet = "tildechat";
|
|
||||||
port = "6697";
|
|
||||||
use_tls = "yes";
|
|
||||||
tls_verify = "no";
|
|
||||||
autoconnect = "yes";
|
|
||||||
tls_cert = "~/.irssi/certs/tilde.pem";
|
|
||||||
},
|
|
||||||
{
|
|
||||||
address = "irc.libera.chat";
|
|
||||||
chatnet = "libera.chat";
|
|
||||||
port = "6697";
|
|
||||||
use_tls = "yes";
|
|
||||||
tls_cert = "~/.irssi/certs/libera.pem";
|
|
||||||
tls_verify = "yes";
|
|
||||||
autoconnect = "yes";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
chatnets = {
|
|
||||||
tildechat = { type = "IRC"; sasl_mechanism = "EXTERNAL"; };
|
|
||||||
"libera.chat" = { type = "IRC"; sasl_mechanism = "EXTERNAL"; };
|
|
||||||
};
|
|
||||||
|
|
||||||
channels = (
|
|
||||||
{ name = "#dimension"; chatnet = "tilechat"; autojoin = "yes"; },
|
|
||||||
{ name = "#dimension"; chatnet = "tildechat"; autojoin = "yes"; },
|
|
||||||
{ name = "#meta"; chatnet = "tildechat"; autojoin = "yes"; },
|
|
||||||
{
|
|
||||||
name = "#idlerpg";
|
|
||||||
chatnet = "tildechat";
|
|
||||||
autojoin = "yes";
|
|
||||||
password = "-botmd";
|
|
||||||
botmasks = "ubergeek@thunix.net";
|
|
||||||
autosendcmd = "^MSG idlerpg_bot login Matalok br6feoot";
|
|
||||||
},
|
|
||||||
{ name = "#livlug"; chatnet = "Freenode"; autojoin = "yes"; },
|
|
||||||
{ name = "#gemini"; chatnet = "tildechat"; autojoin = "yes"; },
|
|
||||||
{ name = "#wiki"; chatnet = "tildechat"; autojoin = "yes"; },
|
|
||||||
{ name = "#tw2002"; chatnet = "tildechat"; autojoin = "yes"; },
|
|
||||||
{ name = "#tildeverse"; chatnet = "tildechat"; autojoin = "yes"; }
|
|
||||||
);
|
|
||||||
settings = {
|
|
||||||
core = {
|
|
||||||
real_name = "Unknown";
|
|
||||||
user_name = "nikdoof";
|
|
||||||
nick = "nikdoof";
|
|
||||||
};
|
|
||||||
"fe-text" = { actlist_sort = "refnum"; colors_ansi_24bit = "yes"; };
|
|
||||||
"fe-common/core" = {
|
|
||||||
activity_hide_level = "QUITS JOINS PARTS KICKS MODES TOPIC NICKS";
|
|
||||||
theme = "IamCyan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
logs = { };
|
|
||||||
hilights = ( { text = "matalok"; nick = "yes"; word = "yes"; } );
|
|
||||||
ignores = ( { level = "JOINS PARTS QUITS"; } );
|
|
||||||
windows = {
|
|
||||||
1 = { immortal = "yes"; name = "(status)"; level = "ALL"; };
|
|
||||||
2 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#dimension";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
3 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#meta";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
4 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#idlerpg";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
5 = { immortal = "yes"; name = "hilight"; sticky = "yes"; };
|
|
||||||
6 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#gemini";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
7 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#wiki";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
8 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#tildeverse";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
9 = {
|
|
||||||
items = (
|
|
||||||
{
|
|
||||||
type = "CHANNEL";
|
|
||||||
chat_type = "IRC";
|
|
||||||
name = "#tw2002";
|
|
||||||
tag = "tildechat";
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mainwindows = {
|
|
||||||
1 = { first_line = "7"; lines = "41"; };
|
|
||||||
5 = { first_line = "1"; lines = "6"; };
|
|
||||||
};
|
|
||||||
@@ -1,294 +0,0 @@
|
|||||||
# When testing changes, the easiest way to reload the theme is with /RELOAD.
|
|
||||||
# This reloads the configuration file too, so if you did any changes remember
|
|
||||||
# to /SAVE it first. Remember also that /SAVE overwrites the theme file with
|
|
||||||
# old data so keep backups :)
|
|
||||||
|
|
||||||
# TEMPLATES:
|
|
||||||
|
|
||||||
# The real text formats that irssi uses are the ones you can find with
|
|
||||||
# /FORMAT command. Back in the old days all the colors and texts were mixed
|
|
||||||
# up in those formats, and it was really hard to change the colors since you
|
|
||||||
# might have had to change them in tens of different places. So, then came
|
|
||||||
# this templating system.
|
|
||||||
|
|
||||||
# Now the /FORMATs don't have any colors in them, and they also have very
|
|
||||||
# little other styling. Most of the stuff you need to change is in this
|
|
||||||
# theme file. If you can't change something here, you can always go back
|
|
||||||
# to change the /FORMATs directly, they're also saved in these .theme files.
|
|
||||||
|
|
||||||
# So .. the templates. They're those {blahblah} parts you see all over the
|
|
||||||
# /FORMATs and here. Their usage is simply {name parameter1 parameter2}.
|
|
||||||
# When irssi sees this kind of text, it goes to find "name" from abstracts
|
|
||||||
# block below and sets "parameter1" into $0 and "parameter2" into $1 (you
|
|
||||||
# can have more parameters of course). Templates can have subtemplates.
|
|
||||||
# Here's a small example:
|
|
||||||
# /FORMAT format hello {colorify {underline world}}
|
|
||||||
# abstracts = { colorify = "%G$0-%n"; underline = "%U$0-%U"; }
|
|
||||||
# When irssi expands the templates in "format", the final string would be:
|
|
||||||
# hello %G%Uworld%U%n
|
|
||||||
# ie. underlined bright green "world" text.
|
|
||||||
# and why "$0-", why not "$0"? $0 would only mean the first parameter,
|
|
||||||
# $0- means all the parameters. With {underline hello world} you'd really
|
|
||||||
# want to underline both of the words, not just the hello (and world would
|
|
||||||
# actually be removed entirely).
|
|
||||||
|
|
||||||
# COLORS:
|
|
||||||
|
|
||||||
# You can find definitions for the color format codes in docs/formats.txt.
|
|
||||||
|
|
||||||
# There's one difference here though. %n format. Normally it means the
|
|
||||||
# default color of the terminal (white mostly), but here it means the
|
|
||||||
# "reset color back to the one it was in higher template". For example
|
|
||||||
# if there was /FORMAT test %g{foo}bar, and foo = "%Y$0%n", irssi would
|
|
||||||
# print yellow "foo" (as set with %Y) but "bar" would be green, which was
|
|
||||||
# set at the beginning before the {foo} template. If there wasn't the %g
|
|
||||||
# at start, the normal behaviour of %n would occur. If you _really_ want
|
|
||||||
# to use the terminal's default color, use %N.
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
# default foreground color (%N) - -1 is the "default terminal color"
|
|
||||||
default_color = "-1";
|
|
||||||
|
|
||||||
# print timestamp/servertag at the end of line, not at beginning
|
|
||||||
info_eol = "false";
|
|
||||||
|
|
||||||
# these characters are automatically replaced with specified color
|
|
||||||
# (dark grey by default)
|
|
||||||
replaces = { "[]=" = "%K$*%n"; };
|
|
||||||
|
|
||||||
abstracts = {
|
|
||||||
##
|
|
||||||
## generic
|
|
||||||
##
|
|
||||||
|
|
||||||
# text to insert at the beginning of each non-message line
|
|
||||||
line_start = "%B-%n!%B-%n ";
|
|
||||||
|
|
||||||
# timestamp styling, nothing by default
|
|
||||||
timestamp = "$*";
|
|
||||||
|
|
||||||
# any kind of text that needs hilighting, default is to bold
|
|
||||||
hilight = "%_$*%_";
|
|
||||||
|
|
||||||
# any kind of error message, default is bright red
|
|
||||||
error = "%R$*%n";
|
|
||||||
|
|
||||||
# channel name is printed
|
|
||||||
channel = "%_$*%_";
|
|
||||||
|
|
||||||
# nick is printed
|
|
||||||
nick = "%_$*%_";
|
|
||||||
|
|
||||||
# nick host is printed
|
|
||||||
nickhost = "[$*]";
|
|
||||||
|
|
||||||
# server name is printed
|
|
||||||
server = "%_$*%_";
|
|
||||||
|
|
||||||
# some kind of comment is printed
|
|
||||||
comment = "[$*]";
|
|
||||||
|
|
||||||
# reason for something is printed (part, quit, kick, ..)
|
|
||||||
reason = "{comment $*}";
|
|
||||||
|
|
||||||
# mode change is printed ([+o nick])
|
|
||||||
mode = "{comment $*}";
|
|
||||||
|
|
||||||
##
|
|
||||||
## channel specific messages
|
|
||||||
##
|
|
||||||
|
|
||||||
# highlighted nick/host is printed (joins)
|
|
||||||
channick_hilight = "%C$*%n";
|
|
||||||
chanhost_hilight = "{nickhost %c$*%n}";
|
|
||||||
|
|
||||||
# nick/host is printed (parts, quits, etc.)
|
|
||||||
channick = "%c$*%n";
|
|
||||||
chanhost = "{nickhost $*}";
|
|
||||||
|
|
||||||
# highlighted channel name is printed
|
|
||||||
channelhilight = "%c$*%n";
|
|
||||||
|
|
||||||
# ban/ban exception/invite list mask is printed
|
|
||||||
ban = "%c$*%n";
|
|
||||||
|
|
||||||
##
|
|
||||||
## messages
|
|
||||||
##
|
|
||||||
|
|
||||||
# the basic styling of how to print message, $0 = nick mode, $1 = nick
|
|
||||||
msgnick = "%K<%n$0$1-%K>%n %|";
|
|
||||||
|
|
||||||
# message from you is printed. "ownnick" specifies the styling of the
|
|
||||||
# nick ($0 part in msgnick) and "ownmsgnick" specifies the styling of the
|
|
||||||
# whole line.
|
|
||||||
|
|
||||||
# Example1: You want the message text to be green:
|
|
||||||
# ownmsgnick = "{msgnick $0 $1-}%g";
|
|
||||||
# Example2.1: You want < and > chars to be yellow:
|
|
||||||
# ownmsgnick = "%Y{msgnick $0 $1-%Y}%n";
|
|
||||||
# (you'll also have to remove <> from replaces list above)
|
|
||||||
# Example2.2: But you still want to keep <> grey for other messages:
|
|
||||||
# pubmsgnick = "%K{msgnick $0 $1-%K}%n";
|
|
||||||
# pubmsgmenick = "%K{msgnick $0 $1-%K}%n";
|
|
||||||
# pubmsghinick = "%K{msgnick $1 $0$2-%n%K}%n";
|
|
||||||
# ownprivmsgnick = "%K{msgnick $*%K}%n";
|
|
||||||
# privmsgnick = "%K{msgnick %R$*%K}%n";
|
|
||||||
|
|
||||||
# $0 = nick mode, $1 = nick
|
|
||||||
ownmsgnick = "{msgnick $0 $1-}";
|
|
||||||
ownnick = "%_$*%n";
|
|
||||||
|
|
||||||
# public message in channel, $0 = nick mode, $1 = nick
|
|
||||||
pubmsgnick = "{msgnick $0 $1-}";
|
|
||||||
pubnick = "%N$*%n";
|
|
||||||
|
|
||||||
# public message in channel meant for me, $0 = nick mode, $1 = nick
|
|
||||||
pubmsgmenick = "{msgnick $0 $1-}";
|
|
||||||
menick = "%Y$*%n";
|
|
||||||
|
|
||||||
# public highlighted message in channel
|
|
||||||
# $0 = highlight color, $1 = nick mode, $2 = nick
|
|
||||||
pubmsghinick = "{msgnick $1 $0$2-%n}";
|
|
||||||
|
|
||||||
# channel name is printed with message
|
|
||||||
msgchannel = "%K:%c$*%n";
|
|
||||||
|
|
||||||
# private message, $0 = nick, $1 = host
|
|
||||||
privmsg = "[%R$0%K(%r$1-%K)%n] ";
|
|
||||||
|
|
||||||
# private message from you, $0 = "msg", $1 = target nick
|
|
||||||
ownprivmsg = "[%r$0%K(%R$1-%K)%n] ";
|
|
||||||
|
|
||||||
# own private message in query
|
|
||||||
ownprivmsgnick = "{msgnick $*}";
|
|
||||||
ownprivnick = "%_$*%n";
|
|
||||||
|
|
||||||
# private message in query
|
|
||||||
privmsgnick = "{msgnick %R$*%n}";
|
|
||||||
|
|
||||||
##
|
|
||||||
## Actions (/ME stuff)
|
|
||||||
##
|
|
||||||
|
|
||||||
# used internally by this theme
|
|
||||||
action_core = "%_ * $*%n";
|
|
||||||
|
|
||||||
# generic one that's used by most actions
|
|
||||||
action = "{action_core $*} ";
|
|
||||||
|
|
||||||
# own action, both private/public
|
|
||||||
ownaction = "{action $*}";
|
|
||||||
|
|
||||||
# own action with target, both private/public
|
|
||||||
ownaction_target = "{action_core $0}%K:%c$1%n ";
|
|
||||||
|
|
||||||
# private action sent by others
|
|
||||||
pvtaction = "%_ (*) $*%n ";
|
|
||||||
pvtaction_query = "{action $*}";
|
|
||||||
|
|
||||||
# public action sent by others
|
|
||||||
pubaction = "{action $*}";
|
|
||||||
|
|
||||||
|
|
||||||
##
|
|
||||||
## other IRC events
|
|
||||||
##
|
|
||||||
|
|
||||||
# whois
|
|
||||||
whois = "%# $[8]0 : $1-";
|
|
||||||
|
|
||||||
# notices
|
|
||||||
ownnotice = "[%r$0%K(%R$1-%K)]%n ";
|
|
||||||
notice = "%K-%M$*%K-%n ";
|
|
||||||
pubnotice_channel = "%K:%m$*";
|
|
||||||
pvtnotice_host = "%K(%m$*%K)";
|
|
||||||
servernotice = "%g!$*%n ";
|
|
||||||
|
|
||||||
# CTCPs
|
|
||||||
ownctcp = "[%r$0%K(%R$1-%K)] ";
|
|
||||||
ctcp = "%g$*%n";
|
|
||||||
|
|
||||||
# wallops
|
|
||||||
wallop = "%_$*%n: ";
|
|
||||||
wallop_nick = "%n$*";
|
|
||||||
wallop_action = "%_ * $*%n ";
|
|
||||||
|
|
||||||
# netsplits
|
|
||||||
netsplit = "%R$*%n";
|
|
||||||
netjoin = "%C$*%n";
|
|
||||||
|
|
||||||
# /names list
|
|
||||||
names_prefix = "";
|
|
||||||
names_nick = "[%_$0%_$1-] ";
|
|
||||||
names_nick_op = "{names_nick $*}";
|
|
||||||
names_nick_halfop = "{names_nick $*}";
|
|
||||||
names_nick_voice = "{names_nick $*}";
|
|
||||||
names_users = "[%g$*%n]";
|
|
||||||
names_channel = "%G$*%n";
|
|
||||||
|
|
||||||
# DCC
|
|
||||||
dcc = "%g$*%n";
|
|
||||||
dccfile = "%_$*%_";
|
|
||||||
|
|
||||||
# DCC chat, own msg/action
|
|
||||||
dccownmsg = "[%r$0%K($1-%K)%n] ";
|
|
||||||
dccownnick = "%R$*%n";
|
|
||||||
dccownquerynick = "%_$*%n";
|
|
||||||
dccownaction = "{action $*}";
|
|
||||||
dccownaction_target = "{action_core $0}%K:%c$1%n ";
|
|
||||||
|
|
||||||
# DCC chat, others
|
|
||||||
dccmsg = "[%G$1-%K(%g$0%K)%n] ";
|
|
||||||
dccquerynick = "%G$*%n";
|
|
||||||
dccaction = "%_ (*dcc*) $*%n %|";
|
|
||||||
|
|
||||||
##
|
|
||||||
## statusbar
|
|
||||||
##
|
|
||||||
|
|
||||||
# default background for all statusbars. You can also give
|
|
||||||
# the default foreground color for statusbar items.
|
|
||||||
sb_background = "%4%k";
|
|
||||||
|
|
||||||
# default backround for "default" statusbar group
|
|
||||||
#sb_default_bg = "%4";
|
|
||||||
# background for prompt / input line
|
|
||||||
sb_prompt_bg = "%n";
|
|
||||||
# background for info statusbar
|
|
||||||
sb_info_bg = "%8";
|
|
||||||
# background for topicbar (same default)
|
|
||||||
#sb_topic_bg = "%4";
|
|
||||||
|
|
||||||
# text at the beginning of statusbars. "sb" already puts a space there,
|
|
||||||
# so we don't use anything by default.
|
|
||||||
sbstart = "";
|
|
||||||
# text at the end of statusbars. Use space so that it's never
|
|
||||||
# used for anything.
|
|
||||||
sbend = " ";
|
|
||||||
|
|
||||||
topicsbstart = "{sbstart $*}";
|
|
||||||
topicsbend = "{sbend $*}";
|
|
||||||
|
|
||||||
prompt = "[$*] ";
|
|
||||||
|
|
||||||
sb = " %K[%n$*%K]%n";
|
|
||||||
sbmode = "(%K+%n$*)";
|
|
||||||
sbaway = " (%GzZzZ%n)";
|
|
||||||
sbservertag = ":$0 (change with ^X)";
|
|
||||||
sbnickmode = "$0";
|
|
||||||
|
|
||||||
# activity in statusbar
|
|
||||||
|
|
||||||
# ',' separator
|
|
||||||
sb_act_sep = "%k$*";
|
|
||||||
# normal text
|
|
||||||
sb_act_text = "%K$*";
|
|
||||||
# public message
|
|
||||||
sb_act_msg = "%W$*";
|
|
||||||
# hilight
|
|
||||||
sb_act_hilight = "%y$*";
|
|
||||||
# hilight with specified color, $0 = color, $1 = text
|
|
||||||
sb_act_hilight_color = "$0$1-%n";
|
|
||||||
};
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Print hilighted messages & private messages to window named "hilight"
|
|
||||||
# for irssi 0.7.99 by Timo Sirainen
|
|
||||||
use Irssi;
|
|
||||||
use vars qw($VERSION %IRSSI);
|
|
||||||
$VERSION = "0.01";
|
|
||||||
%IRSSI = (
|
|
||||||
authors => "Timo \'cras\' Sirainen",
|
|
||||||
contact => "tss\@iki.fi",
|
|
||||||
name => "hilightwin",
|
|
||||||
description => "Print hilighted messages & private messages to window named \"hilight\"",
|
|
||||||
license => "Public Domain",
|
|
||||||
url => "http://irssi.org/",
|
|
||||||
changed => "2002-03-04T22:47+0100"
|
|
||||||
);
|
|
||||||
|
|
||||||
sub sig_printtext {
|
|
||||||
my ($dest, $text, $stripped) = @_;
|
|
||||||
|
|
||||||
if (($dest->{level} & (MSGLEVEL_HILIGHT|MSGLEVEL_MSGS)) &&
|
|
||||||
($dest->{level} & MSGLEVEL_NOHILIGHT) == 0) {
|
|
||||||
$window = Irssi::window_find_name('hilight');
|
|
||||||
|
|
||||||
if ($dest->{level} & MSGLEVEL_PUBLIC) {
|
|
||||||
$text = $dest->{target}.": ".$text;
|
|
||||||
}
|
|
||||||
$window->print($text, MSGLEVEL_CLIENTCRAP) if ($window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$window = Irssi::window_find_name('hilight');
|
|
||||||
Irssi::print("Create a window named 'hilight'") if (!$window);
|
|
||||||
|
|
||||||
Irssi::signal_add('print text', 'sig_printtext');
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
use Irssi;
|
|
||||||
use strict;
|
|
||||||
use FileHandle;
|
|
||||||
|
|
||||||
use vars qw($VERSION %IRSSI);
|
|
||||||
|
|
||||||
$VERSION = "2.1"; # e8934ed1ce04461
|
|
||||||
%IRSSI = (
|
|
||||||
authors => 'cdidier',
|
|
||||||
name => 'tmux_away',
|
|
||||||
description => 'set (un)away if tmux session is attached/detached',
|
|
||||||
license => 'GPL v2',
|
|
||||||
url => 'http://cybione.org',
|
|
||||||
);
|
|
||||||
|
|
||||||
# tmux_away irssi module
|
|
||||||
#
|
|
||||||
# Written by Colin Didier <cdidier@cybione.org> and heavily based on
|
|
||||||
# screen_away irssi module version 0.9.7.1 written by Andreas 'ads' Scherbaum
|
|
||||||
# <ads@ufp.de>.
|
|
||||||
#
|
|
||||||
# Updated by John C. Vernaleo <john@netpurgatory.com> to handle tmux with
|
|
||||||
# named sessions and other code cleanup and forked as version 2.0.
|
|
||||||
#
|
|
||||||
# usage:
|
|
||||||
#
|
|
||||||
# put this script into your autorun directory and/or load it with
|
|
||||||
# /SCRIPT LOAD <name>
|
|
||||||
#
|
|
||||||
# there are 5 settings available:
|
|
||||||
#
|
|
||||||
# /set tmux_away_active ON/OFF/TOGGLE
|
|
||||||
# /set tmux_away_repeat <integer>
|
|
||||||
# /set tmux_away_grace <integer>
|
|
||||||
# /set tmux_away_message <string>
|
|
||||||
# /set tmux_away_window <string>
|
|
||||||
# /set tmux_away_nick <string>
|
|
||||||
#
|
|
||||||
# active means that you will be only set away/unaway, if this
|
|
||||||
# flag is set, default is ON
|
|
||||||
# repeat is the number of seconds, after the script will check the
|
|
||||||
# tmux session status again, default is 5 seconds
|
|
||||||
# grace is the number of seconds, to wait additionally, before
|
|
||||||
# setting you away, default is disabled (0)
|
|
||||||
# message is the away message sent to the server, default: not here ...
|
|
||||||
# window is a window number or name, if set, the script will switch
|
|
||||||
# to this window, if it sets you away, default is '1'
|
|
||||||
# nick is the new nick, if the script goes away
|
|
||||||
# will only be used it not empty
|
|
||||||
|
|
||||||
|
|
||||||
# variables
|
|
||||||
my $timer_name = undef;
|
|
||||||
my $away_status = 0;
|
|
||||||
my %old_nicks = ();
|
|
||||||
my %away = ();
|
|
||||||
|
|
||||||
# Register formats
|
|
||||||
Irssi::theme_register(
|
|
||||||
[
|
|
||||||
'tmux_away_crap',
|
|
||||||
'{line_start}{hilight ' . $IRSSI{'name'} . ':} $0'
|
|
||||||
]);
|
|
||||||
|
|
||||||
# try to find out if we are running in a tmux session
|
|
||||||
# (see if $ENV{TMUX} is set)
|
|
||||||
if (!defined($ENV{TMUX})) {
|
|
||||||
# just return, we will never be called again
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap',
|
|
||||||
"no tmux session!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
my @args_env = split(',', $ENV{TMUX});
|
|
||||||
my $tmux_socket = $args_env[0];
|
|
||||||
|
|
||||||
# register config variables
|
|
||||||
Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_active', 1);
|
|
||||||
Irssi::settings_add_int('misc', $IRSSI{'name'} . '_repeat', 5);
|
|
||||||
Irssi::settings_add_int('misc', $IRSSI{'name'} . '_grace', 0);
|
|
||||||
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_message', "not here...");
|
|
||||||
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_window', "1");
|
|
||||||
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_nick', "");
|
|
||||||
|
|
||||||
|
|
||||||
# check, set or reset the away status
|
|
||||||
sub tmux_away {
|
|
||||||
my ($immediate) = @_;
|
|
||||||
my ($status, @res);
|
|
||||||
|
|
||||||
# only run, if activated
|
|
||||||
if (Irssi::settings_get_bool($IRSSI{'name'} . '_active') != 1) {
|
|
||||||
$away_status = 0;
|
|
||||||
} else {
|
|
||||||
if ($away_status == 0) {
|
|
||||||
# display init message at first time
|
|
||||||
my $grace = Irssi::settings_get_int($IRSSI{'name'} . '_grace');
|
|
||||||
$grace = ", $grace seconds grace" if $grace;
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap',
|
|
||||||
"activating $IRSSI{'name'} (interval: " . Irssi::settings_get_int($IRSSI{'name'} . '_repeat') . " seconds$grace)");
|
|
||||||
$away_status = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
# get actual tmux session status
|
|
||||||
chomp(@res = `tmux -S '$tmux_socket' lsc 2>&1`);
|
|
||||||
chomp(my $tmux_session = `tmux -S '$tmux_socket' display -p '#S' 2>/dev/null`);
|
|
||||||
if ($res[0] =~ /^server not found/ || $? >> 8) {
|
|
||||||
die "error getting tmux session status.";
|
|
||||||
}
|
|
||||||
$status = 1; # away, assumes the session is detached
|
|
||||||
foreach (@res) {
|
|
||||||
my @args_st = split(' ');
|
|
||||||
if ($args_st[1] eq $tmux_session) {
|
|
||||||
$status = 2; # unaway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# unaway -> away
|
|
||||||
if ($status == 1 and $away_status != 1) {
|
|
||||||
if (my $grace = Irssi::settings_get_int($IRSSI{'name'} . '_grace')) {
|
|
||||||
if (!$immediate) {
|
|
||||||
Irssi::timeout_add_once($grace * 1000, 'tmux_away', '1');
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap',
|
|
||||||
"(in grace for away: $grace seconds)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (length(Irssi::settings_get_str($IRSSI{'name'} . '_window')) > 0) {
|
|
||||||
# if length of window is greater then 0, make this window active
|
|
||||||
Irssi::command('window goto ' . Irssi::settings_get_str($IRSSI{'name'} . '_window'));
|
|
||||||
}
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap', "Set away");
|
|
||||||
my $message = Irssi::settings_get_str($IRSSI{'name'} . '_message');
|
|
||||||
if (length($message) == 0) {
|
|
||||||
# we have to set a message or we wouldnt go away
|
|
||||||
$message = "not here ...";
|
|
||||||
}
|
|
||||||
foreach (Irssi::servers()) {
|
|
||||||
if (!$_->{usermode_away}) {
|
|
||||||
# user isn't yet away
|
|
||||||
$away{$_->{'tag'}} = 0;
|
|
||||||
$_->command("^AWAY " . ($_->{chat_type} ne 'SILC' ? "-one " : "") . "$message");
|
|
||||||
if ($_->{chat_type} ne 'XMPP' and length(Irssi::settings_get_str($IRSSI{'name'} . '_nick')) > 0) {
|
|
||||||
# only change if actual nick isn't already the away nick
|
|
||||||
if (Irssi::settings_get_str($IRSSI{'name'} . '_nick') ne $_->{nick}) {
|
|
||||||
# keep old nick
|
|
||||||
$old_nicks{$_->{'tag'}} = $_->{nick};
|
|
||||||
# set new nick
|
|
||||||
$_->command("NICK " . Irssi::settings_get_str($IRSSI{'name'} . '_nick'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
# user is already away, remember this
|
|
||||||
$away{$_->{'tag'}} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$away_status = $status;
|
|
||||||
|
|
||||||
# away -> unaway
|
|
||||||
} elsif ($status == 2 and $away_status != 2) {
|
|
||||||
if (my $grace = Irssi::settings_get_int($IRSSI{'name'} . '_grace')) {
|
|
||||||
if (!$immediate) {
|
|
||||||
Irssi::timeout_add_once($grace * 1000, 'tmux_away', '1');
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap',
|
|
||||||
"(in grace for unaway: $grace seconds)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# unset away
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap', "Reset away");
|
|
||||||
foreach (Irssi::servers()) {
|
|
||||||
if ($away{$_->{'tag'}} == 1) {
|
|
||||||
# user was already away, don't reset away
|
|
||||||
$away{$_->{'tag'}} = 0;
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
$_->command("^AWAY" . (($_->{chat_type} ne 'SILC') ? " -one" : "")) if ($_->{usermode_away});
|
|
||||||
if ($_->{chat_type} ne 'XMPP' and defined($old_nicks{$_->{'tag'}}) and length($old_nicks{$_->{'tag'}}) > 0) {
|
|
||||||
# set old nick
|
|
||||||
$_->command("NICK " . $old_nicks{$_->{'tag'}});
|
|
||||||
$old_nicks{$_->{'tag'}} = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$away_status = $status;
|
|
||||||
} elsif ($immediate) {
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'tmux_away_crap',
|
|
||||||
"in grace aborted");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
# but everytimes install a new timer
|
|
||||||
register_tmux_away_timer();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
# remove old timer and install a new one
|
|
||||||
sub register_tmux_away_timer {
|
|
||||||
# add new timer with new timeout (maybe the timeout has been changed)
|
|
||||||
Irssi::timeout_add_once(Irssi::settings_get_int($IRSSI{'name'} . '_repeat') * 1000, 'tmux_away', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
# init process
|
|
||||||
tmux_away();
|
|
||||||
|
|
||||||
@@ -1,606 +0,0 @@
|
|||||||
## trackbar.pl
|
|
||||||
#
|
|
||||||
# This little script will do just one thing: it will draw a line each time you
|
|
||||||
# switch away from a window. This way, you always know just upto where you've
|
|
||||||
# been reading that window :) It also removes the previous drawn line, so you
|
|
||||||
# don't see double lines.
|
|
||||||
#
|
|
||||||
# redraw trackbar only works on irssi 0.8.17 or higher.
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
## Usage:
|
|
||||||
#
|
|
||||||
# The script works right out of the box, but if you want you can change
|
|
||||||
# the working by /set'ing the following variables:
|
|
||||||
#
|
|
||||||
# Setting: trackbar_style
|
|
||||||
# Description: This setting will be the color of your trackbar line.
|
|
||||||
# By default the value will be '%K', only Irssi color
|
|
||||||
# formats are allowed. If you don't know the color formats
|
|
||||||
# by heart, you can take a look at the formats documentation.
|
|
||||||
# You will find the proper docs on http://www.irssi.org/docs.
|
|
||||||
#
|
|
||||||
# Setting: trackbar_string
|
|
||||||
# Description: This is the string that your line will display. This can
|
|
||||||
# be multiple characters or just one. For example: '~-~-'
|
|
||||||
# The default setting is '-'.
|
|
||||||
# Here are some unicode characters you can try:
|
|
||||||
# "───" => U+2500 => a line
|
|
||||||
# "═══" => U+2550 => a double line
|
|
||||||
# "━━━" => U+2501 => a wide line
|
|
||||||
# "▭ " => U+25ad => a white rectangle
|
|
||||||
#
|
|
||||||
# Setting: trackbar_use_status_window
|
|
||||||
# Description: If this setting is set to OFF, Irssi won't print a trackbar
|
|
||||||
# in the statuswindow
|
|
||||||
#
|
|
||||||
# Setting: trackbar_ignore_windows
|
|
||||||
# Description: A list of windows where no trackbar should be printed
|
|
||||||
#
|
|
||||||
# Setting: trackbar_print_timestamp
|
|
||||||
# Description: If this setting is set to ON, Irssi will print the formatted
|
|
||||||
# timestamp in front of the trackbar.
|
|
||||||
#
|
|
||||||
# Setting: trackbar_require_seen
|
|
||||||
# Description: Only clear the trackbar if it has been scrolled to.
|
|
||||||
#
|
|
||||||
# Setting: trackbar_all_manual
|
|
||||||
# Description: Never clear the trackbar until you do /mark.
|
|
||||||
#
|
|
||||||
# /mark is a command that will redraw the line at the bottom.
|
|
||||||
#
|
|
||||||
# Command: /trackbar, /trackbar goto
|
|
||||||
# Description: Jump to where the trackbar is, to pick up reading
|
|
||||||
#
|
|
||||||
# Command: /trackbar keep
|
|
||||||
# Description: Keep this window's trackbar where it is the next time
|
|
||||||
# you switch windows (then this flag is cleared again)
|
|
||||||
#
|
|
||||||
# Command: /mark, /trackbar mark
|
|
||||||
# Description: Remove the old trackbar and mark the bottom of this
|
|
||||||
# window with a new trackbar
|
|
||||||
#
|
|
||||||
# Command: /trackbar markvisible
|
|
||||||
# Description: Like mark for all visible windows
|
|
||||||
#
|
|
||||||
# Command: /trackbar markall
|
|
||||||
# Description: Like mark for all windows
|
|
||||||
#
|
|
||||||
# Command: /trackbar remove
|
|
||||||
# Description: Remove this window's trackbar
|
|
||||||
#
|
|
||||||
# Command: /trackbar removeall
|
|
||||||
# Description: Remove all windows' trackbars
|
|
||||||
#
|
|
||||||
# Command: /trackbar redraw
|
|
||||||
# Description: Force redraw of trackbars
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
##
|
|
||||||
#
|
|
||||||
# For bugreports and other improvements contact one of the authors.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this script; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
use strict;
|
|
||||||
use warnings;
|
|
||||||
use vars qw($VERSION %IRSSI);
|
|
||||||
|
|
||||||
$VERSION = "2.9"; # a4c78e85092a271
|
|
||||||
|
|
||||||
%IRSSI = (
|
|
||||||
authors => "Peter 'kinlo' Leurs, Uwe Dudenhoeffer, " .
|
|
||||||
"Michiel Holtkamp, Nico R. Wohlgemuth, " .
|
|
||||||
"Geert Hauwaerts",
|
|
||||||
contact => 'peter@pfoe.be',
|
|
||||||
patchers => 'Johan Kiviniemi (UTF-8), Uwe Dudenhoeffer (on-upgrade-remove-line)',
|
|
||||||
name => 'trackbar',
|
|
||||||
description => 'Shows a bar where you have last read a window.',
|
|
||||||
license => 'GNU General Public License',
|
|
||||||
url => 'http://www.pfoe.be/~peter/trackbar/',
|
|
||||||
commands => 'trackbar',
|
|
||||||
);
|
|
||||||
|
|
||||||
## Comments and remarks.
|
|
||||||
#
|
|
||||||
# This script uses settings.
|
|
||||||
# Use /SET to change the value or /TOGGLE to switch it on or off.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Tip: The command 'trackbar' is very useful if you bind that to a key,
|
|
||||||
# so you can easily jump to the trackbar. Please see 'help bind' for
|
|
||||||
# more information about keybindings in Irssi.
|
|
||||||
#
|
|
||||||
# Command: /BIND meta2-P key F1
|
|
||||||
# /BIND F1 command trackbar
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
## Bugfixes and new items in this rewrite.
|
|
||||||
#
|
|
||||||
# * Remove all the trackbars before upgrading.
|
|
||||||
# * New setting trackbar_use_status_window to control the statuswindow trackbar.
|
|
||||||
# * New setting trackbar_print_timestamp to print a timestamp or not.
|
|
||||||
# * New command 'trackbar' to scroll up to the trackbar.
|
|
||||||
# * When resizing your terminal, Irssi will update all the trackbars to the new size.
|
|
||||||
# * When changing trackbar settings, change all the trackbars to the new settings.
|
|
||||||
# * New command 'trackbar mark' to draw a new trackbar (The old '/mark').
|
|
||||||
# * New command 'trackbar markall' to draw a new trackbar in each window.
|
|
||||||
# * New command 'trackbar remove' to remove the trackbar from the current window.
|
|
||||||
# * New command 'trackbar removeall' to remove all the trackbars.
|
|
||||||
# * Don't draw a trackbar in empty windows.
|
|
||||||
# * Added a version check to prevent Irssi redraw errors.
|
|
||||||
# * Fixed a bookmark NULL versus 0 bug.
|
|
||||||
# * Fixed a remove-line bug in Uwe Dudenhoeffer his patch.
|
|
||||||
# * New command 'help trackbar' to display the trackbar commands.
|
|
||||||
# * Fixed an Irssi startup bug, now processing each auto-created window.
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
## Known bugs and the todolist.
|
|
||||||
#
|
|
||||||
# Todo: * Instead of drawing a line, invert the line.
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
## Authors:
|
|
||||||
#
|
|
||||||
# - Main maintainer & author: Peter 'kinlo' Leurs
|
|
||||||
# - Many thanks to Timo 'cras' Sirainen for placing me on my way
|
|
||||||
# - on-upgrade-remove-line patch by Uwe Dudenhoeffer
|
|
||||||
# - trackbar resizing by Michiel Holtkamp (02 Jul 2012)
|
|
||||||
# - scroll to trackbar, window excludes, and timestamp options by Nico R.
|
|
||||||
# Wohlgemuth (22 Sep 2012)
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
## Version history:
|
|
||||||
#
|
|
||||||
# 2.9: - fix crash on /mark in empty window
|
|
||||||
# 2.8: - fix /^join bug
|
|
||||||
# 2.7: - add /set trackbar_all_manual option
|
|
||||||
# 2.5: - merge back on scripts.irssi.org
|
|
||||||
# - fix /trackbar redraw broken in 2.4
|
|
||||||
# - fix legacy encodings
|
|
||||||
# - add workaround for irssi issue #271
|
|
||||||
# 2.4: - add support for horizontal splits
|
|
||||||
# 2.3: - add some features for seen tracking using other scripts
|
|
||||||
# 2.0: - big rewrite based on 1.4
|
|
||||||
# * removed /tb, you can have it with /alias tb trackbar if you want
|
|
||||||
# * subcommand and settings changes:
|
|
||||||
# /trackbar vmark => /trackbar markvisible
|
|
||||||
# /trackbar scroll => /trackbar goto (or just /trackbar)
|
|
||||||
# /trackbar help => /help trackbar
|
|
||||||
# /set trackbar_hide_windows => /set trackbar_ignore_windows
|
|
||||||
# /set trackbar_timestamp => /set trackbar_print_timestamp
|
|
||||||
# * magic line strings were removed, just paste the unicode you want!
|
|
||||||
# * trackbar_timestamp_styled is not currently supported
|
|
||||||
# 1.9: - add version guard
|
|
||||||
# 1.8: - sub draw_bar
|
|
||||||
# 1.7: - Added /tb scroll, trackbar_hide_windows, trackbar_timestamp_timestamp
|
|
||||||
# and trackbar_timestamp_styled
|
|
||||||
# 1.6: - Work around Irssi resize bug, please do /upgrade! (see below)
|
|
||||||
# 1.5: - Resize trackbars in all windows when terminal is resized
|
|
||||||
# 1.4: - Changed our's by my's so the irssi script header is valid
|
|
||||||
# - Removed utf-8 support. In theory, the script should work w/o any
|
|
||||||
# problems for utf-8, just set trackbar_string to a valid utf-8 character
|
|
||||||
# and everything *should* work. However, this script is being plagued by
|
|
||||||
# irssi internal bugs. The function Irssi::settings_get_str does NOT handle
|
|
||||||
# unicode strings properly, hence you will notice problems when setting the bar
|
|
||||||
# to a unicode char. For changing your bar to utf-8 symbols, read the line sub.
|
|
||||||
# 1.3: - Upgrade now removes the trackbars.
|
|
||||||
# - Some code cleanups, other defaults
|
|
||||||
# - /mark sets the line to the bottom
|
|
||||||
# 1.2: - Support for utf-8
|
|
||||||
# - How the bar looks can now be configured with trackbar_string
|
|
||||||
# and trackbar_style
|
|
||||||
# 1.1: - Fixed bug when closing window
|
|
||||||
# 1.0: - Initial release
|
|
||||||
#
|
|
||||||
##
|
|
||||||
|
|
||||||
use Irssi;
|
|
||||||
use Irssi::TextUI;
|
|
||||||
use Encode;
|
|
||||||
|
|
||||||
use POSIX qw(strftime);
|
|
||||||
|
|
||||||
sub cmd_help {
|
|
||||||
my ($args) = @_;
|
|
||||||
if ($args =~ /^trackbar *$/i) {
|
|
||||||
print CLIENTCRAP <<HELP
|
|
||||||
%9Syntax:%9
|
|
||||||
|
|
||||||
TRACKBAR
|
|
||||||
TRACKBAR GOTO
|
|
||||||
TRACKBAR KEEP
|
|
||||||
TRACKBAR MARK
|
|
||||||
TRACKBAR MARKVISIBLE
|
|
||||||
TRACKBAR MARKALL
|
|
||||||
TRACKBAR REMOVE
|
|
||||||
TRACKBAR REMOVEALL
|
|
||||||
TRACKBAR REDRAW
|
|
||||||
|
|
||||||
%9Parameters:%9
|
|
||||||
|
|
||||||
GOTO: Jump to where the trackbar is, to pick up reading
|
|
||||||
KEEP: Keep this window's trackbar where it is the next time
|
|
||||||
you switch windows (then this flag is cleared again)
|
|
||||||
MARK: Remove the old trackbar and mark the bottom of this
|
|
||||||
window with a new trackbar
|
|
||||||
MARKVISIBLE: Like mark for all visible windows
|
|
||||||
MARKALL: Like mark for all windows
|
|
||||||
REMOVE: Remove this window's trackbar
|
|
||||||
REMOVEALL: Remove all windows' trackbars
|
|
||||||
REDRAW: Force redraw of trackbars
|
|
||||||
|
|
||||||
%9Description:%9
|
|
||||||
|
|
||||||
Manage a trackbar. Without arguments, it will scroll up to the trackbar.
|
|
||||||
|
|
||||||
%9Examples:%9
|
|
||||||
|
|
||||||
/TRACKBAR MARK
|
|
||||||
/TRACKBAR REMOVE
|
|
||||||
HELP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Irssi::theme_register([
|
|
||||||
'trackbar_loaded', '%R>>%n %_Scriptinfo:%_ Loaded $0 version $1 by $2.',
|
|
||||||
'trackbar_wrong_version', '%R>>%n %_Trackbar:%_ Please upgrade your client to 0.8.17 or above if you would like to use this feature of trackbar.',
|
|
||||||
'trackbar_all_removed', '%R>>%n %_Trackbar:%_ All the trackbars have been removed.',
|
|
||||||
'trackbar_not_found', '%R>>%n %_Trackbar:%_ No trackbar found in this window.',
|
|
||||||
]);
|
|
||||||
|
|
||||||
my $old_irssi = Irssi::version < 20140701;
|
|
||||||
sub check_version {
|
|
||||||
if ($old_irssi) {
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_wrong_version');
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub is_utf8 {
|
|
||||||
lc Irssi::settings_get_str('term_charset') eq 'utf-8'
|
|
||||||
}
|
|
||||||
|
|
||||||
my (%config, %keep_trackbar, %unseen_trackbar);
|
|
||||||
|
|
||||||
sub remove_one_trackbar {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = shift || $win->view;
|
|
||||||
my $line = $view->get_bookmark('trackbar');
|
|
||||||
if (defined $line) {
|
|
||||||
my $bottom = $view->{bottom};
|
|
||||||
$view->remove_line($line);
|
|
||||||
$win->command('^scrollback end') if $bottom && !$win->view->{bottom};
|
|
||||||
$view->redraw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub add_one_trackbar_pt1 {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = shift || $win->view;
|
|
||||||
|
|
||||||
my $last_cur_line = ($view->{buffer}{cur_line}||+{})->{_irssi};
|
|
||||||
$win->print(line($win->{width}), MSGLEVEL_NEVER);
|
|
||||||
|
|
||||||
my $cur_line = ($win->view->{buffer}{cur_line}||+{})->{_irssi}; # get a fresh buffer
|
|
||||||
|
|
||||||
($last_cur_line//'') ne ($cur_line//'') # printing was successful
|
|
||||||
}
|
|
||||||
|
|
||||||
sub add_one_trackbar_pt2 {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = $win->view;
|
|
||||||
|
|
||||||
$view->set_bookmark_bottom('trackbar');
|
|
||||||
$unseen_trackbar{ $win->{_irssi} } = 1;
|
|
||||||
Irssi::signal_emit("window trackbar added", $win);
|
|
||||||
$view->redraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub update_one_trackbar {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = shift || $win->view;
|
|
||||||
my $force = shift;
|
|
||||||
my $ignored = win_ignored($win, $view);
|
|
||||||
my $success;
|
|
||||||
|
|
||||||
$success = add_one_trackbar_pt1($win, $view) ? 1 : 0
|
|
||||||
if $force || !$ignored;
|
|
||||||
|
|
||||||
remove_one_trackbar($win, $view)
|
|
||||||
if ( $success || !defined $success ) && ( $force || !defined $force || !$ignored );
|
|
||||||
|
|
||||||
add_one_trackbar_pt2($win)
|
|
||||||
if $success;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub win_ignored {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = shift || $win->view;
|
|
||||||
return 1 unless $view->{buffer}{lines_count};
|
|
||||||
return 1 if $win->{name} eq '(status)' && !$config{use_status_window};
|
|
||||||
no warnings 'uninitialized';
|
|
||||||
return 1 if grep { $win->{name} eq $_ || $win->{refnum} eq $_
|
|
||||||
|| $win->get_active_name eq $_ } @{ $config{ignore_windows} };
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub sig_window_changed {
|
|
||||||
my ($newwindow, $oldwindow) = @_;
|
|
||||||
return unless $oldwindow;
|
|
||||||
redraw_one_trackbar($newwindow) unless $old_irssi;
|
|
||||||
trackbar_update_seen($newwindow);
|
|
||||||
return if delete $keep_trackbar{ $oldwindow->{_irssi} };
|
|
||||||
trackbar_update_seen($oldwindow);
|
|
||||||
return if $config{require_seen} && $unseen_trackbar{ $oldwindow->{_irssi } };
|
|
||||||
return if $config{all_manual};
|
|
||||||
update_one_trackbar($oldwindow, undef, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub trackbar_update_seen {
|
|
||||||
my $win = shift;
|
|
||||||
return unless $win;
|
|
||||||
return unless $unseen_trackbar{ $win->{_irssi} };
|
|
||||||
|
|
||||||
my $view = $win->view;
|
|
||||||
my $line = $view->get_bookmark('trackbar');
|
|
||||||
unless ($line) {
|
|
||||||
delete $unseen_trackbar{ $win->{_irssi} };
|
|
||||||
Irssi::signal_emit("window trackbar seen", $win);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
my $startline = $view->{startline};
|
|
||||||
return unless $startline;
|
|
||||||
|
|
||||||
if ($startline->{info}{time} < $line->{info}{time}
|
|
||||||
|| $startline->{_irssi} == $line->{_irssi}) {
|
|
||||||
delete $unseen_trackbar{ $win->{_irssi} };
|
|
||||||
Irssi::signal_emit("window trackbar seen", $win);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub screen_length;
|
|
||||||
{ local $@;
|
|
||||||
eval { require Text::CharWidth; };
|
|
||||||
unless ($@) {
|
|
||||||
*screen_length = sub { Text::CharWidth::mbswidth($_[0]) };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
*screen_length = sub {
|
|
||||||
my $temp = shift;
|
|
||||||
Encode::_utf8_on($temp) if is_utf8();
|
|
||||||
length($temp)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{ my %strip_table = (
|
|
||||||
(map { $_ => '' } (split //, '04261537' . 'kbgcrmyw' . 'KBGCRMYW' . 'U9_8I:|FnN>#[' . 'pP')),
|
|
||||||
(map { $_ => $_ } (split //, '{}%')),
|
|
||||||
);
|
|
||||||
sub c_length {
|
|
||||||
my $o = Irssi::strip_codes($_[0]);
|
|
||||||
$o =~ s/(%(%|Z.{6}|z.{6}|X..|x..|.))/exists $strip_table{$2} ? $strip_table{$2} :
|
|
||||||
$2 =~ m{x(?:0[a-f]|[1-6][0-9a-z]|7[a-x])|z[0-9a-f]{6}}i ? '' : $1/gex;
|
|
||||||
screen_length($o)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub line {
|
|
||||||
my ($width, $time) = @_;
|
|
||||||
my $string = $config{string};
|
|
||||||
$string = ' ' unless length $string;
|
|
||||||
$time ||= time;
|
|
||||||
|
|
||||||
Encode::_utf8_on($string) if is_utf8();
|
|
||||||
my $length = c_length($string);
|
|
||||||
|
|
||||||
my $format = '';
|
|
||||||
if ($config{print_timestamp}) {
|
|
||||||
$format = $config{timestamp_str};
|
|
||||||
$format =~ y/%/\01/;
|
|
||||||
$format =~ s/\01\01/%/g;
|
|
||||||
$format = strftime($format, localtime $time);
|
|
||||||
$format =~ y/\01/%/;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $times = $width / $length;
|
|
||||||
$times += 1 if $times != int $times;
|
|
||||||
my $style = "$config{style}";
|
|
||||||
Encode::_utf8_on($style) if is_utf8();
|
|
||||||
$format .= $style;
|
|
||||||
$width -= c_length($format);
|
|
||||||
$string x= $times;
|
|
||||||
chop $string while length $string && c_length($string) > $width;
|
|
||||||
return $format . $string;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub remove_all_trackbars {
|
|
||||||
for my $window (Irssi::windows) {
|
|
||||||
next unless ref $window;
|
|
||||||
remove_one_trackbar($window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub UNLOAD {
|
|
||||||
remove_all_trackbars();
|
|
||||||
}
|
|
||||||
|
|
||||||
sub redraw_one_trackbar {
|
|
||||||
my $win = shift;
|
|
||||||
my $view = $win->view;
|
|
||||||
my $line = $view->get_bookmark('trackbar');
|
|
||||||
return unless $line;
|
|
||||||
my $bottom = $view->{bottom};
|
|
||||||
$win->print_after($line, MSGLEVEL_NEVER, line($win->{width}, $line->{info}{time}),
|
|
||||||
$line->{info}{time});
|
|
||||||
$view->set_bookmark('trackbar', $win->last_line_insert);
|
|
||||||
$view->remove_line($line);
|
|
||||||
$win->command('^scrollback end') if $bottom && !$win->view->{bottom};
|
|
||||||
$view->redraw;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub redraw_trackbars {
|
|
||||||
return unless check_version();
|
|
||||||
for my $win (Irssi::windows) {
|
|
||||||
next unless ref $win;
|
|
||||||
redraw_one_trackbar($win);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub goto_trackbar {
|
|
||||||
my $win = Irssi::active_win;
|
|
||||||
my $line = $win->view->get_bookmark('trackbar');
|
|
||||||
|
|
||||||
if ($line) {
|
|
||||||
$win->command("scrollback goto ". strftime("%d %H:%M:%S", localtime($line->{info}{time})));
|
|
||||||
} else {
|
|
||||||
$win->printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_not_found');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_mark {
|
|
||||||
update_one_trackbar(Irssi::active_win, undef, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_markall {
|
|
||||||
for my $window (Irssi::windows) {
|
|
||||||
next unless ref $window;
|
|
||||||
update_one_trackbar($window);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub signal_stop {
|
|
||||||
Irssi::signal_stop;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_markvisible {
|
|
||||||
my @wins = Irssi::windows;
|
|
||||||
my $awin =
|
|
||||||
my $bwin = Irssi::active_win;
|
|
||||||
my $awin_counter = 0;
|
|
||||||
Irssi::signal_add_priority('window changed' => 'signal_stop', -99);
|
|
||||||
do {
|
|
||||||
Irssi::active_win->command('window up');
|
|
||||||
$awin = Irssi::active_win;
|
|
||||||
update_one_trackbar($awin);
|
|
||||||
++$awin_counter;
|
|
||||||
} until ($awin->{refnum} == $bwin->{refnum} || $awin_counter >= @wins);
|
|
||||||
Irssi::signal_remove('window changed' => 'signal_stop');
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_trackbar_remove_one {
|
|
||||||
remove_one_trackbar(Irssi::active_win);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_remove_all_trackbars {
|
|
||||||
remove_all_trackbars();
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_all_removed');
|
|
||||||
}
|
|
||||||
|
|
||||||
sub cmd_keep_once {
|
|
||||||
$keep_trackbar{ Irssi::active_win->{_irssi} } = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub trackbar_runsub {
|
|
||||||
my ($data, $server, $item) = @_;
|
|
||||||
$data =~ s/\s+$//g;
|
|
||||||
|
|
||||||
if ($data) {
|
|
||||||
Irssi::command_runsub('trackbar', $data, $server, $item);
|
|
||||||
} else {
|
|
||||||
goto_trackbar();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub update_config {
|
|
||||||
my $was_status_window = $config{use_status_window};
|
|
||||||
$config{style} = Irssi::settings_get_str('trackbar_style');
|
|
||||||
$config{string} = Irssi::settings_get_str('trackbar_string');
|
|
||||||
$config{require_seen} = Irssi::settings_get_bool('trackbar_require_seen');
|
|
||||||
$config{all_manual} = Irssi::settings_get_bool('trackbar_all_manual');
|
|
||||||
$config{ignore_windows} = [ split /[,\s]+/, Irssi::settings_get_str('trackbar_ignore_windows') ];
|
|
||||||
$config{use_status_window} = Irssi::settings_get_bool('trackbar_use_status_window');
|
|
||||||
$config{print_timestamp} = Irssi::settings_get_bool('trackbar_print_timestamp');
|
|
||||||
if (defined $was_status_window && $was_status_window != $config{use_status_window}) {
|
|
||||||
if (my $swin = Irssi::window_find_name('(status)')) {
|
|
||||||
if ($config{use_status_window}) {
|
|
||||||
update_one_trackbar($swin);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
remove_one_trackbar($swin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($config{print_timestamp}) {
|
|
||||||
my $ts_format = Irssi::settings_get_str('timestamp_format');
|
|
||||||
my $ts_theme = Irssi::current_theme->get_format('fe-common/core', 'timestamp');
|
|
||||||
my $render_str = Irssi::current_theme->format_expand($ts_theme);
|
|
||||||
(my $ts_escaped = $ts_format) =~ s/([%\$])/$1$1/g;
|
|
||||||
$render_str =~ s/(?|\$(.)(?!\w)|\$\{(\w+)\})/$1 eq 'Z' ? $ts_escaped : $1/ge;
|
|
||||||
$config{timestamp_str} = $render_str;
|
|
||||||
}
|
|
||||||
redraw_trackbars() unless $old_irssi;
|
|
||||||
}
|
|
||||||
|
|
||||||
Irssi::settings_add_str('trackbar', 'trackbar_string', is_utf8() ? "\x{2500}" : '-');
|
|
||||||
Irssi::settings_add_str('trackbar', 'trackbar_style', '%K');
|
|
||||||
Irssi::settings_add_str('trackbar', 'trackbar_ignore_windows', '');
|
|
||||||
Irssi::settings_add_bool('trackbar', 'trackbar_use_status_window', 1);
|
|
||||||
Irssi::settings_add_bool('trackbar', 'trackbar_print_timestamp', 0);
|
|
||||||
Irssi::settings_add_bool('trackbar', 'trackbar_require_seen', 0);
|
|
||||||
Irssi::settings_add_bool('trackbar', 'trackbar_all_manual', 0);
|
|
||||||
|
|
||||||
update_config();
|
|
||||||
|
|
||||||
Irssi::signal_add_last( 'mainwindow resized' => 'redraw_trackbars')
|
|
||||||
unless $old_irssi;
|
|
||||||
|
|
||||||
Irssi::signal_register({'window trackbar added' => [qw/Irssi::UI::Window/]});
|
|
||||||
Irssi::signal_register({'window trackbar seen' => [qw/Irssi::UI::Window/]});
|
|
||||||
Irssi::signal_register({'gui page scrolled' => [qw/Irssi::UI::Window/]});
|
|
||||||
Irssi::signal_add_last('gui page scrolled' => 'trackbar_update_seen');
|
|
||||||
|
|
||||||
Irssi::signal_add('setup changed' => 'update_config');
|
|
||||||
Irssi::signal_add_priority('session save' => 'remove_all_trackbars', Irssi::SIGNAL_PRIORITY_HIGH-1);
|
|
||||||
|
|
||||||
Irssi::signal_add('window changed' => 'sig_window_changed');
|
|
||||||
|
|
||||||
Irssi::command_bind('trackbar goto' => 'goto_trackbar');
|
|
||||||
Irssi::command_bind('trackbar keep' => 'cmd_keep_once');
|
|
||||||
Irssi::command_bind('trackbar mark' => 'cmd_mark');
|
|
||||||
Irssi::command_bind('trackbar markvisible' => 'cmd_markvisible');
|
|
||||||
Irssi::command_bind('trackbar markall' => 'cmd_markall');
|
|
||||||
Irssi::command_bind('trackbar remove' => 'cmd_trackbar_remove_one');
|
|
||||||
Irssi::command_bind('trackbar removeall' => 'cmd_remove_all_trackbars');
|
|
||||||
Irssi::command_bind('trackbar redraw' => 'redraw_trackbars');
|
|
||||||
Irssi::command_bind('trackbar' => 'trackbar_runsub');
|
|
||||||
Irssi::command_bind('mark' => 'cmd_mark');
|
|
||||||
Irssi::command_bind_last('help' => 'cmd_help');
|
|
||||||
|
|
||||||
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'trackbar_loaded', $IRSSI{name}, $VERSION, $IRSSI{authors});
|
|
||||||
|
|
||||||
# workaround for issue #271
|
|
||||||
{ package Irssi::Nick }
|
|
||||||
@@ -5,6 +5,7 @@ tap "homebrew/bundle"
|
|||||||
tap "sass/sass"
|
tap "sass/sass"
|
||||||
|
|
||||||
brew "awscli"
|
brew "awscli"
|
||||||
|
brew "awslogs"
|
||||||
brew "dockutil"
|
brew "dockutil"
|
||||||
brew "fluxcd/tap/flux"
|
brew "fluxcd/tap/flux"
|
||||||
brew "go"
|
brew "go"
|
||||||
@@ -18,10 +19,13 @@ brew "mas"
|
|||||||
brew "poetry"
|
brew "poetry"
|
||||||
brew "sass/sass/sass"
|
brew "sass/sass/sass"
|
||||||
brew "smartmontools"
|
brew "smartmontools"
|
||||||
brew "terraform"
|
brew "hashicorp/tap/terraform"
|
||||||
|
brew "terraform-local"
|
||||||
brew "tz"
|
brew "tz"
|
||||||
brew "uv"
|
brew "uv"
|
||||||
brew "yazi"
|
brew "yazi"
|
||||||
|
brew "jq"
|
||||||
|
brew "fzf"
|
||||||
|
|
||||||
cask "appcleaner"
|
cask "appcleaner"
|
||||||
cask "balenaetcher"
|
cask "balenaetcher"
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
# Updates Homebrew installation from the Brewfile
|
|
||||||
function update-brewfile() {
|
|
||||||
brew bundle check --file "$HOME/.config/Brewfile" || brew bundle --cleanup -f --file "$HOME/.config/Brewfile"
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Updates the dock
|
|
||||||
function update-dock() {
|
|
||||||
idx=1
|
|
||||||
while read entry; do
|
|
||||||
app_name=$(echo "$entry" | cut -d $'\t' -f 1)
|
|
||||||
app_path=$(echo "$entry" | cut -d $'\t' -f 2)
|
|
||||||
app_type=$(echo "$entry" | cut -d $'\t' -f 3)
|
|
||||||
idx=$((idx+1))
|
|
||||||
dockutil --no-restart -a "$app_path" > /dev/null 2>&1
|
|
||||||
if [ "$app_type" = "persisentApps" ]; then
|
|
||||||
dockutil --move "$app_name" -p $idx
|
|
||||||
fi
|
|
||||||
done < ~/.dotfiles/macos/.config/dockConfig.txt
|
|
||||||
killall Dock
|
|
||||||
}
|
|
||||||
36
macos/.config/shell-common/macos.sh
Normal file
36
macos/.config/shell-common/macos.sh
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# macOS tags downloads with "com.apple.quarantine" attribute to prevent execution of downloaded files until the user explicitly allows it.
|
||||||
|
# This function removes that attribute, allowing the file to be opened without warning.
|
||||||
|
# Usage: itsok <file_path>
|
||||||
|
function itsok() {
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
xattr -d com.apple.quarantine $1
|
||||||
|
else
|
||||||
|
echo 'This only works on macOS...'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Runs a brew bundle check and installs missing packages
|
||||||
|
# Usage: update-brewfile
|
||||||
|
function update-brewfile() {
|
||||||
|
brew bundle check --file "$HOME/.config/Brewfile" || brew bundle --cleanup -f --file "$HOME/.config/Brewfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Updates the macOS Dock based on a configuration file
|
||||||
|
# The configuration file should be in the format:
|
||||||
|
# app_name<TAB>app_path<TAB>app_type
|
||||||
|
# where app_type can be "persisentApps" or "other"
|
||||||
|
# Usage: update-dock
|
||||||
|
function update-dock() {
|
||||||
|
idx=1
|
||||||
|
while read entry; do
|
||||||
|
app_name=$(echo "$entry" | cut -d $'\t' -f 1)
|
||||||
|
app_path=$(echo "$entry" | cut -d $'\t' -f 2)
|
||||||
|
app_type=$(echo "$entry" | cut -d $'\t' -f 3)
|
||||||
|
idx=$((idx+1))
|
||||||
|
dockutil --no-restart -a "$app_path" > /dev/null 2>&1
|
||||||
|
if [ "$app_type" = "persisentApps" ]; then
|
||||||
|
dockutil --move "$app_name" -p $idx
|
||||||
|
fi
|
||||||
|
done < ~/.dotfiles/macos/.config/dockConfig.txt
|
||||||
|
killall Dock
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Required parameters:
|
|
||||||
# @raycast.schemaVersion 1
|
|
||||||
# @raycast.title Flush DNS
|
|
||||||
# @raycast.mode fullOutput
|
|
||||||
# @raycast.packageName Browsing
|
|
||||||
|
|
||||||
# Optional parameters:
|
|
||||||
# @raycast.icon 💾
|
|
||||||
|
|
||||||
# Documentation:
|
|
||||||
# @raycast.author Andrew Williams
|
|
||||||
# @raycast.authorURL https://github.com/nikdoof
|
|
||||||
# @raycast.description Flushes DNS cache on macOS
|
|
||||||
|
|
||||||
sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/osascript
|
|
||||||
|
|
||||||
# Required parameters:
|
|
||||||
# @raycast.author Jax0rz
|
|
||||||
# @authorURL https://github.com/Jax0rz
|
|
||||||
# @raycast.schemaVersion 1
|
|
||||||
# @raycast.title Move Downloads to Trash
|
|
||||||
# @raycast.mode silent
|
|
||||||
# @raycast.packageName System
|
|
||||||
# @raycast.needsConfirmation true
|
|
||||||
|
|
||||||
# Optional parameters:
|
|
||||||
# @raycast.icon images/move-downloads-to-trash.png
|
|
||||||
|
|
||||||
tell application "Finder"
|
|
||||||
set allDownloads to every item of folder (path to downloads folder as text)
|
|
||||||
move allDownloads to trash
|
|
||||||
log ""
|
|
||||||
end tell
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/osascript
|
|
||||||
|
|
||||||
# Required parameters:
|
|
||||||
# @raycast.schemaVersion 1
|
|
||||||
# @raycast.title Viscosity: Connect
|
|
||||||
# @raycast.mode silent
|
|
||||||
# @raycast.packageName Viscosity
|
|
||||||
#
|
|
||||||
# Optional parameters:
|
|
||||||
# @raycast.icon images/viscosity.png
|
|
||||||
# @raycast.needsConfirmation false
|
|
||||||
# @raycast.argument1 { "type": "text", "placeholder": "Configuration" }
|
|
||||||
#
|
|
||||||
# Documentation:
|
|
||||||
# @raycast.description Connect a VPN viscosity configuration.
|
|
||||||
# @raycast.author Luigi Cardito (credits Achille Lacoin https://github.com/pomdtr)
|
|
||||||
# @raycast.authorURL https://github.com/lcardito
|
|
||||||
|
|
||||||
on run argv
|
|
||||||
tell application "Viscosity" to connect (item 1 of argv)
|
|
||||||
return # Discard Output
|
|
||||||
end run
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/osascript
|
|
||||||
|
|
||||||
# Required parameters:
|
|
||||||
# @raycast.schemaVersion 1
|
|
||||||
# @raycast.title Viscosity: Disconnect
|
|
||||||
# @raycast.mode silent
|
|
||||||
# @raycast.packageName Viscosity
|
|
||||||
#
|
|
||||||
# Optional parameters:
|
|
||||||
# @raycast.icon images/viscosity.png
|
|
||||||
# @raycast.needsConfirmation false
|
|
||||||
# @raycast.argument1 { "type": "text", "placeholder": "Configuration" }
|
|
||||||
#
|
|
||||||
# Documentation:
|
|
||||||
# @raycast.description Disconnect a VPN configuration.
|
|
||||||
# @raycast.author Luigi Cardito (credits Achille Lacoin https://github.com/pomdtr)
|
|
||||||
# @raycast.authorURL https://github.com/lcardito
|
|
||||||
|
|
||||||
on run argv
|
|
||||||
tell application "Viscosity" to disconnect (item 1 of argv)
|
|
||||||
return # Discard Output
|
|
||||||
end run
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
#!/usr/bin/osascript
|
|
||||||
|
|
||||||
# @raycast.title Toggle Wi-Fi
|
|
||||||
# @raycast.author Vincent Dörig
|
|
||||||
# @raycast.authorURL https://github.com/vincentdoerig
|
|
||||||
# @raycast.description Toggle your Wi-Fi connection.
|
|
||||||
|
|
||||||
# @raycast.icon images/wifi-dark.png
|
|
||||||
# @raycast.iconDark images/wifi.png
|
|
||||||
# @raycast.mode silent
|
|
||||||
# @raycast.packageName System
|
|
||||||
# @raycast.schemaVersion 1
|
|
||||||
|
|
||||||
# Wi-Fi interface, should normally be either `en0` or `en1`
|
|
||||||
# ⌥ + click the wifi icon in your menu bar to display the Wi-Fi interface name
|
|
||||||
set Interface to "en0"
|
|
||||||
|
|
||||||
set NetworkStatus to (do shell script "networksetup -getairportnetwork " & Interface)
|
|
||||||
if (NetworkStatus contains "off") then
|
|
||||||
# turn Wi-Fi on
|
|
||||||
do shell script "networksetup -setairportpower Interface on"
|
|
||||||
do shell script "echo Wi-Fi turned on"
|
|
||||||
else
|
|
||||||
# turn Wi-Fi off
|
|
||||||
do shell script "networksetup -setairportpower Interface off"
|
|
||||||
do shell script "echo Wi-Fi turned off"
|
|
||||||
end if
|
|
||||||
246
shell-common/.config/shell-common/aws.sh
Normal file
246
shell-common/.config/shell-common/aws.sh
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
# Get the list of AWS profiles
|
||||||
|
function awsprofiles() {
|
||||||
|
profiles=$(aws --no-cli-pager configure list-profiles 2> /dev/null)
|
||||||
|
if [[ -z "$profiles" ]]; then
|
||||||
|
echo "No AWS profiles found in '$HOME/.aws/config, check if ~/.aws/config exists and properly configured.'"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
echo $profiles
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# login via SSO to AWS
|
||||||
|
function awslogin() {
|
||||||
|
local profile=""
|
||||||
|
local region=""
|
||||||
|
|
||||||
|
# Parse optional arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--profile)
|
||||||
|
profile="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--region)
|
||||||
|
region="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Usage: awslogin [--profile prof] [--region region]"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Get available profiles
|
||||||
|
local available_profiles
|
||||||
|
available_profiles=$(aws --no-cli-pager configure list-profiles 2> /dev/null)
|
||||||
|
if [[ -z "$available_profiles" ]]; then
|
||||||
|
echo "No AWS profiles found in ~/.aws/config"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no profile provided, use fzf to select one
|
||||||
|
if [[ -z "$profile" ]]; then
|
||||||
|
profile=$(echo "$available_profiles" | fzf --header "Select AWS profile" --height 40%)
|
||||||
|
if [[ -z "$profile" ]]; then
|
||||||
|
echo "No profile selected."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Check if provided profile exists
|
||||||
|
if ! echo "$available_profiles" | grep -qx "$profile"; then
|
||||||
|
echo "Profile '$profile' not found. Searching for matches..."
|
||||||
|
local matched_profiles
|
||||||
|
matched_profiles=$(echo "$available_profiles" | grep -i "$profile")
|
||||||
|
|
||||||
|
if [[ -z "$matched_profiles" ]]; then
|
||||||
|
echo "No matching profiles found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
profile=$(echo "$matched_profiles" | fzf --header "Select AWS profile" --height 40%)
|
||||||
|
if [[ -z "$profile" ]]; then
|
||||||
|
echo "No profile selected."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build AWS CLI options
|
||||||
|
local aws_opts=()
|
||||||
|
[[ -n "$profile" ]] && aws_opts+=(--profile "$profile")
|
||||||
|
[[ -n "$region" ]] && aws_opts+=(--region "$region")
|
||||||
|
|
||||||
|
# Login via SSO
|
||||||
|
aws sso login "${aws_opts[@]}"
|
||||||
|
|
||||||
|
# Export AWS credentials
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[[ -n "$line" ]] && eval "export $line"
|
||||||
|
done < <(aws configure export-credentials --format env "${aws_opts[@]}")
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
echo "Failed to export AWS credentials."
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
echo "AWS login successful. Credentials exported."
|
||||||
|
export AWS_PROFILE_ACTIVE="$profile"
|
||||||
|
if [[ -n "$profile" ]]; then
|
||||||
|
export AWS_PROFILE_DISPLAY="[aws: $profile]"
|
||||||
|
else
|
||||||
|
export AWS_PROFILE_DISPLAY=""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function awslogout() {
|
||||||
|
unset AWS_PROFILE_ACTIVE
|
||||||
|
unset AWS_ACCESS_KEY_ID
|
||||||
|
unset AWS_SECRET_ACCESS_KEY
|
||||||
|
unset AWS_SESSION_TOKEN
|
||||||
|
unset AWS_CREDENTIAL_EXPIRATION
|
||||||
|
export AWS_PROFILE_DISPLAY=""
|
||||||
|
echo "AWS profile and credentials cleared."
|
||||||
|
}
|
||||||
|
|
||||||
|
function _aws_creds_expiration_check() {
|
||||||
|
if [[ -n "$AWS_CREDENTIAL_EXPIRATION" ]]; then
|
||||||
|
local expiration_epoch
|
||||||
|
local current_epoch
|
||||||
|
|
||||||
|
# Convert expiration time to epoch (handles ISO 8601 format)
|
||||||
|
if command -v gdate &> /dev/null; then
|
||||||
|
# macOS with GNU coreutils installed
|
||||||
|
expiration_epoch=$(gdate -d "$AWS_CREDENTIAL_EXPIRATION" +%s 2>/dev/null)
|
||||||
|
current_epoch=$(gdate +%s)
|
||||||
|
else
|
||||||
|
# macOS with BSD date
|
||||||
|
expiration_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%S%z" "$AWS_CREDENTIAL_EXPIRATION" +%s 2>/dev/null)
|
||||||
|
current_epoch=$(date +%s)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $? -eq 0 && -n "$expiration_epoch" ]]; then
|
||||||
|
if [[ $current_epoch -ge $expiration_epoch ]]; then
|
||||||
|
echo "AWS credentials have expired. Logging out..."
|
||||||
|
awslogout
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# easy access to SSH
|
||||||
|
function awsssh() {
|
||||||
|
local profile=""
|
||||||
|
local region=""
|
||||||
|
local username="ansible"
|
||||||
|
local search=""
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--profile)
|
||||||
|
profile="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--region)
|
||||||
|
region="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
search="$1"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$search" ]]; then
|
||||||
|
echo "Usage: awsssh [--profile prof] [--region reg] [user@]search-term"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract username if provided as user@search
|
||||||
|
if [[ "$search" == *@* ]]; then
|
||||||
|
username="${search%@*}"
|
||||||
|
search="${search#*@}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build AWS CLI options
|
||||||
|
local aws_opts=()
|
||||||
|
[[ -n "$profile" ]] && aws_opts+=(--profile "$profile")
|
||||||
|
[[ -n "$region" ]] && aws_opts+=(--region "$region")
|
||||||
|
|
||||||
|
# Get matching instances
|
||||||
|
local instances
|
||||||
|
instances=$(aws ec2 describe-instances \
|
||||||
|
--filters "Name=tag:Name,Values=*$search*" \
|
||||||
|
--query 'Reservations[].Instances[].{
|
||||||
|
Name: Tags[?Key==`Name`].Value | [0],
|
||||||
|
IP: PublicIpAddress,
|
||||||
|
InstanceId: InstanceId
|
||||||
|
}' \
|
||||||
|
--output json \
|
||||||
|
"${aws_opts[@]}")
|
||||||
|
|
||||||
|
if [[ $? -ne 0 || -z "$instances" || "$instances" == "[]" ]]; then
|
||||||
|
echo "Failed to retrieve instances or no match found."
|
||||||
|
return 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Select instance using fzf
|
||||||
|
local selection
|
||||||
|
selection=$(echo "$instances" | jq -r '.[] | "\(.Name): \(.IP // "no-ip") (\(.InstanceId))"' |
|
||||||
|
fzf -1 -0 --header "Select an instance")
|
||||||
|
|
||||||
|
if [[ -z "$selection" ]]; then
|
||||||
|
echo "No valid instance selected."
|
||||||
|
return 3
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract IP and InstanceId from selection
|
||||||
|
local ip instance_id
|
||||||
|
ip=$(echo "$selection" | sed -E 's/.*: (.*) \(.*/\1/')
|
||||||
|
instance_id=$(echo "$selection" | sed -E 's/.*\((i-[a-z0-9]+)\).*/\1/')
|
||||||
|
|
||||||
|
if [[ "$ip" != "no-ip" ]]; then
|
||||||
|
echo "Connecting to $username@$ip via SSH..."
|
||||||
|
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "${username}@${ip}"
|
||||||
|
else
|
||||||
|
echo "No public IP found. Falling back to AWS Session Manager..."
|
||||||
|
aws ssm start-session --target "$instance_id" "${aws_opts[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function instances() {
|
||||||
|
local profile=""
|
||||||
|
local region=""
|
||||||
|
|
||||||
|
# Parse optional arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--profile)
|
||||||
|
profile="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--region)
|
||||||
|
region="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Usage: list_ec2_instances [--profile prof] [--region region]"
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Build AWS CLI options
|
||||||
|
local aws_opts=()
|
||||||
|
[[ -n "$profile" ]] && aws_opts+=(--profile "$profile")
|
||||||
|
[[ -n "$region" ]] && aws_opts+=(--region "$region")
|
||||||
|
|
||||||
|
# Query EC2 for names and instance IDs
|
||||||
|
aws ec2 describe-instances \
|
||||||
|
--query 'Reservations[].Instances[].{Name: Tags[?Key==`Name`].Value | [0], InstanceId: InstanceId}' \
|
||||||
|
--output table \
|
||||||
|
"${aws_opts[@]}"
|
||||||
|
}
|
||||||
@@ -32,14 +32,14 @@ if [ -f $HOME/.cargo/env ]; then
|
|||||||
source $HOME/.cargo/env
|
source $HOME/.cargo/env
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# https://github.com/oz/tz
|
|
||||||
if [ -x "$(command -v tz)" ]; then
|
|
||||||
export TZ_LIST="America/New_York,WDW;America/Los_Angeles,DLR;Europe/Paris,DLP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# macOS Specific envs
|
# macOS Specific envs
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
# Homebrew
|
# Homebrew
|
||||||
export HOMEBREW_NO_ENV_HINTS=1
|
export HOMEBREW_NO_ENV_HINTS=1
|
||||||
[ -d /opt/homebrew ] && eval $(/opt/homebrew/bin/brew shellenv)
|
[ -d /opt/homebrew ] && eval "$(/opt/homebrew/bin/brew shellenv)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# https://github.com/oz/tz
|
||||||
|
if [ -x "$(command -v tz)" ]; then
|
||||||
|
export TZ_LIST="Europe/Dublin,Portwest HQ;America/New_York,WDW;America/Los_Angeles,DLR;Europe/Paris,DLP"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
# Git pulls latest dotfiles
|
# Git pulls latest dotfiles
|
||||||
function update-dotfiles() {
|
function update-dotfiles() {
|
||||||
prevdir=$PWD
|
prevdir=$PWD
|
||||||
if [ -d "${HOME}/.dotfiles" ]; then
|
for dir in "${HOME}/.dotfiles" "${HOME}/.dotfiles-private" "${HOME}/.dotfiles-work"; do
|
||||||
cd $HOME/.dotfiles
|
if [ -d "$dir" ]; then
|
||||||
|
cd "$dir"
|
||||||
git pull --rebase --autostash
|
git pull --rebase --autostash
|
||||||
fi
|
fi
|
||||||
if [ -d "${HOME}/.dotfiles-private" ]; then
|
done
|
||||||
cd $HOME/.dotfiles-private
|
cd "$prevdir"
|
||||||
git pull --rebase --autostash
|
|
||||||
fi
|
|
||||||
cd $prevdir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Wrapper around ssh-add to ease usage and also ensure basic timeouts
|
# Wrapper around ssh-add to easily add SSH keys with a timeout
|
||||||
|
# Usage: add-sshkey [key_name]
|
||||||
function add-sshkey() {
|
function add-sshkey() {
|
||||||
TIMEOUT="2h"
|
TIMEOUT="2h"
|
||||||
NAME=$1
|
NAME=$1
|
||||||
@@ -40,95 +39,3 @@ function demoprompt() {
|
|||||||
clear
|
clear
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Tag the file as OK to run
|
|
||||||
function itsok() {
|
|
||||||
if [[ $(uname) == "Darwin" ]]; then
|
|
||||||
xattr -d com.apple.quarantine $1
|
|
||||||
else
|
|
||||||
echo 'This only works on macOS...'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# easy access to SSH
|
|
||||||
function awsssh() {
|
|
||||||
local profile=""
|
|
||||||
local region=""
|
|
||||||
local username="ec2-user"
|
|
||||||
local search=""
|
|
||||||
|
|
||||||
# Parse arguments
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
--profile)
|
|
||||||
profile="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
--region)
|
|
||||||
region="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
search="$1"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "$search" ]]; then
|
|
||||||
echo "Usage: awsssh [--profile prof] [--region reg] [user@]search-term"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract username if provided as user@search
|
|
||||||
if [[ "$search" == *@* ]]; then
|
|
||||||
username="${search%@*}"
|
|
||||||
search="${search#*@}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build AWS CLI options
|
|
||||||
local aws_opts=()
|
|
||||||
[[ -n "$profile" ]] && aws_opts+=(--profile "$profile")
|
|
||||||
[[ -n "$region" ]] && aws_opts+=(--region "$region")
|
|
||||||
|
|
||||||
# Get matching instances
|
|
||||||
local instances
|
|
||||||
instances=$(aws ec2 describe-instances \
|
|
||||||
--filters "Name=tag:Name,Values=*$search*" \
|
|
||||||
--query 'Reservations[].Instances[].{
|
|
||||||
Name: Tags[?Key==`Name`].Value | [0],
|
|
||||||
IP: PublicIpAddress,
|
|
||||||
InstanceId: InstanceId
|
|
||||||
}' \
|
|
||||||
--output json \
|
|
||||||
"${aws_opts[@]}")
|
|
||||||
|
|
||||||
if [[ $? -ne 0 || -z "$instances" || "$instances" == "[]" ]]; then
|
|
||||||
echo "Failed to retrieve instances or no match found."
|
|
||||||
return 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Select instance using fzf
|
|
||||||
local selection
|
|
||||||
selection=$(echo "$instances" | jq -r '.[] | "\(.Name): \(.IP // "no-ip") (\(.InstanceId))"' |
|
|
||||||
fzf -1 -0 --header "Select an instance")
|
|
||||||
|
|
||||||
if [[ -z "$selection" ]]; then
|
|
||||||
echo "No valid instance selected."
|
|
||||||
return 3
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Extract IP and InstanceId from selection
|
|
||||||
local ip instance_id
|
|
||||||
ip=$(echo "$selection" | sed -E 's/.*: (.*) \(.*/\1/')
|
|
||||||
instance_id=$(echo "$selection" | sed -E 's/.*\((i-[a-z0-9]+)\).*/\1/')
|
|
||||||
|
|
||||||
if [[ "$ip" != "no-ip" ]]; then
|
|
||||||
echo "Connecting to $username@$ip via SSH..."
|
|
||||||
ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "${username}@${ip}"
|
|
||||||
else
|
|
||||||
echo "No public IP found. Falling back to AWS Session Manager..."
|
|
||||||
aws ssm start-session --target "$instance_id" "${aws_opts[@]}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,4 +13,3 @@ Host *
|
|||||||
ServerAliveInterval 60
|
ServerAliveInterval 60
|
||||||
ServerAliveCountMax 30
|
ServerAliveCountMax 30
|
||||||
VerifyHostKeyDNS ask
|
VerifyHostKeyDNS ask
|
||||||
SetEnv TERM=xterm-256color
|
|
||||||
|
|||||||
@@ -4,4 +4,6 @@ HISTSIZE=2000
|
|||||||
SAVEHIST=1000
|
SAVEHIST=1000
|
||||||
|
|
||||||
# Prompt
|
# Prompt
|
||||||
export PS1="%F{8}[%F{white}%n@%m%F{8}] (%F{white}%1~%F{8}) %F{white}%#%f "
|
setopt PROMPT_SUBST
|
||||||
|
export AWS_PROFILE_DISPLAY=''
|
||||||
|
export PS1='%F{8}[%F{white}%n@%m%F{8}] (%F{white}%1~%F{8}) %F{yellow}$AWS_PROFILE_DISPLAY%F{white} %#%f '
|
||||||
|
|||||||
Reference in New Issue
Block a user