32 Commits

Author SHA1 Message Date
Shaun Setlock
aa13febadf Correcting container registry. 2025-05-03 20:51:20 -04:00
Shaun Setlock
eeccd013dc Trying simple trigger.
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 13s
2025-05-03 20:49:12 -04:00
907c44472c Merge pull request 'Trying GitHub syntax.' (#6) from feature/update_CICD_trigger into master
Reviewed-on: https://www.gitea.setlock.net/shaun/dotfiles/pulls/6
2025-05-03 20:45:42 -04:00
Shaun Setlock
b1c5de4450 Trying GitHub syntax. 2025-05-03 20:44:50 -04:00
Shaun Setlock
b5a1cb646a Triggering only on nvim file changes. 2025-05-03 20:39:27 -04:00
Shaun Setlock
0ee97a7c72 Modified comment in Actions workflow. 2025-05-03 20:31:13 -04:00
6b7ebb1f42 Merge pull request 'Modified triggers.' (#5) from feature/update_CICD_trigger into master
Reviewed-on: https://www.gitea.setlock.net/shaun/dotfiles/pulls/5
2025-05-03 19:54:27 -04:00
Shaun Setlock
35628b774f Modified triggers. 2025-05-03 19:53:44 -04:00
Shaun Setlock
30ed4f77f6 Simplifying triggers in Actions workflow.
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m53s
2025-05-03 17:08:44 -04:00
0635cad22e feature/implement_CI_CD_dotfiles#2 (#4)
Co-authored-by: Shaun Setlock <shaun@setlock.net>
Reviewed-on: https://www.gitea.setlock.net/shaun/dotfiles/pulls/4
2025-05-03 17:01:08 -04:00
bf228bf176 Created Actions workflow for nvim container build. (#3)
Co-authored-by: Shaun Setlock <shaun@setlock.net>
Reviewed-on: https://www.gitea.setlock.net/shaun/dotfiles/pulls/3
2025-05-03 16:46:11 -04:00
Shaun Setlock
41b245a43b No longer tracking workspace.json 2025-04-24 22:47:03 -04:00
Shaun Setlock
e03d5d85c0 Ignoring workspace.json since it will come from Remotely Save. 2025-04-24 22:44:34 -04:00
Shaun Setlock
c48638a0d4 Adding Obsidian main vault settings. 2025-04-24 21:49:57 -04:00
Shaun Setlock
050866ea84 Correcting README's for softlink path. 2025-04-19 23:24:38 -04:00
Shaun Setlock
7f1b4069be Adjusted to use non-root user. 2025-03-06 19:30:56 -05:00
Shaun Setlock
93f2a0f28f Updated dev container Dockerfile and included a docker compose. 2025-03-06 16:17:38 -05:00
Shaun Setlock
f754c4ab47 Created Dockerfile for a neovim container. 2025-03-06 07:32:18 -05:00
Shaun Setlock
727c19c811 Added support for c, c++ and included yanky. 2025-03-01 18:23:00 -05:00
Shaun Setlock
8b00333443 Added gitui and startuptime plugins for nvim. 2025-02-21 18:55:44 -05:00
Shaun Setlock
cc3c3bdeac Switching to lazyvim. 2025-02-21 18:36:01 -05:00
Shaun Setlock
aa89bb7ea7 Added fish support for ssh-agent. 2025-02-02 20:21:08 -05:00
Shaun Setlock
6dfbc1b97a Updated tmux to have resize pane bindings. 2025-01-20 12:59:56 -05:00
Shaun Setlock
9d30cd5d12 Moving to kickstart, with a single init.lua file. 2025-01-02 21:39:46 -05:00
Shaun Setlock
6722fe742b No longer tracking lazyvim version lock file. 2025-01-01 21:59:01 -05:00
Shaun Setlock
fb62851c06 Ignoring lazyvim version lock file. 2025-01-01 21:55:55 -05:00
Shaun Setlock
555595cc17 Added several plugins and extras in nvim. Updated docs on how they were added. 2025-01-01 19:54:28 -05:00
Shaun Setlock
291f252dc6 Removed powerline and the distro specific stuff, just too much hassle. 2024-12-31 19:18:53 -05:00
Shaun Setlock
94145e931f Separated fish configs for each distro family and updated docs. 2024-12-31 14:25:52 -05:00
Shaun Setlock
811b50a5e5 Added documentation for fish setup, and included configs for RedHat and Debian distros. 2024-12-31 13:58:38 -05:00
24373e4888 Merge pull request 'Updated typo in title from copy/paste.' (#1) from README-title-typo into master
Reviewed-on: #1
2024-12-30 22:28:37 -05:00
fe11983a88 Updated typo in title from copy/paste. 2024-12-30 22:27:43 -05:00
40 changed files with 32337 additions and 74 deletions

View File

@@ -0,0 +1,42 @@
# .gitea/workflows/docker-build-push.yml
name: Build and Push Docker Image
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Gitea Container Registry
uses: docker/login-action@v3
with:
registry: gitea.setlock.net
username: ${{ secrets.USER }}
password: ${{ secrets.TOKEN }}
- name: Extract Tag Name (if any)
id: get_tag
run: |
echo "GIT_TAG=${GITHUB_REF##*/}" >> $GITHUB_ENV
- name: Build and Push Docker Image
uses: docker/build-push-action@v5
with:
context: ./nvim/tools
push: true
platforms: linux/amd64,linux/arm64
tags: |
https://gitea.setlock.net/shaun/dotfiles:latest
https://gitea.setlock.net/shaun/dotfiles:${{ env.GIT_TAG }}

3
.gitignore vendored
View File

@@ -1,6 +1,9 @@
# Ignore the installed tmux plugins. # Ignore the installed tmux plugins.
/tmux/plugins /tmux/plugins
# Ignore lazyvim's version lock file.
/nvim/lazy-lock.json
# Ignore the installed vim plugins. # Ignore the installed vim plugins.
/vim/.vim/bundle /vim/.vim/bundle

37
fish/README.md Normal file
View File

@@ -0,0 +1,37 @@
# Shaun's `fish` Dotfiles
## Location
### Config Directory
The configuration files need to be present at this location, `~/.config/fish`. So, we can use the following command to softlink/symlink,
```bash
ln -s <location of cloned dotfiles fish directory> ~/.config
# e.g.
# ln -s ~/dotfiles/fish ~/.config
```
## Install Powerline Font or Nerd Font
A nerd font is expected for the awesome unicode characters, and the easiest is probably powerline.
```bash
dnf install powerline
```
## Install Oh My Fish (`omf`)
This addon is expected within our configuration so we should install it.
```bash
curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install | fish
```
## Install Bob The Fish Theme (`bobthefish`)
This theme is great.
```bash
omf install bobthefish
```

View File

@@ -0,0 +1,7 @@
if test -z "$SSH_ENV"
set -xg SSH_ENV $HOME/.ssh/environment
end
if not __ssh_agent_is_started
__ssh_agent_start
end

View File

@@ -1,7 +1,17 @@
# set powerline prompt goodness set -g theme_nerd_fonts yes
set fish_function_path $fish_function_path "/usr/share/powerline/bindings/fish" set -g theme_display_git yes
#source /usr/share/powerline/bindings/fish/powerline-setup.fish set -g theme_display_git_untracked yes
#powerline-setup set -g theme_display_git_ahead_verbose yes
set -g theme_display_vagrant yes
# set mcfly to alias reverse searches set -g theme_display_hg no
#mcfly init fish | source set -g theme_display_virtualenv yes
set -g theme_display_ruby no
set -g theme_display_user yes
set -g theme_display_vi yes
set -g theme_display_vi_hide_mode default
set -g theme_title_display_process yes
set -g theme_title_display_path no
set -g theme_title_use_abbreviated_path yes
set -g theme_date_format "+%a %H:%M"
set -g theme_avoid_ambiguous_glyphs yes
set -g theme_show_exit_status yes

View File

@@ -0,0 +1,23 @@
function __ssh_agent_is_started -d "check if ssh agent is already started"
if test -n "$SSH_CONNECTION"
# This is an SSH session
ssh-add -l > /dev/null 2>&1
if test $status -eq 0 -o $status -eq 1
# An SSH agent was forwarded
return 0
end
end
if begin; test -f "$SSH_ENV"; and test -z "$SSH_AGENT_PID"; end
source $SSH_ENV > /dev/null
end
if test -z "$SSH_AGENT_PID"
return 1
end
ssh-add -l > /dev/null 2>&1
if test $status -eq 2
return 1
end
end

View File

@@ -0,0 +1,5 @@
function __ssh_agent_start -d "start a new ssh agent"
ssh-agent -c | sed 's/^echo/#echo/' > $SSH_ENV
chmod 600 $SSH_ENV
source $SSH_ENV > /dev/null
end

View File

@@ -1,15 +0,0 @@
{
"neodev": {
"library": {
"enabled": true,
"plugins": true
}
},
"neoconf": {
"plugins": {
"lua_ls": {
"enabled": true
}
}
}
}

View File

@@ -1,14 +1,21 @@
# Shaun's `nvim` Dotfiles # Shaun's `nvim` Dotfiles
## Location ## Location
The configuration files need to be present at this location, `~/.config/nvim`. So, we can use the following command to softlink/symlink, The configuration files need to be present at this location, `~/.config/nvim`. So, we can use the following command to softlink/symlink,
```bash ```bash
ln -s <location of cloned dotfiles nvim directory> ~/.config/nvim ln -s <location of cloned dotfiles nvim directory> ~/.config
# e.g. # e.g.
# ln -s ~/dotfiles/nvim ~/.config/nvim # ln -s ~/dotfiles/nvim ~/.config
``` ```
## `neovim` System Package ## `neovim` System Package
Ensure that neovim is installed on the system. For example, Ensure that neovim is installed on the system. For example,
`dnf install neovim` `dnf install neovim`
## Plugins and Extra's
Packer and Mason can help with extras and plugins.
Try `:Mason` and the select items to install with `i`.

View File

@@ -1,36 +0,0 @@
{
"LazyVim": { "branch": "main", "commit": "d0c366e4d861b848bdc710696d5311dca2c6d540" },
"blink.cmp": { "branch": "main", "commit": "5f442681df24fe705d1ee7ce5b4d435aa4b4dee4" },
"bufferline.nvim": { "branch": "main", "commit": "261a72b90d6db4ed8014f7bda976bcdc9dd7ce76" },
"catppuccin": { "branch": "main", "commit": "f67b886d65a029f12ffa298701fb8f1efd89295d" },
"conform.nvim": { "branch": "master", "commit": "9180320205d250429f0f80e073326c674e2a7149" },
"flash.nvim": { "branch": "main", "commit": "34c7be146a91fec3555c33fe89c7d643f6ef5cf1" },
"friendly-snippets": { "branch": "main", "commit": "efff286dd74c22f731cdec26a70b46e5b203c619" },
"fzf-lua": { "branch": "main", "commit": "12ac915c26ec6337ff96be0b8b2311736cca4c13" },
"gitsigns.nvim": { "branch": "main", "commit": "5f808b5e4fef30bd8aca1b803b4e555da07fc412" },
"grug-far.nvim": { "branch": "main", "commit": "c88435b825a35bfa468b47159709b3221976ecd1" },
"lazy.nvim": { "branch": "main", "commit": "7e6c863bc7563efbdd757a310d17ebc95166cef3" },
"lazydev.nvim": { "branch": "main", "commit": "8620f82ee3f59ff2187647167b6b47387a13a018" },
"lualine.nvim": { "branch": "master", "commit": "2a5bae925481f999263d6f5ed8361baef8df4f83" },
"mason-lspconfig.nvim": { "branch": "main", "commit": "c6c686781f9841d855bf1b926e10aa5e19430a38" },
"mason.nvim": { "branch": "main", "commit": "e2f7f9044ec30067bc11800a9e266664b88cda22" },
"mini.ai": { "branch": "main", "commit": "ebb04799794a7f94628153991e6334c3304961b8" },
"mini.icons": { "branch": "main", "commit": "6787321f70d674a481776b7cc2c781fb7002c644" },
"mini.pairs": { "branch": "main", "commit": "7e834c5937d95364cc1740e20d673afe2d034cdb" },
"neo-tree.nvim": { "branch": "main", "commit": "a9f8943b4c31f8460d25c71e0f463d65e9775f1c" },
"noice.nvim": { "branch": "main", "commit": "eaed6cc9c06aa2013b5255349e4f26a6b17ab70f" },
"nui.nvim": { "branch": "main", "commit": "53e907ffe5eedebdca1cd503b00aa8692068ca46" },
"nvim-lint": { "branch": "master", "commit": "1fea92f1d9908eaa5eb8bafe08b4293d7aadaa55" },
"nvim-lspconfig": { "branch": "master", "commit": "8b15a1a597a59f4f5306fad9adfe99454feab743" },
"nvim-treesitter": { "branch": "master", "commit": "4b222913486ec0a5983efa82b0649a2ab87cf1f0" },
"nvim-treesitter-textobjects": { "branch": "master", "commit": "ad8f0a472148c3e0ae9851e26a722ee4e29b1595" },
"nvim-ts-autotag": { "branch": "main", "commit": "1cca23c9da708047922d3895a71032bc0449c52d" },
"persistence.nvim": { "branch": "main", "commit": "f6aad7dde7fcf54148ccfc5f622c6d5badd0cc3d" },
"plenary.nvim": { "branch": "master", "commit": "2d9b06177a975543726ce5c73fca176cedbffe9d" },
"snacks.nvim": { "branch": "main", "commit": "98df370703b3c47a297988f3e55ce99628639590" },
"todo-comments.nvim": { "branch": "main", "commit": "ae0a2afb47cf7395dc400e5dc4e05274bf4fb9e0" },
"tokyonight.nvim": { "branch": "main", "commit": "45d22cf0e1b93476d3b6d362d720412b3d34465c" },
"trouble.nvim": { "branch": "main", "commit": "46cf952fc115f4c2b98d4e208ed1e2dce08c9bf6" },
"ts-comments.nvim": { "branch": "main", "commit": "872dcfa0418f4a33b7437fb4d9f4e89f2f000d74" },
"which-key.nvim": { "branch": "main", "commit": "8ab96b38a2530eacba5be717f52e04601eb59326" }
}

View File

@@ -1,9 +1,24 @@
{ {
"extras": [ "extras": [
"lazyvim.plugins.extras.coding.yanky",
"lazyvim.plugins.extras.formatting.black",
"lazyvim.plugins.extras.lang.ansible",
"lazyvim.plugins.extras.lang.clangd",
"lazyvim.plugins.extras.lang.cmake",
"lazyvim.plugins.extras.lang.docker",
"lazyvim.plugins.extras.lang.git",
"lazyvim.plugins.extras.lang.json",
"lazyvim.plugins.extras.lang.markdown",
"lazyvim.plugins.extras.lang.python",
"lazyvim.plugins.extras.lang.sql",
"lazyvim.plugins.extras.lang.yaml",
"lazyvim.plugins.extras.util.dot",
"lazyvim.plugins.extras.util.gitui",
"lazyvim.plugins.extras.util.startuptime"
], ],
"install_version": 8,
"news": { "news": {
"NEWS.md": "10960" "NEWS.md": "10960"
}, },
"version": 7 "version": 8
} }

View File

@@ -0,0 +1,58 @@
return {
{
"catppuccin/nvim",
lazy = true,
name = "catppuccin",
opts = {
integrations = {
aerial = true,
alpha = true,
cmp = true,
dashboard = true,
flash = true,
fzf = true,
grug_far = true,
gitsigns = true,
headlines = true,
illuminate = true,
indent_blankline = { enabled = true },
leap = true,
lsp_trouble = true,
mason = true,
markdown = true,
mini = true,
native_lsp = {
enabled = true,
underlines = {
errors = { "undercurl" },
hints = { "undercurl" },
warnings = { "undercurl" },
information = { "undercurl" },
},
},
navic = { enabled = true, custom_bg = "lualine" },
neotest = true,
neotree = true,
noice = true,
notify = true,
semantic_tokens = true,
snacks = true,
telescope = true,
treesitter = true,
treesitter_context = true,
which_key = true,
},
},
specs = {
{
"akinsho/bufferline.nvim",
optional = true,
opts = function(_, opts)
if (vim.g.colors_name or ""):find("catppuccin") then
opts.highlights = require("catppuccin.groups.integrations.bufferline").get()
end
end,
},
},
},
}

73
nvim/tools/Dockerfile Normal file
View File

@@ -0,0 +1,73 @@
# Docker file for base Neovim image.
# Debian image as base (unstable for newest software).
FROM debian:unstable
RUN apt-get update && apt-get install -y locales
# Set image locale.
ENV LANG=en_US.UTF-8
ENV LANGUAGE=en_US:en
ENV LC_ALL=en_US.UTF-8
ENV TZ=America/New_York
ENV TERM=xterm-256color
# Create a non-root user with UID 1000
RUN useradd -m -u 1000 -s /usr/bin/fish shaun
# Install required software
RUN apt-get update && apt-get -y install \
curl fzf ripgrep tree git xclip python3 python3-pip python3-venv nodejs npm \
tzdata ninja-build gettext libtool libtool-bin autoconf automake cmake g++ \
pkg-config zip unzip fish tmux
# Cooperate Neovim with Python 3.
RUN python3 -m pip install --break-system-packages --root-user-action ignore pynvim
# Cooperate NodeJS with Neovim.
RUN npm i -g neovim
# Install Neovim from source.
RUN mkdir -p /tmp/neovim-src && \
git clone --depth 1 --branch stable https://github.com/neovim/neovim /tmp/neovim-src && \
cd /tmp/neovim-src && make -j$(nproc) && make install && \
rm -rf /tmp/neovim-src
# Clone configuration files.
USER shaun
WORKDIR /home/shaun
RUN git clone https://gitea.setlock.net/shaun/dotfiles.git /home/shaun/dotfiles
# Create directories.
RUN mkdir -p /home/shaun/.config /home/shaun/.ssh
# Softlink configuration files.
RUN ln -s /home/shaun/dotfiles/nvim /home/shaun/.config
RUN ln -s /home/shaun/dotfiles/fish /home/shaun/.config
RUN ln -s /home/shaun/dotfiles/tmux /home/shaun/.config
# Install tmux plugin manager.
RUN git clone https://github.com/tmux-plugins/tpm /home/shaun/.config/tmux/plugins/tpm && \
/home/shaun/.config/tmux/plugins/tpm/scripts/install_plugins.sh
# Get oh-my-fish and bob-the-fish installed.
RUN curl https://raw.githubusercontent.com/oh-my-fish/oh-my-fish/master/bin/install > install
RUN fish install --noninteractive
RUN fish -c "omf install bobthefish"
# Install Neovim plugins
RUN nvim --headless "+Lazy! sync" +qa
# Set default shell for shaun
USER root
RUN usermod --shell /usr/bin/fish shaun
# Set workspace directory
RUN mkdir -p /workspace && chown shaun:shaun /workspace
WORKDIR /workspace
# Switch to non-root user
USER shaun
# Avoid container exit.
CMD ["tail", "-f", "/dev/null"]

View File

@@ -0,0 +1,9 @@
version: "3"
services:
nv:
container_name: nv
image: shaun/neovim:latest
user: "1000:1000"
restart: unless-stopped
volumes:
- ~/code:/root/workspace

1
obsidian/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
workspace.json

5
obsidian/app.json Normal file
View File

@@ -0,0 +1,5 @@
{
"alwaysUpdateLinks": true,
"vimMode": true,
"showLineNumber": true
}

4
obsidian/appearance.json Normal file
View File

@@ -0,0 +1,4 @@
{
"cssTheme": "Catppuccin",
"interfaceFontFamily": "Ubuntu Nerd Font"
}

View File

@@ -0,0 +1,6 @@
[
"remotely-save",
"calendar",
"code-styler",
"file-explorer-note-count"
]

View File

@@ -0,0 +1,31 @@
{
"file-explorer": true,
"global-search": true,
"switcher": true,
"graph": true,
"backlink": true,
"canvas": true,
"outgoing-link": true,
"tag-pane": true,
"properties": false,
"page-preview": true,
"daily-notes": true,
"templates": true,
"note-composer": true,
"command-palette": true,
"slash-command": false,
"editor-status": true,
"bookmarks": true,
"markdown-importer": false,
"zk-prefixer": false,
"random-note": false,
"outline": true,
"word-count": true,
"slides": false,
"audio-recorder": false,
"workspaces": false,
"file-recovery": true,
"publish": false,
"sync": false,
"webviewer": false
}

45
obsidian/hotkeys.json Normal file
View File

@@ -0,0 +1,45 @@
{
"editor:swap-line-down": [
{
"modifiers": [
"Alt"
],
"key": "ArrowDown"
}
],
"editor:swap-line-up": [
{
"modifiers": [
"Alt"
],
"key": "ArrowUp"
}
],
"editor:add-cursor-above": [
{
"modifiers": [
"Alt",
"Shift"
],
"key": "ArrowUp"
}
],
"editor:add-cursor-below": [
{
"modifiers": [
"Alt",
"Shift"
],
"key": "ArrowDown"
}
],
"remotely-save:start-sync": [
{
"modifiers": [
"Mod",
"Shift"
],
"key": "S"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"shouldConfirmBeforeCreate": true,
"weekStart": "locale",
"wordsPerDot": 250,
"showWeeklyNote": false,
"weeklyNoteFormat": "",
"weeklyNoteTemplate": "",
"weeklyNoteFolder": "",
"localeOverride": "system-default"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
{
"id": "calendar",
"name": "Calendar",
"description": "Calendar view of your daily notes",
"version": "1.5.10",
"author": "Liam Cain",
"authorUrl": "https://github.com/liamcain/",
"isDesktopOnly": false,
"minAppVersion": "0.9.11"
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
{
"id": "code-styler",
"name": "Code Styler",
"version": "1.1.7",
"minAppVersion": "0.15.0",
"description": "Style and customize codeblocks and inline code in both editing mode and reading mode.",
"author": "Mayuran Visakan",
"authorUrl": "https://github.com/mayurankv",
"fundingUrl": "https://www.buymeacoffee.com/mayurankv2",
"isDesktopOnly": false
}

View File

@@ -0,0 +1 @@
{}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,970 @@
'use strict';
var obsidian = require('obsidian');
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
// 'path' module extracted from Node.js v8.11.1 (only the posix part)
function assertPath(path) {
if (typeof path !== 'string') {
throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
}
}
// Resolves . and .. elements in a path with directory names
function normalizeStringPosix(path, allowAboveRoot) {
var res = '';
var lastSegmentLength = 0;
var lastSlash = -1;
var dots = 0;
var code;
for (var i = 0; i <= path.length; ++i) {
if (i < path.length)
code = path.charCodeAt(i);
else if (code === 47 /*/*/)
break;
else
code = 47 /*/*/;
if (code === 47 /*/*/) {
if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
if (res.length > 2) {
var lastSlashIndex = res.lastIndexOf('/');
if (lastSlashIndex !== res.length - 1) {
if (lastSlashIndex === -1) {
res = '';
lastSegmentLength = 0;
} else {
res = res.slice(0, lastSlashIndex);
lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
}
lastSlash = i;
dots = 0;
continue;
}
} else if (res.length === 2 || res.length === 1) {
res = '';
lastSegmentLength = 0;
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
if (res.length > 0)
res += '/..';
else
res = '..';
lastSegmentLength = 2;
}
} else {
if (res.length > 0)
res += '/' + path.slice(lastSlash + 1, i);
else
res = path.slice(lastSlash + 1, i);
lastSegmentLength = i - lastSlash - 1;
}
lastSlash = i;
dots = 0;
} else if (code === 46 /*.*/ && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
function _format(sep, pathObject) {
var dir = pathObject.dir || pathObject.root;
var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
if (!dir) {
return base;
}
if (dir === pathObject.root) {
return dir + base;
}
return dir + sep + base;
}
var posix = {
// path.resolve([from ...], to)
resolve: function resolve() {
var resolvedPath = '';
var resolvedAbsolute = false;
var cwd;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path;
if (i >= 0)
path = arguments[i];
else {
if (cwd === undefined)
cwd = process.cwd();
path = cwd;
}
assertPath(path);
// Skip empty entries
if (path.length === 0) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
if (resolvedAbsolute) {
if (resolvedPath.length > 0)
return '/' + resolvedPath;
else
return '/';
} else if (resolvedPath.length > 0) {
return resolvedPath;
} else {
return '.';
}
},
normalize: function normalize(path) {
assertPath(path);
if (path.length === 0) return '.';
var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;
// Normalize the path
path = normalizeStringPosix(path, !isAbsolute);
if (path.length === 0 && !isAbsolute) path = '.';
if (path.length > 0 && trailingSeparator) path += '/';
if (isAbsolute) return '/' + path;
return path;
},
isAbsolute: function isAbsolute(path) {
assertPath(path);
return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
},
join: function join() {
if (arguments.length === 0)
return '.';
var joined;
for (var i = 0; i < arguments.length; ++i) {
var arg = arguments[i];
assertPath(arg);
if (arg.length > 0) {
if (joined === undefined)
joined = arg;
else
joined += '/' + arg;
}
}
if (joined === undefined)
return '.';
return posix.normalize(joined);
},
relative: function relative(from, to) {
assertPath(from);
assertPath(to);
if (from === to) return '';
from = posix.resolve(from);
to = posix.resolve(to);
if (from === to) return '';
// Trim any leading backslashes
var fromStart = 1;
for (; fromStart < from.length; ++fromStart) {
if (from.charCodeAt(fromStart) !== 47 /*/*/)
break;
}
var fromEnd = from.length;
var fromLen = fromEnd - fromStart;
// Trim any leading backslashes
var toStart = 1;
for (; toStart < to.length; ++toStart) {
if (to.charCodeAt(toStart) !== 47 /*/*/)
break;
}
var toEnd = to.length;
var toLen = toEnd - toStart;
// Compare paths to find the longest common path from root
var length = fromLen < toLen ? fromLen : toLen;
var lastCommonSep = -1;
var i = 0;
for (; i <= length; ++i) {
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === 47 /*/*/) {
// We get here if `from` is the exact base path for `to`.
// For example: from='/foo/bar'; to='/foo/bar/baz'
return to.slice(toStart + i + 1);
} else if (i === 0) {
// We get here if `from` is the root
// For example: from='/'; to='/foo'
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
// We get here if `to` is the exact base path for `from`.
// For example: from='/foo/bar/baz'; to='/foo/bar'
lastCommonSep = i;
} else if (i === 0) {
// We get here if `to` is the root.
// For example: from='/foo'; to='/'
lastCommonSep = 0;
}
}
break;
}
var fromCode = from.charCodeAt(fromStart + i);
var toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (fromCode === 47 /*/*/)
lastCommonSep = i;
}
var out = '';
// Generate the relative path based on the path difference between `to`
// and `from`
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
if (out.length === 0)
out += '..';
else
out += '/..';
}
}
// Lastly, append the rest of the destination (`to`) path that comes after
// the common path parts
if (out.length > 0)
return out + to.slice(toStart + lastCommonSep);
else {
toStart += lastCommonSep;
if (to.charCodeAt(toStart) === 47 /*/*/)
++toStart;
return to.slice(toStart);
}
},
_makeLong: function _makeLong(path) {
return path;
},
dirname: function dirname(path) {
assertPath(path);
if (path.length === 0) return '.';
var code = path.charCodeAt(0);
var hasRoot = code === 47 /*/*/;
var end = -1;
var matchedSlash = true;
for (var i = path.length - 1; i >= 1; --i) {
code = path.charCodeAt(i);
if (code === 47 /*/*/) {
if (!matchedSlash) {
end = i;
break;
}
} else {
// We saw the first non-path separator
matchedSlash = false;
}
}
if (end === -1) return hasRoot ? '/' : '.';
if (hasRoot && end === 1) return '//';
return path.slice(0, end);
},
basename: function basename(path, ext) {
if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
assertPath(path);
var start = 0;
var end = -1;
var matchedSlash = true;
var i;
if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
if (ext.length === path.length && ext === path) return '';
var extIdx = ext.length - 1;
var firstNonSlashEnd = -1;
for (i = path.length - 1; i >= 0; --i) {
var code = path.charCodeAt(i);
if (code === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
start = i + 1;
break;
}
} else {
if (firstNonSlashEnd === -1) {
// We saw the first non-path separator, remember this index in case
// we need it if the extension ends up not matching
matchedSlash = false;
firstNonSlashEnd = i + 1;
}
if (extIdx >= 0) {
// Try to match the explicit extension
if (code === ext.charCodeAt(extIdx)) {
if (--extIdx === -1) {
// We matched the extension, so mark this as the end of our path
// component
end = i;
}
} else {
// Extension does not match, so our result is the entire path
// component
extIdx = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
return path.slice(start, end);
} else {
for (i = path.length - 1; i >= 0; --i) {
if (path.charCodeAt(i) === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
start = i + 1;
break;
}
} else if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// path component
matchedSlash = false;
end = i + 1;
}
}
if (end === -1) return '';
return path.slice(start, end);
}
},
extname: function extname(path) {
assertPath(path);
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0;
for (var i = path.length - 1; i >= 0; --i) {
var code = path.charCodeAt(i);
if (code === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false;
end = i + 1;
}
if (code === 46 /*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = -1;
}
}
if (startDot === -1 || end === -1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return '';
}
return path.slice(startDot, end);
},
format: function format(pathObject) {
if (pathObject === null || typeof pathObject !== 'object') {
throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
}
return _format('/', pathObject);
},
parse: function parse(path) {
assertPath(path);
var ret = { root: '', dir: '', base: '', ext: '', name: '' };
if (path.length === 0) return ret;
var code = path.charCodeAt(0);
var isAbsolute = code === 47 /*/*/;
var start;
if (isAbsolute) {
ret.root = '/';
start = 1;
} else {
start = 0;
}
var startDot = -1;
var startPart = 0;
var end = -1;
var matchedSlash = true;
var i = path.length - 1;
// Track the state of characters (if any) we see before our first dot and
// after any path separator we find
var preDotState = 0;
// Get non-dir info
for (; i >= start; --i) {
code = path.charCodeAt(i);
if (code === 47 /*/*/) {
// If we reached a path separator that was not part of a set of path
// separators at the end of the string, stop now
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
// We saw the first non-path separator, mark this as the end of our
// extension
matchedSlash = false;
end = i + 1;
}
if (code === 46 /*.*/) {
// If this is our first dot, mark it as the start of our extension
if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
} else if (startDot !== -1) {
// We saw a non-dot and non-path separator before our dot, so we should
// have a good chance at having a non-empty extension
preDotState = -1;
}
}
if (startDot === -1 || end === -1 ||
// We saw a non-dot character immediately before the dot
preDotState === 0 ||
// The (right-most) trimmed path component is exactly '..'
preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
}
} else {
if (startPart === 0 && isAbsolute) {
ret.name = path.slice(1, startDot);
ret.base = path.slice(1, end);
} else {
ret.name = path.slice(startPart, startDot);
ret.base = path.slice(startPart, end);
}
ret.ext = path.slice(startDot, end);
}
if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';
return ret;
},
sep: '/',
delimiter: ':',
win32: null,
posix: null
};
posix.posix = posix;
var pathBrowserify = posix;
const withSubfolderClass = 'oz-with-subfolder';
const showAllNumbersClass = 'oz-show-all-num';
const isFolder = (item) => item.file instanceof obsidian.TFolder;
const iterateItems = (items, callback) => {
for (const key in items) {
if (!Object.prototype.hasOwnProperty.call(items, key))
continue;
callback(items[key]);
}
};
const getParentPath = (src) => {
if (src === '/')
return null;
const path = pathBrowserify.dirname(src);
if (path === '.')
return '/';
else
return path;
};
const equals = (arr1, arr2) => {
// if the other array is a falsy value, return
if (!Array.isArray(arr1) || !Array.isArray(arr2))
return false;
// compare lengths - can save a lot of time
if (arr1.length != arr2.length)
return false;
return arr1.every((v, i) => v === arr2[i]);
};
const isParent = (parent, child) => {
if (child === parent)
return false;
if (parent === '/')
parent = '';
if (child === '/')
child = '';
const parentTokens = parent.split('/').filter((i) => i.length);
return parentTokens.every((t, i) => child.split('/')[i] === t);
};
// Helper to play with the File Explorer (if exists)
const doWithFileExplorer = (plugin, callback) => {
let leaves;
let count = 0;
const tryGetView = () => {
leaves = plugin.app.workspace.getLeavesOfType('file-explorer');
if (leaves.length === 0) {
if (count++ > 5)
console.error('failed to get file-explorer');
else {
console.log('file-explorer not found, retrying...');
setTimeout(tryGetView, 500);
}
}
else {
if (leaves.length > 1)
console.warn('more then one file-explorer');
callback(leaves[0].view);
}
};
tryGetView();
};
function around(obj, factories) {
const removers = Object.keys(factories).map(key => around1(obj, key, factories[key]));
return removers.length === 1 ? removers[0] : function () { removers.forEach(r => r()); };
}
function around1(obj, method, createWrapper) {
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
let current = createWrapper(original);
// Let our wrapper inherit static props from the wrapping method,
// and the wrapping method, props from the original method
if (original)
Object.setPrototypeOf(current, original);
Object.setPrototypeOf(wrapper, current);
obj[method] = wrapper;
// Return a callback to allow safe removal
return remove;
function wrapper(...args) {
// If we have been deactivated and are no longer wrapped, remove ourselves
if (current === original && obj[method] === wrapper)
remove();
return current.apply(this, args);
}
function remove() {
// If no other patches, just do a direct removal
if (obj[method] === wrapper) {
if (hadOwn)
obj[method] = original;
else
delete obj[method];
}
if (current === original)
return;
// Else pass future calls through, and remove wrapper from the prototype chain
current = original;
Object.setPrototypeOf(wrapper, original || Function);
}
}
const countFolderChildren = (folder, filter) => {
let count = 0;
for (const af of folder.children) {
if (filter(af))
count++;
if (af instanceof obsidian.TFolder)
count += countFolderChildren(af, filter);
}
return count;
};
/** filter out all path that is the parent of existing path */
const filterParent = (pathList) => {
const list = Array.from(pathList);
list.sort();
for (let i = 0; i < list.length; i++) {
if (i < list.length - 1 && (list[i] === list[i + 1] || isParent(list[i], list[i + 1]))) {
list.shift();
i--;
}
}
return new Set(list);
};
/** get all parents and add to set if not exist */
const getAllParents = (path, set) => {
let parent = getParentPath(path);
while (parent && !set.has(parent)) {
set.add(parent);
parent = getParentPath(parent);
}
};
/**
* Update folder count of target's parent
*/
const updateCount = (targetList, plugin) => {
const set = filterParent(targetList);
for (const path of targetList) {
getAllParents(path, set);
}
// set count of path
const { fileExplorer, fileFilter } = plugin;
if (!fileExplorer) {
console.error('fileExplorer missing');
return;
}
for (const path of set) {
// check if path available
if (!fileExplorer.fileItems[path])
continue;
setCount(fileExplorer.fileItems[path], fileFilter);
}
// Update root separately
if (plugin.rootFolderEl && plugin.settings.addRootFolder) {
setupRootCount(plugin);
}
// empty waitingList
targetList.length = 0;
};
const setupRootCount = (plugin) => {
if (plugin.rootFolderEl) {
let rootFolderElChildren = plugin.rootFolderEl.children;
if (rootFolderElChildren && rootFolderElChildren.length > 0) {
let totalCount = countFolderChildren(plugin.app.vault.getAbstractFileByPath('/'), plugin.fileFilter);
rootFolderElChildren[0].setAttr('data-count', totalCount.toString());
}
}
};
const setupCount = (plugin, revert = false) => {
if (!plugin.fileExplorer)
throw new Error('fileExplorer not found');
// For each setup, first setup the root folder
plugin.setupRootFolder();
setupRootCount(plugin);
// Iterate other items and include new counts
iterateItems(plugin.fileExplorer.fileItems, (item) => {
if (!isFolder(item))
return;
if (revert)
removeCount(item);
else
setCount(item, plugin.fileFilter);
});
};
const setCount = (item, filter) => {
// if (item.file.isRoot()) return;
const count = countFolderChildren(item.file, filter);
item.selfEl.dataset['count'] = count.toString();
item.selfEl.toggleClass(withSubfolderClass, Array.isArray(item.file.children) && item.file.children.some((af) => af instanceof obsidian.TFolder));
};
const removeCount = (item) => {
if (item.selfEl.dataset['count'])
delete item.selfEl.dataset['count'];
item.selfEl.removeClass(withSubfolderClass);
};
class VaultHandler {
get app() {
return this.plugin.app;
}
get vault() {
return this.plugin.app.vault;
}
constructor(plugin) {
this.waitingList = [];
this.update = obsidian.debounce(() => updateCount(this.waitingList, this.plugin), 500, true);
this.handler = (...args) => {
var _a;
for (const arg of args) {
const path = arg instanceof obsidian.TAbstractFile ? arg.path : arg;
this.waitingList.push((_a = getParentPath(path)) !== null && _a !== void 0 ? _a : '/');
}
this.update();
};
this.registerVaultEvent = () => {
this.plugin.registerEvent(this.vault.on('create', this.handler));
this.plugin.registerEvent(this.vault.on('rename', this.handler));
this.plugin.registerEvent(this.vault.on('delete', this.handler));
};
this.plugin = plugin;
}
}
const DEFAULT_SETTINGS = {
showAllNumbers: false,
filterList: ['md'],
blacklist: false,
addRootFolder: false,
};
class FENoteCountSettingTab extends obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
get showOnlyNoteValue() {
const { settings } = this.plugin;
return settings.blacklist === DEFAULT_SETTINGS.blacklist && equals(settings.filterList, DEFAULT_SETTINGS.filterList);
}
set showOnlyNoteValue(value) {
const { blacklist, filterList } = DEFAULT_SETTINGS;
this.plugin.settings.blacklist = blacklist;
if (value) {
// do deep copy
this.plugin.settings.filterList = Array.from(filterList);
}
else {
this.plugin.settings.filterList.length = 0;
}
}
display() {
let { containerEl } = this;
containerEl.empty();
containerEl.createEl('h2', {
text: 'File Explorer Note Count Settings',
});
new obsidian.Setting(containerEl)
.setName('Show All Numbers')
.setDesc('Turn on this option if you want to see the number of notes even after you expand the collapsed folders')
.addToggle((toggle) => toggle.setValue(this.plugin.settings.showAllNumbers).onChange((value) => {
document.body.toggleClass('oz-show-all-num', value);
this.plugin.settings.showAllNumbers = value;
this.plugin.saveSettings();
}));
new obsidian.Setting(containerEl)
.setName('Add Root Folder')
.setDesc('By default, there is no root folder provided by Obsidian. It is moved to drop-down menu to switch between vaults. ' +
'Enable this option if you want to see root folder and its count in the file explorer')
.addToggle((toggle) => toggle.setValue(this.plugin.settings.addRootFolder).onChange((value) => {
this.plugin.settings.addRootFolder = value;
this.plugin.saveSettings();
this.plugin.reloadCount();
}));
this.filterOpt();
}
filterOpt() {
new obsidian.Setting(this.containerEl)
.setName('Show Only Markdown Notes')
.setDesc('Turn off this option to choose file that should be counted')
.addToggle((toggle) => toggle.setValue(this.showOnlyNoteValue).onChange((value) => {
this.showOnlyNoteValue = value;
this.plugin.reloadCount();
this.plugin.saveSettings();
this.display();
}));
if (!this.showOnlyNoteValue) {
new obsidian.Setting(this.containerEl)
.setName('Filter List')
.setDesc(createFragment((descEl) => {
descEl.appendText('Extension list to include/exclude file during counting');
descEl.appendChild(document.createElement('br'));
descEl.appendText('Separated by comma');
}))
.addTextArea((text) => {
const onChange = (value) => __awaiter(this, void 0, void 0, function* () {
const list = value.split(',').map((v) => v.trim());
this.plugin.settings.filterList = list;
this.plugin.reloadCount();
yield this.plugin.saveSettings();
});
text.setPlaceholder('Leave it empty to count all types of files');
text.setValue(this.plugin.settings.filterList.join(', ')).onChange(obsidian.debounce(onChange, 500, true));
text.inputEl.rows = 2;
text.inputEl.cols = 25;
});
new obsidian.Setting(this.containerEl)
.setName('Enable Blacklist')
.setDesc('Turn on this option to use Filter List to exclude files')
.addToggle((toggle) => toggle.setValue(this.plugin.settings.blacklist).onChange((value) => {
this.plugin.settings.blacklist = value;
this.plugin.reloadCount();
this.plugin.saveSettings();
}));
}
}
}
class FileExplorerNoteCount extends obsidian.Plugin {
constructor() {
super(...arguments);
this.settings = DEFAULT_SETTINGS;
this.vaultHandler = new VaultHandler(this);
this.rootFolderEl = null;
this.explorerNavHeaderSelector = '.workspace-leaf-content[data-type="file-explorer"] .nav-header';
this.rootFolderClassName = 'oz-explorer-root-folder';
this.initialize = (revert = false) => {
let plugin = this;
// First Check if the root folder exists
let explorerHeaderEl = document.querySelector(`${this.explorerNavHeaderSelector} .${this.rootFolderClassName}`);
if (explorerHeaderEl)
this.rootFolderEl = explorerHeaderEl;
const getViewHandler = (revert) => (view) => {
this.fileExplorer = view;
setupCount(this, revert);
this.setupRootFolder(revert);
if (!revert) {
this.registerEvent(this.app.workspace.on('css-change', this.setupRootFolder));
this.vaultHandler.registerVaultEvent();
if (this.settings.showAllNumbers)
document.body.addClass('oz-show-all-num');
}
else {
for (const el of document.getElementsByClassName(withSubfolderClass)) {
el.removeClass(withSubfolderClass);
}
document.body.removeClass(showAllNumbersClass);
}
if (!revert) {
// when file explorer is closed (workspace changed)
// try to update fehanlder with new file explorer instance
this.register(around(view, {
onClose: (next) => function () {
setTimeout(() => doWithFileExplorer(plugin, getViewHandler(false)), 1e3);
return next.apply(this);
},
}));
}
};
doWithFileExplorer(plugin, getViewHandler(revert));
};
this.setupRootFolder = (revert = false) => {
var _a, _b, _c;
if (!this.fileExplorer) {
console.error('file-explorer not found');
return;
}
if (this.rootFolderEl && !this.settings.addRootFolder) {
this.rootFolderEl.remove();
this.rootFolderEl = null;
}
// Check if root is provided by Obsidian (it shouldn't be in the new releases)
const root = (_c = (_b = (_a = this.fileExplorer) === null || _a === void 0 ? void 0 : _a.fileItems) === null || _b === void 0 ? void 0 : _b['/']) !== null && _c !== void 0 ? _c : null;
if (!root) {
// Get the Nav Header
let explorerHeaderEl = document.querySelector(this.explorerNavHeaderSelector);
if (!explorerHeaderEl)
return;
if (!this.rootFolderEl && this.settings.addRootFolder) {
this.rootFolderEl = explorerHeaderEl.createEl('div', {
cls: ['tree-item', 'nav-folder', this.rootFolderClassName],
});
this.rootFolderEl.innerHTML = `
<div class="oz-explorer-root-nav-folder-title" data-path="/">
<div class="tree-item-inner nav-folder-title-content">${this.app.vault.getName()}</div>
</div>
`;
}
}
};
}
onload() {
return __awaiter(this, void 0, void 0, function* () {
console.log('loading FileExplorerNoteCount');
this.addSettingTab(new FENoteCountSettingTab(this.app, this));
yield this.loadSettings();
this.app.workspace.onLayoutReady(this.initialize);
});
}
onunload() {
console.log('unloading FileExplorerNoteCount');
this.initialize(true);
}
loadSettings() {
return __awaiter(this, void 0, void 0, function* () {
this.settings = Object.assign(Object.assign({}, this.settings), (yield this.loadData()));
});
}
saveSettings() {
return __awaiter(this, void 0, void 0, function* () {
yield this.saveData(this.settings);
});
}
reloadCount() {
setupCount(this);
}
get fileFilter() {
let list = this.settings.filterList;
return (af) => {
if (af instanceof obsidian.TFile) {
const { extension: target } = af;
// if list is empty, filter nothing
if (list.length === 0)
return true;
else if (this.settings.blacklist)
return !list.includes(target);
else
return list.includes(target);
}
else
return false;
};
}
}
module.exports = FileExplorerNoteCount;
/* nosourcemap */

View File

@@ -0,0 +1,10 @@
{
"id": "file-explorer-note-count",
"name": "File Explorer Note Count",
"version": "1.2.3",
"minAppVersion": "1.2.0",
"description": "The plugin helps you to see the number of notes under each folder within the file explorer.",
"author": "Ozan Tellioglu",
"authorUrl": "https://www.ozan.pl",
"isDesktopOnly": false
}

View File

@@ -0,0 +1,34 @@
.nav-folder-title[data-count]::after {
content: attr(data-count);
display: inline-block;
position: relative;
font-size: calc(100% * 0.8);
margin-right: 4px;
/* border-radius: 3px; */
padding: 2px 0;
/* background-color: var(--background-secondary-alt); */
transition: opacity 100ms ease-in-out;
}
.oz-explorer-root-nav-folder-title {
display: flex;
}
.oz-explorer-root-nav-folder-title[data-count]::after {
content: attr(data-count);
margin-right: 4px;
font-size: calc(100% * 0.8);
display: inline-block;
}
body:not(.oz-show-all-num) .nav-folder:not(.is-collapsed) > .nav-folder-title.oz-with-subfolder[data-count]:not([data-path='/'])::after {
opacity: 0;
}
.nav-folder-title-content {
flex-grow: 1;
}
.oz-explorer-root-folder {
margin-top: 15px;
}

View File

@@ -0,0 +1 @@
data.json

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,11 @@
{
"id": "remotely-save",
"name": "Remotely Save",
"version": "0.5.25",
"minAppVersion": "0.13.21",
"description": "Yet another unofficial plugin allowing users to synchronize notes between local device and the cloud service.",
"author": "fyears",
"authorUrl": "https://github.com/fyears",
"isDesktopOnly": false,
"fundingUrl": "https://remotelysave.com"
}

View File

@@ -0,0 +1,244 @@
/* set the styles */
.password-second-confirm {
font-weight: bold;
}
.password-disclaimer {
font-weight: bold;
}
.encryptionmethod-second-confirm {
font-weight: bold;
}
.settings-auth-related {
border-top: 1px solid var(--background-modifier-border);
padding-top: 18px;
}
.settings-percentage-custom-hide {
display: none;
}
.settings-encryption-method-hide {
display: none;
}
.s3-disclaimer {
font-weight: bold;
}
.s3-hide {
display: none;
}
.dropbox-disclaimer {
font-weight: bold;
}
.dropbox-hide {
display: none;
}
.dropbox-auth-button-hide {
display: none;
}
.dropbox-revoke-auth-button-hide {
display: none;
}
.onedrive-disclaimer {
font-weight: bold;
}
.onedrive-hide {
display: none;
}
.onedrive-auth-button-hide {
display: none;
}
.onedrive-revoke-auth-button-hide {
display: none;
}
.onedrivefull-allow-to-use-hide {
display: none;
}
.onedrivefull-disclaimer {
font-weight: bold;
}
.onedrivefull-hide {
display: none;
}
.onedrivefull-auth-button-hide {
display: none;
}
.onedrivefull-revoke-auth-button-hide {
display: none;
}
.webdav-disclaimer {
font-weight: bold;
}
.webdav-hide {
display: none;
}
.webdav-customheaders-textarea {
font-family: monospace;
}
.webdis-disclaimer {
font-weight: bold;
}
.webdis-hide {
display: none;
}
.googledrive-disclaimer {
font-weight: bold;
}
.googledrive-hide {
display: none;
}
.googledrive-allow-to-use-hide {
display: none;
}
.googledrive-auth-button-hide {
display: none;
}
.googledrive-revoke-auth-button-hide {
display: none;
}
.box-disclaimer {
font-weight: bold;
}
.box-hide {
display: none;
}
.box-allow-to-use-hide {
display: none;
}
.box-auth-button-hide {
display: none;
}
.box-revoke-auth-button-hide {
display: none;
}
.pcloud-disclaimer {
font-weight: bold;
}
.pcloud-hide {
display: none;
}
.pcloud-allow-to-use-hide {
display: none;
}
.pcloud-auth-button-hide {
display: none;
}
.pcloud-revoke-auth-button-hide {
display: none;
}
.yandexdisk-disclaimer {
font-weight: bold;
}
.yandexdisk-hide {
display: none;
}
.yandexdisk-allow-to-use-hide {
display: none;
}
.yandexdisk-auth-button-hide {
display: none;
}
.yandexdisk-revoke-auth-button-hide {
display: none;
}
.koofr-disclaimer {
font-weight: bold;
}
.koofr-hide {
display: none;
}
.koofr-allow-to-use-hide {
display: none;
}
.koofr-auth-button-hide {
display: none;
}
.koofr-revoke-auth-button-hide {
display: none;
}
.azureblobstorage-disclaimer {
font-weight: bold;
}
.azureblobstorage-hide {
display: none;
}
.azureblobstorage-allow-to-use-hide {
display: none;
}
.qrcode-img {
width: 350px;
height: 350px;
}
.ignorepaths-textarea {
font-family: monospace;
}
.onlyallowpaths-textarea {
font-family: monospace;
}
.logtohttpserver-warning {
color: red;
font-weight: bolder;
}
.setting-need-wrapping .setting-item-control {
/* flex-wrap: wrap; */
display: grid;
}
.pro-disclaimer {
font-weight: bold;
}
.pro-hide {
display: none;
}
.pro-auth-button-hide {
display: none;
}
.pro-revoke-auth-button-hide {
display: none;
}

View File

@@ -0,0 +1,7 @@
{
"name": "Catppuccin",
"version": "0.4.42",
"minAppVersion": "1.0.0",
"author": "Marshall Beckrich",
"authorUrl": "https://github.com/catppuccin/obsidian"
}

File diff suppressed because one or more lines are too long

4
obsidian/workspaces.json Normal file
View File

@@ -0,0 +1,4 @@
{
"workspaces": {},
"active": ""
}

View File

@@ -1,20 +1,24 @@
# Shaun's `tmux` Dotfiles # Shaun's `tmux` Dotfiles
## Location ## Location
The configuration files need to be present at this location, `~/.config/tmux`. So, we can use the following command to softlink/symlink, The configuration files need to be present at this location, `~/.config/tmux`. So, we can use the following command to softlink/symlink,
```bash ```bash
ln -s <location of cloned dotfiles tmux directory> ~/.config/tmux ln -s <location of cloned dotfiles tmux directory> ~/.config
# e.g. # e.g.
# ln -s ~/dotfiles/tmux ~/.config/tmux # ln -s ~/dotfiles/tmux ~/.config
``` ```
## Install Plugin Manager (`tpm`) ## Install Plugin Manager (`tpm`)
We will use `tpm` as our plugin manager, but it cannot install itself. So we have to clone it into the proper place. We will use `tpm` as our plugin manager, but it cannot install itself. So we have to clone it into the proper place.
`git clone https://github.com/tmux-plugins/tpm ~/.config/tmux/plugins/tpm` `git clone https://github.com/tmux-plugins/tpm ~/.config/tmux/plugins/tpm`
## Install Plugins ## Install Plugins
Once the tmux symlink is created, we can install all plugins. This is done using tpm from within a tmux session. Once the tmux symlink is created, we can install all plugins. This is done using tpm from within a tmux session.
```bash ```bash
tmux tmux
<leader> I <leader> I

View File

@@ -2,6 +2,11 @@
# NAVIGATION # NAVIGATION
############ ############
### Helpful Arrow Key Navigation Changes ### Helpful Arrow Key Navigation Changes
# Resize the current pane using Alt + direction
bind -n M-Up resize-pane -U 1
bind -n M-Down resize-pane -D 1
bind -n M-Left resize-pane -L 1
bind -n M-Right resize-pane -R 1
# Use Alt-arrow keys without prefix key to move panes # Use Alt-arrow keys without prefix key to move panes
bind -n C-Left select-pane -L bind -n C-Left select-pane -L
bind -n C-Right select-pane -R bind -n C-Right select-pane -R
@@ -10,15 +15,6 @@ bind -n C-Down select-pane -D
# Shift arrow to switch windows # Shift arrow to switch windows
bind -n S-Left previous-window bind -n S-Left previous-window
bind -n S-Right next-window bind -n S-Right next-window
### Helpful VIM Navigation Changes (Conflicts with Arrows; Choose One)
# Vim style pane selection
#bind-key h select-pane -L
#bind-key j select-pane -D
#bind-key k select-pane -U
#bind-key l select-pane -R
# Shift Alt vim keys to switch windows
#bind -n M-H previous-window
#bind -n M-L next-window
########## ##########
# PLUG-INS # PLUG-INS

View File

@@ -1,4 +1,4 @@
# Shaun's `tmux` Dotfiles # Shaun's `vim` Dotfiles
## Location ## Location
The configuration file needs to be present at this location, `~/.vimrc`. So, we can use the following command to softlink/symlink, The configuration file needs to be present at this location, `~/.vimrc`. So, we can use the following command to softlink/symlink,