Compare commits
8 Commits
15babf9da3
...
0d96105a95
Author | SHA1 | Date | |
---|---|---|---|
0d96105a95 | |||
583c3c46b4 | |||
355f430bac | |||
8cd0b5a1db | |||
a9f22038b8 | |||
dc34a653d1 | |||
81ed3b521c | |||
cc586564bf |
@ -12,7 +12,8 @@ $mainMod = SUPER # Sets "Windows" key as main modifier
|
|||||||
# apps
|
# apps
|
||||||
bind = $mainMod, T, exec, $terminal # terminal
|
bind = $mainMod, T, exec, $terminal # terminal
|
||||||
bind = $mainMod SHIFT, T, exec, crow
|
bind = $mainMod SHIFT, T, exec, crow
|
||||||
bind = $mainMod CTRL SHIFT, T, exec, ~/.config/hypr/scripts/translate-selection.sh
|
bind = CTRL ALT, T, exec, ~/.config/hypr/scripts/translate-clipboard.sh
|
||||||
|
bind = CTRL SHIFT ALT, T, exec, ~/.config/hypr/scripts/translate-selection.sh
|
||||||
bind = $mainMod, E, exec, $fileManager # file manager
|
bind = $mainMod, E, exec, $fileManager # file manager
|
||||||
bind = $mainMod, A, exec, $toggle_menu_cmd # wofi
|
bind = $mainMod, A, exec, $toggle_menu_cmd # wofi
|
||||||
bind = $mainMod CTRL ALT, V, exec, ~/.config/hypr/scripts/dnd-clipboard.sh
|
bind = $mainMod CTRL ALT, V, exec, ~/.config/hypr/scripts/dnd-clipboard.sh
|
||||||
@ -154,4 +155,4 @@ bindm = $mainMod, mouse:273, resizewindow
|
|||||||
bindl = , switch:on:Lid Switch, exec, hyprctl keyword monitor "eDP-1, disable"
|
bindl = , switch:on:Lid Switch, exec, hyprctl keyword monitor "eDP-1, disable"
|
||||||
|
|
||||||
# При открытии крышки (Lid Switch выключён)
|
# При открытии крышки (Lid Switch выключён)
|
||||||
bindl = , switch:off:Lid Switch, exec, hyprctl keyword monitor "eDP-1, preferred, auto, 1"
|
bindl = , switch:off:Lid Switch, exec, hyprctl keyword monitor "eDP-1,1920x1080@60.01,0x0,1.0"
|
||||||
|
@ -44,6 +44,9 @@ source = ./conf/autostart.conf
|
|||||||
env = XCURSOR_SIZE,24
|
env = XCURSOR_SIZE,24
|
||||||
env = HYPRCURSOR_SIZE,24
|
env = HYPRCURSOR_SIZE,24
|
||||||
|
|
||||||
|
debug {
|
||||||
|
disable_logs = false
|
||||||
|
}
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
### LOOK AND FEEL ###
|
### LOOK AND FEEL ###
|
||||||
@ -166,14 +169,14 @@ source = ./conf/keybindings.conf
|
|||||||
# │ WINDOWRULES │
|
# │ WINDOWRULES │
|
||||||
# ╰──────────────────────────────────────────────────────────╯
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
# ──────────────────────────────── copyq ──────────────────────────────
|
# ──────────────────────────────── copyq ──────────────────────────────
|
||||||
windowrule = size 300 400,class:^(copyq)$
|
windowrule = size 300 400,class:com.github.hluk.copyq
|
||||||
windowrule = float,class:com.github.hluk.copyq
|
windowrule = float,class:com.github.hluk.copyq
|
||||||
windowrule = move onscreen cursor,class:com.github.hluk.copyq
|
windowrule = move onscreen cursor,class:com.github.hluk.copyq
|
||||||
|
|
||||||
# ────────────────────── Browser Picture in Picture ──────────────────────
|
# ────────────────────── Browser Picture in Picture ──────────────────────
|
||||||
windowrulev2 = float, title:^(Picture-in-Picture)$
|
windowrule = float, title:^(Picture-in-Picture)$
|
||||||
windowrulev2 = pin, title:^(Picture-in-Picture)$
|
windowrule = pin, title:^(Picture-in-Picture)$
|
||||||
windowrulev2 = move 69.5% 4%, title:^(Picture-in-Picture)$
|
windowrule = move 69.5% 4%, title:^(Picture-in-Picture)$
|
||||||
|
|
||||||
# ──────────────────────── telegram media viewer ──────────────────────
|
# ──────────────────────── telegram media viewer ──────────────────────
|
||||||
windowrulev2 = float, title:(Media viewer)
|
windowrulev2 = float, title:(Media viewer)
|
||||||
@ -214,6 +217,3 @@ windowrule = size 400 400, class:(.*)(Figure)(.*)
|
|||||||
|
|
||||||
windowrule = suppressevent maximize, class:.* # You'll probably like this.
|
windowrule = suppressevent maximize, class:.* # You'll probably like this.
|
||||||
|
|
||||||
workspace = special:music, opacity:0.5
|
|
||||||
workspace = opacity 0.5, onworkspace:name:special:music
|
|
||||||
workspace = special:music, gapsout:100
|
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
background {
|
background {
|
||||||
monitor = eDP-1
|
monitor = eDP-1
|
||||||
path = /home/goodhumored/wallpapers/3.png
|
path = /home/goodhumored/wallpapers/7.png
|
||||||
}
|
}
|
||||||
background {
|
background {
|
||||||
monitor = DP-2
|
monitor = DP-2
|
||||||
path = /home/goodhumored/wallpapers/3.png
|
path = /home/goodhumored/wallpapers/7.png
|
||||||
|
}
|
||||||
|
background {
|
||||||
|
monitor = HDMI-A-1
|
||||||
|
path = /home/goodhumored/wallpapers/7.png
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,5 +21,5 @@ monitor=desc:Iiyama North America PL3270Q 1155103721286,2560x1440@59.95,-640x-14
|
|||||||
# Домашний монитор
|
# Домашний монитор
|
||||||
monitor=desc:BNQ BenQ G925HDA 29A01966019,prefered,auto,1.0
|
monitor=desc:BNQ BenQ G925HDA 29A01966019,prefered,auto,1.0
|
||||||
monitor=desc:HJW MACROSILICON 0x0002E842,prefered,320x-720,1.0
|
monitor=desc:HJW MACROSILICON 0x0002E842,prefered,320x-720,1.0
|
||||||
monitor=desc:Huawei Technologies Co. Inc. ZQE-CBA 0xC080F622,3440x1440@100Hz,-760x-1440,1,bitdepth,10, cm, hdr
|
monitor=desc:Huawei Technologies Co. Inc. ZQE-CBA 0xC080F622,3440x1440@120Hz,-760x-1440,1,bitdepth,10, cm, hdr
|
||||||
monitor=desc:Huawei Technologies Co. Inc. ZQE-CBA 0xC080F622,3440x1440@100Hz,-760x-1440,1,bitdepth,10
|
monitor=desc:Huawei Technologies Co. Inc. ZQE-CBA 0xC080F622,3440x1440@120Hz,-760x-1440,1,bitdepth,10
|
||||||
|
18
.config/hypr/scripts/translate-clipboard.sh
Executable file
18
.config/hypr/scripts/translate-clipboard.sh
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
copied_text=$(wl-paste)
|
||||||
|
|
||||||
|
# Проверяем, есть ли выделенный текст
|
||||||
|
if [ -z "$copied_text" ]; then
|
||||||
|
notify-send "Ошибка" "Нет выделенного текста"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Переводим текст с помощью crow (на русский, например)
|
||||||
|
translated_text=$(echo "$copied_text" | crow -i -t ru)
|
||||||
|
|
||||||
|
# Выводим результат через notify-send
|
||||||
|
notify-send "Перевод" "$translated_text"
|
||||||
|
|
||||||
|
# ─────────────────────────── Старый вариант: ───────────────────────────
|
||||||
|
# qdbus io.crow_translate.CrowTranslate /io/crow_translate/CrowTranslate/MainWindow translateSelection
|
@ -1 +1,19 @@
|
|||||||
qdbus io.crow_translate.CrowTranslate /io/crow_translate/CrowTranslate/MainWindow translateSelection
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Получаем выделенный текст (primary selection)
|
||||||
|
selected_text=$(wl-paste --primary)
|
||||||
|
|
||||||
|
# Проверяем, есть ли выделенный текст
|
||||||
|
if [ -z "$selected_text" ]; then
|
||||||
|
notify-send "Ошибка" "Нет выделенного текста"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Переводим текст с помощью crow (на русский, например)
|
||||||
|
translated_text=$(echo "$selected_text" | crow -i -t ru)
|
||||||
|
|
||||||
|
# Выводим результат через notify-send
|
||||||
|
notify-send "Перевод" "$translated_text"
|
||||||
|
|
||||||
|
# ─────────────────────────── Старый вариант: ───────────────────────────
|
||||||
|
# qdbus io.crow_translate.CrowTranslate /io/crow_translate/CrowTranslate/MainWindow translateSelection
|
||||||
|
@ -1,32 +1,11 @@
|
|||||||
return {
|
return {
|
||||||
"ellisonleao/gruvbox.nvim",
|
"sainnhe/gruvbox-material",
|
||||||
|
lazy = false,
|
||||||
priority = 1000,
|
priority = 1000,
|
||||||
config = function()
|
config = function()
|
||||||
require("gruvbox").setup({
|
-- Optionally configure and load the colorscheme
|
||||||
terminal_colors = true, -- add neovim terminal colors
|
-- directly inside the plugin declaration.
|
||||||
undercurl = true,
|
vim.g.gruvbox_material_enable_italic = true
|
||||||
underline = true,
|
vim.cmd.colorscheme("gruvbox-material")
|
||||||
bold = true,
|
|
||||||
italic = {
|
|
||||||
strings = true,
|
|
||||||
emphasis = true,
|
|
||||||
comments = true,
|
|
||||||
operators = false,
|
|
||||||
folds = true,
|
|
||||||
},
|
|
||||||
strikethrough = true,
|
|
||||||
invert_selection = false,
|
|
||||||
invert_signs = false,
|
|
||||||
invert_tabline = false,
|
|
||||||
invert_intend_guides = false,
|
|
||||||
inverse = true, -- invert background for search, diffs, statuslines and errors
|
|
||||||
contrast = "", -- can be "hard", "soft" or empty string
|
|
||||||
palette_overrides = {},
|
|
||||||
overrides = {},
|
|
||||||
dim_inactive = false,
|
|
||||||
transparent_mode = false,
|
|
||||||
})
|
|
||||||
vim.o.background = "dark"
|
|
||||||
vim.cmd("colorscheme gruvbox")
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,16 @@ return {
|
|||||||
-- Or, specify all three
|
-- Or, specify all three
|
||||||
Outline = { event = "BufWinLeave", text = "symbols-outline", align = "right" },
|
Outline = { event = "BufWinLeave", text = "symbols-outline", align = "right" },
|
||||||
},
|
},
|
||||||
|
custom_buffer_name = function(bufnr)
|
||||||
|
local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype")
|
||||||
|
if filetype == "markdown" and vim.b[bufnr].obsidian_note then
|
||||||
|
local note = vim.b[bufnr].obsidian_note
|
||||||
|
return note.title
|
||||||
|
or table.concat(note.aliases, ", ")
|
||||||
|
or vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":t:r")
|
||||||
|
end
|
||||||
|
return vim.fn.fnamemodify(vim.api.nvim_buf_get_name(bufnr), ":t")
|
||||||
|
end,
|
||||||
},
|
},
|
||||||
version = "^1.0.0", -- optional: only update when a new 1.x version is released
|
version = "^1.0.0", -- optional: only update when a new 1.x version is released
|
||||||
}
|
}
|
||||||
|
@ -4,32 +4,33 @@ return {
|
|||||||
config = function()
|
config = function()
|
||||||
require("lualine").setup({
|
require("lualine").setup({
|
||||||
options = {
|
options = {
|
||||||
theme = "iceberg_dark",
|
icons_enabled = true, -- Включить иконки
|
||||||
component_separators = "",
|
theme = "gruvbox-material",
|
||||||
section_separators = { left = "", right = "" },
|
component_separators = { left = " ", right = " " },
|
||||||
|
section_separators = { left = " ", right = " " },
|
||||||
|
disabled_filetypes = { -- Отключить lualine для определённых типов файлов
|
||||||
|
statusline = {},
|
||||||
|
winbar = {},
|
||||||
|
},
|
||||||
|
-- always_divide_middle = true,
|
||||||
|
globalstatus = true, -- Один статусбар для всех окон
|
||||||
},
|
},
|
||||||
sections = {
|
sections = {
|
||||||
lualine_a = { { "mode", separator = { left = "" }, right_padding = 2 } },
|
lualine_a = { "mode" }, -- Режим (Normal, Insert, etc.)
|
||||||
lualine_b = { "filename", "branch" },
|
lualine_b = { "branch", "diagnostics" }, -- Git и диагностика
|
||||||
lualine_c = {
|
lualine_c = { "filename" }, -- Имя файла
|
||||||
"%=", --[[ add your center compoentnts here in place of this comment ]]
|
lualine_x = { "fileformat", "filetype" }, -- Кодировка, формат, тип файла
|
||||||
},
|
lualine_y = { "progress" }, -- Прогресс в файле
|
||||||
lualine_x = {},
|
lualine_z = { "location" }, -- Положение курсора
|
||||||
lualine_y = { "filetype", "progress" },
|
|
||||||
lualine_z = {
|
|
||||||
{ "location", separator = { right = "" }, left_padding = 2 },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
inactive_sections = {
|
inactive_sections = {
|
||||||
lualine_a = { "filename" },
|
lualine_a = {},
|
||||||
lualine_b = {},
|
lualine_b = {},
|
||||||
lualine_c = {},
|
lualine_c = { "filename" },
|
||||||
lualine_x = {},
|
lualine_x = { "location" },
|
||||||
lualine_y = {},
|
lualine_y = {},
|
||||||
lualine_z = { "location" },
|
lualine_z = {},
|
||||||
},
|
},
|
||||||
tabline = {},
|
|
||||||
extensions = {},
|
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,9 @@ return {
|
|||||||
local api = require("nvim-tree.api")
|
local api = require("nvim-tree.api")
|
||||||
vim.keymap.set("n", "<leader>e", api.tree.toggle, { desc = "[E]xplorer" })
|
vim.keymap.set("n", "<leader>e", api.tree.toggle, { desc = "[E]xplorer" })
|
||||||
vim.keymap.set("n", "<leader>E", function()
|
vim.keymap.set("n", "<leader>E", function()
|
||||||
|
-- api.tree.open() -- Просто открываем дерево
|
||||||
api.tree.find_file({ open = true, focus = true })
|
api.tree.find_file({ open = true, focus = true })
|
||||||
|
-- api.tree.find_file({ focus = true })
|
||||||
end, { desc = "Focus file in [E]xplorer" })
|
end, { desc = "Focus file in [E]xplorer" })
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,8 @@ vim.opt.cursorline = true
|
|||||||
-- Minimal number of screen lines to keep above and below the cursor.
|
-- Minimal number of screen lines to keep above and below the cursor.
|
||||||
vim.opt.scrolloff = 10
|
vim.opt.scrolloff = 10
|
||||||
|
|
||||||
|
vim.o.termguicolors = true
|
||||||
|
|
||||||
-- [[ Basic Keymaps ]]
|
-- [[ Basic Keymaps ]]
|
||||||
-- See `:help vim.keymap.set()`
|
-- See `:help vim.keymap.set()`
|
||||||
|
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
return {
|
return {
|
||||||
"jiangmiao/auto-pairs",
|
"windwp/nvim-autopairs",
|
||||||
|
-- config = function()
|
||||||
|
-- require("nvim-autopairs").setup({
|
||||||
|
-- check_ts = true, -- Опционально, если используешь treesitter
|
||||||
|
-- })
|
||||||
|
--
|
||||||
|
-- -- Переопределяем автокомманду BufEnter
|
||||||
|
-- vim.api.nvim_create_autocmd("BufEnter", {
|
||||||
|
-- group = vim.api.nvim_create_augroup("NvimAutopairsCustom", { clear = true }),
|
||||||
|
-- callback = function()
|
||||||
|
-- if vim.bo.filetype ~= "NvimTree" then
|
||||||
|
-- require("nvim-autopairs").on_enter()
|
||||||
|
-- end
|
||||||
|
-- end,
|
||||||
|
-- })
|
||||||
|
-- end,
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,10 @@ return {
|
|||||||
-- require("goodhumored.languages.rust.rust.vim"),
|
-- require("goodhumored.languages.rust.rust.vim"),
|
||||||
require("goodhumored.languages.rust.rust-tools"),
|
require("goodhumored.languages.rust.rust-tools"),
|
||||||
require("goodhumored.languages.markdown.otter"),
|
require("goodhumored.languages.markdown.otter"),
|
||||||
|
require("goodhumored.languages.markdown.obsidian-nvim"),
|
||||||
|
require("goodhumored.languages.markdown.bullets-nvim"),
|
||||||
require("goodhumored.languages.markdown.markview"),
|
require("goodhumored.languages.markdown.markview"),
|
||||||
require("goodhumored.languages.markdown.markdown-preview"),
|
-- require("goodhumored.languages.markdown.markdown-preview"),
|
||||||
require("goodhumored.languages.plantuml.plantuml"),
|
require("goodhumored.languages.plantuml.plantuml"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
return {
|
||||||
|
"bullets-vim/bullets.vim",
|
||||||
|
}
|
@ -14,4 +14,60 @@ return {
|
|||||||
"nvim-treesitter/nvim-treesitter",
|
"nvim-treesitter/nvim-treesitter",
|
||||||
"nvim-tree/nvim-web-devicons",
|
"nvim-tree/nvim-web-devicons",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
config = function()
|
||||||
|
-- Настройка markview.nvim
|
||||||
|
require("markview").setup({
|
||||||
|
modes = { "n", "i", "c" },
|
||||||
|
hybrid_modes = { "i" },
|
||||||
|
checkboxes = {
|
||||||
|
enable = false, -- Отключить чекбоксы, чтобы избежать конфликта с obsidian.nvim
|
||||||
|
},
|
||||||
|
headings = {
|
||||||
|
enable = true,
|
||||||
|
level_1 = {
|
||||||
|
style = "icon",
|
||||||
|
icon = "📌 ",
|
||||||
|
hl = "MarkviewHeading1",
|
||||||
|
padding_left = " ",
|
||||||
|
padding_right = " ",
|
||||||
|
},
|
||||||
|
level_2 = {
|
||||||
|
style = "icon",
|
||||||
|
icon = "📋 ",
|
||||||
|
hl = "MarkviewHeading2",
|
||||||
|
padding_left = " ",
|
||||||
|
padding_right = " ",
|
||||||
|
},
|
||||||
|
level_3 = {
|
||||||
|
style = "icon",
|
||||||
|
icon = "📝 ",
|
||||||
|
hl = "MarkviewHeading3",
|
||||||
|
padding_left = " ",
|
||||||
|
padding_right = " ",
|
||||||
|
},
|
||||||
|
level_4 = {
|
||||||
|
style = "icon",
|
||||||
|
icon = "🔖 ",
|
||||||
|
hl = "MarkviewHeading4",
|
||||||
|
padding_left = " ",
|
||||||
|
padding_right = " ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
list_items = {
|
||||||
|
enable = false,
|
||||||
|
marker_minus = { rendered = "•" },
|
||||||
|
marker_star = { rendered = "★" },
|
||||||
|
marker_plus = { rendered = "➕" },
|
||||||
|
},
|
||||||
|
links = {
|
||||||
|
enable = false,
|
||||||
|
conceal = false,
|
||||||
|
hl = "Underlined",
|
||||||
|
},
|
||||||
|
conceal = {
|
||||||
|
enabled = true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,183 @@
|
|||||||
|
return {
|
||||||
|
"epwalsh/obsidian.nvim",
|
||||||
|
version = "*", -- recommended, use latest release instead of latest commit
|
||||||
|
lazy = true,
|
||||||
|
ft = "markdown",
|
||||||
|
-- Replace the above line with this if you only want to load obsidian.nvim for markdown files in your vault:
|
||||||
|
-- event = {
|
||||||
|
-- -- If you want to use the home shortcut '~' here you need to call 'vim.fn.expand'.
|
||||||
|
-- -- E.g. "BufReadPre " .. vim.fn.expand "~" .. "/my-vault/*.md"
|
||||||
|
-- -- refer to `:h file-pattern` for more examples
|
||||||
|
-- "BufReadPre path/to/my-vault/*.md",
|
||||||
|
-- "BufNewFile path/to/my-vault/*.md",
|
||||||
|
-- },
|
||||||
|
dependencies = {
|
||||||
|
-- Required.
|
||||||
|
"nvim-lua/plenary.nvim",
|
||||||
|
|
||||||
|
-- see below for full list of optional dependencies 👇
|
||||||
|
},
|
||||||
|
opts = {
|
||||||
|
workspaces = {
|
||||||
|
{
|
||||||
|
name = "personal",
|
||||||
|
path = "~/notes/personal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "work",
|
||||||
|
path = "~/notes/work/",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "study",
|
||||||
|
path = "~/notes/study",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
-- Optional, configure key mappings. These are the defaults. If you don't want to set any keymappings this
|
||||||
|
-- way then set 'mappings = {}'.
|
||||||
|
mappings = {
|
||||||
|
-- Overrides the 'gf' mapping to work on markdown/wiki links within your vault.
|
||||||
|
["gf"] = {
|
||||||
|
action = function()
|
||||||
|
return require("obsidian").util.gf_passthrough()
|
||||||
|
end,
|
||||||
|
opts = { noremap = false, expr = true, buffer = true },
|
||||||
|
},
|
||||||
|
["<leader>njt"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianToday")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "Open [t]oday's daily note" },
|
||||||
|
},
|
||||||
|
["<leader>njT"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianTomorrow")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "Open [t]omorrow's daily note" },
|
||||||
|
},
|
||||||
|
["<leader>njy"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianYesterday")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "Open [y]esterday's daily note" },
|
||||||
|
},
|
||||||
|
["<leader>nj"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianDailies")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "Obsidian dailies" },
|
||||||
|
},
|
||||||
|
["<leader>so"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianSearch")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "[S]earch [O]bsidian" },
|
||||||
|
},
|
||||||
|
["<leader>ow"] = {
|
||||||
|
action = function()
|
||||||
|
return vim.cmd("ObsidianWorkspace")
|
||||||
|
end,
|
||||||
|
opts = { noremap = true, buffer = true, desc = "[O]bsidian [W]orkspace" },
|
||||||
|
},
|
||||||
|
-- Toggle check-boxes.
|
||||||
|
["<leader>ch"] = {
|
||||||
|
action = function()
|
||||||
|
return require("obsidian").util.toggle_checkbox()
|
||||||
|
end,
|
||||||
|
opts = { buffer = true },
|
||||||
|
},
|
||||||
|
-- Smart action depending on context, either follow link or toggle checkbox.
|
||||||
|
["<cr>"] = {
|
||||||
|
action = function()
|
||||||
|
return require("obsidian").util.smart_action()
|
||||||
|
end,
|
||||||
|
opts = { buffer = true, expr = true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
daily_notes = {
|
||||||
|
-- Optional, if you keep daily notes in a separate directory.
|
||||||
|
folder = "daily",
|
||||||
|
-- Optional, if you want to change the date format for the ID of daily notes.
|
||||||
|
date_format = "%Y-%m-%d",
|
||||||
|
-- Optional, if you want to change the date format of the default alias of daily notes.
|
||||||
|
alias_format = "%B %-d, %Y",
|
||||||
|
-- Optional, default tags to add to each new daily note created.
|
||||||
|
default_tags = { "daily-notes" },
|
||||||
|
-- Optional, if you want to automatically insert a template from your template directory like 'daily.md'
|
||||||
|
template = nil,
|
||||||
|
},
|
||||||
|
ui = {
|
||||||
|
enable = true, -- set to false to disable all additional syntax features
|
||||||
|
update_debounce = 200, -- update delay after a text change (in milliseconds)
|
||||||
|
max_file_length = 5000, -- disable UI features for files with more than this many lines
|
||||||
|
-- Define how various check-boxes are displayed
|
||||||
|
checkboxes = {
|
||||||
|
-- NOTE: the 'char' value has to be a single character, and the highlight groups are defined below.
|
||||||
|
[" "] = { char = "", hl_group = "ObsidianTodo" },
|
||||||
|
["."] = { char = "", hl_group = "ObsidianInProgress" },
|
||||||
|
["x"] = { char = "", hl_group = "ObsidianDone" },
|
||||||
|
["="] = { char = "", hl_group = "ObsidianPause" },
|
||||||
|
[">"] = { char = "", hl_group = "ObsidianRightArrow" },
|
||||||
|
["~"] = { char = "", hl_group = "ObsidianTilde" },
|
||||||
|
["!"] = { char = "", hl_group = "ObsidianImportant" },
|
||||||
|
-- Replace the above with this if you don't have a patched font:
|
||||||
|
-- [" "] = { char = "☐", hl_group = "ObsidianTodo" },
|
||||||
|
-- ["x"] = { char = "✔", hl_group = "ObsidianDone" },
|
||||||
|
|
||||||
|
-- You can also add more custom ones...
|
||||||
|
},
|
||||||
|
-- Use bullet marks for non-checkbox lists.
|
||||||
|
bullets = { char = "•", hl_group = "ObsidianBullet" },
|
||||||
|
external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" },
|
||||||
|
-- Replace the above with this if you don't have a patched font:
|
||||||
|
-- external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" },
|
||||||
|
reference_text = { hl_group = "ObsidianRefText" },
|
||||||
|
highlight_text = { hl_group = "ObsidianHighlightText" },
|
||||||
|
tags = { hl_group = "ObsidianTag" },
|
||||||
|
block_ids = { hl_group = "ObsidianBlockID" },
|
||||||
|
hl_groups = {
|
||||||
|
-- The options are passed directly to `vim.api.nvim_set_hl()`. See `:help nvim_set_hl`.
|
||||||
|
ObsidianTodo = { bold = true, fg = "#89ddff" },
|
||||||
|
ObsidianInProgress = { bold = true, fg = "#a8e0ae" },
|
||||||
|
ObsidianDone = { bold = true, fg = "#84c470" },
|
||||||
|
ObsidianRightArrow = { bold = true, fg = "#f78c6c" },
|
||||||
|
ObsidianTilde = { bold = true, fg = "#bbbcc7" },
|
||||||
|
ObsidianImportant = { bold = true, fg = "#d73128" },
|
||||||
|
ObsidianPause = { bold = true, fg = "#bcd1a7" },
|
||||||
|
ObsidianBullet = { bold = true, fg = "#89ddff" },
|
||||||
|
ObsidianRefText = { underline = true, fg = "#c792ea" },
|
||||||
|
ObsidianExtLinkIcon = { fg = "#c792ea" },
|
||||||
|
ObsidianTag = { italic = true, fg = "#89ddff" },
|
||||||
|
ObsidianBlockID = { italic = true, fg = "#89ddff" },
|
||||||
|
ObsidianHighlightText = { bg = "#75662e" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Specify how to handle attachments.
|
||||||
|
attachments = {
|
||||||
|
-- The default folder to place images in via `:ObsidianPasteImg`.
|
||||||
|
-- If this is a relative path it will be interpreted as relative to the vault root.
|
||||||
|
-- You can always override this per image by passing a full path to the command instead of just a filename.
|
||||||
|
img_folder = "assets/imgs", -- This is the default
|
||||||
|
|
||||||
|
-- Optional, customize the default name or prefix when pasting images via `:ObsidianPasteImg`.
|
||||||
|
---@return string
|
||||||
|
img_name_func = function()
|
||||||
|
-- Prefix image names with timestamp.
|
||||||
|
return string.format("%s-", os.time())
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- A function that determines the text to insert in the note when pasting an image.
|
||||||
|
-- It takes two arguments, the `obsidian.Client` and an `obsidian.Path` to the image file.
|
||||||
|
-- This is the default implementation.
|
||||||
|
---@param client obsidian.Client
|
||||||
|
---@param path obsidian.Path the absolute path to the image file
|
||||||
|
---@return string
|
||||||
|
img_text_func = function(client, path)
|
||||||
|
path = client:vault_relative_path(path) or path
|
||||||
|
return string.format("", path.name, path)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- see below for full list of options 👇
|
||||||
|
},
|
||||||
|
}
|
@ -45,35 +45,35 @@ return {
|
|||||||
end,
|
end,
|
||||||
|
|
||||||
keys = {
|
keys = {
|
||||||
{
|
-- {
|
||||||
"<leader>nw",
|
-- "<leader>nw",
|
||||||
":Neorg workspace ",
|
-- ":Neorg workspace ",
|
||||||
desc = "[N]eorg [W]orkspaces",
|
-- desc = "[N]eorg [W]orkspaces",
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
"<leader>nj",
|
-- "<leader>nj",
|
||||||
":Neorg journal<CR>",
|
-- ":Neorg journal<CR>",
|
||||||
desc = "[N]eorg [J]ournal",
|
-- desc = "[N]eorg [J]ournal",
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
"<leader>ni",
|
-- "<leader>ni",
|
||||||
":Neorg index<CR>",
|
-- ":Neorg index<CR>",
|
||||||
desc = "[N]eorg [I]ndex",
|
-- desc = "[N]eorg [I]ndex",
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
"<leader>nT",
|
-- "<leader>nT",
|
||||||
":Neorg toc qflist<CR>",
|
-- ":Neorg toc qflist<CR>",
|
||||||
desc = "[N]eorg [T]able of contents",
|
-- desc = "[N]eorg [T]able of contents",
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
"<leader>nr",
|
-- "<leader>nr",
|
||||||
":Neorg return<CR>",
|
-- ":Neorg return<CR>",
|
||||||
desc = "[N]eorg [R]eturn",
|
-- desc = "[N]eorg [R]eturn",
|
||||||
},
|
-- },
|
||||||
{
|
-- {
|
||||||
"<leader>tl",
|
-- "<leader>tl",
|
||||||
":Neorg render-latex<CR>",
|
-- ":Neorg render-latex<CR>",
|
||||||
desc = "[N]eorg [L]atex",
|
-- desc = "[N]eorg [L]atex",
|
||||||
},
|
-- },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -110,6 +110,11 @@ set -g @continuum-restore 'on' # enabling
|
|||||||
# ╰──────────────────────────────────────────────────────────╯
|
# ╰──────────────────────────────────────────────────────────╯
|
||||||
set -g @plugin 'egel/tmux-gruvbox'
|
set -g @plugin 'egel/tmux-gruvbox'
|
||||||
set -g @tmux-gruvbox 'dark'
|
set -g @tmux-gruvbox 'dark'
|
||||||
|
set -g @tmux-gruvbox-status-left "#[bg=colour241,fg=colour248] #S #[bg=colour237,fg=colour241,nobold,noitalics,nounderscore]"
|
||||||
|
set -g @tmux-gruvbox-status-right "#[bg=colour237,fg=colour239 nobold, nounderscore, noitalics]#[bg=colour239,fg=colour246] %Y-%m-%d │ %H:%M #[bg=colour239,fg=colour248,nobold,noitalics,nounderscore]#[bg=colour248,fg=colour237] #h "
|
||||||
|
|
||||||
|
set -g @tmux-gruvbox-window-status-current-format "#[bg=colour214,fg=colour237,nobold,noitalics,nounderscore]#[bg=colour214,fg=colour239] #I │#[bg=colour214,fg=colour239,bold] #W#{?window_zoomed_flag,*Z,} #[bg=colour237,fg=colour214,nobold,noitalics,nounderscore]"
|
||||||
|
set -g @tmux-gruvbox-window-status-format "#[bg=colour239,fg=colour237,noitalics]#[bg=colour239,fg=colour223] #I │#[bg=colour239,fg=colour223] #W #[bg=colour237,fg=colour239,noitalics]│"
|
||||||
|
|
||||||
# ╭──────────────────────────────────────────────────────────╮
|
# ╭──────────────────────────────────────────────────────────╮
|
||||||
# │ Dracula theme │
|
# │ Dracula theme │
|
||||||
|
135
init.sh
Executable file
135
init.sh
Executable file
@ -0,0 +1,135 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print messages
|
||||||
|
info() {
|
||||||
|
echo -e "${GREEN}[INFO] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}[ERROR] $1${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect OS
|
||||||
|
OS=""
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
case $ID in
|
||||||
|
ubuntu)
|
||||||
|
OS="ubuntu"
|
||||||
|
;;
|
||||||
|
arch)
|
||||||
|
OS="arch"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
error "Unsupported OS: $ID"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
error "Cannot detect OS. /etc/os-release not found."
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Detected OS: $OS"
|
||||||
|
|
||||||
|
# Ensure we're in the dotfiles directory
|
||||||
|
if [ ! -f "$(pwd)/.gitmodules" ]; then
|
||||||
|
error "This script must be run from the dotfiles repository directory"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install prerequisites
|
||||||
|
info "Installing prerequisites..."
|
||||||
|
|
||||||
|
if [ "$OS" = "ubuntu" ]; then
|
||||||
|
# Update package lists
|
||||||
|
sudo apt update && sudo apt upgrade -y
|
||||||
|
|
||||||
|
# Install required packages
|
||||||
|
sudo apt install -y git tmux stow fzf gcc
|
||||||
|
|
||||||
|
# Install optional packages (bat, fd-find, zoxide)
|
||||||
|
sudo apt install -y bat fd-find
|
||||||
|
curl -sS https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | bash
|
||||||
|
|
||||||
|
# Install eza (community-maintained ls alternative)
|
||||||
|
sudo mkdir -p /etc/apt/keyrings
|
||||||
|
wget -qO- https://raw.githubusercontent.com/eza-community/eza/main/deb.asc | sudo gpg --dearmor -o /etc/apt/keyrings/gierens.gpg
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/gierens.gpg] http://deb.gierens.de stable main" | sudo tee /etc/apt/sources.list.d/gierens.list
|
||||||
|
sudo chmod 644 /etc/apt/keyrings/gierens.gpg /etc/apt/sources.list.d/gierens.list
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y eza
|
||||||
|
|
||||||
|
# Install Neovim from GitHub releases (latest stable)
|
||||||
|
info "Installing Neovim from GitHub releases..."
|
||||||
|
NVIM_VERSION=$(curl -s https://api.github.com/repos/neovim/neovim/releases/latest | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
|
||||||
|
wget -O /tmp/nvim-linux64.tar.gz "https://github.com/neovim/neovim/releases/download/${NVIM_VERSION}/nvim-linux64.tar.gz"
|
||||||
|
sudo tar -C /usr/local -xzf /tmp/nvim-linux64.tar.gz
|
||||||
|
sudo ln -sf /usr/local/nvim-linux64/bin/nvim /usr/local/bin/nvim
|
||||||
|
rm /tmp/nvim-linux64.tar.gz
|
||||||
|
|
||||||
|
# Install thefuck
|
||||||
|
sudo apt install -y python3-pip
|
||||||
|
pip3 install thefuck --user
|
||||||
|
|
||||||
|
elif [ "$OS" = "arch" ]; then
|
||||||
|
# Ensure yay is installed for AUR packages
|
||||||
|
if ! command -v yay &> /dev/null; then
|
||||||
|
info "Installing yay..."
|
||||||
|
sudo pacman -S --needed git base-devel
|
||||||
|
git clone https://aur.archlinux.org/yay.git /tmp/yay
|
||||||
|
cd /tmp/yay
|
||||||
|
makepkg -si --noconfirm
|
||||||
|
cd - && rm -rf /tmp/yay
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install all packages
|
||||||
|
yay -S --noconfirm git tmux neovim zoxide stow fzf bat eza fd gcc thefuck
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize and update submodules
|
||||||
|
info "Initializing git submodules..."
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
# Backup existing config files
|
||||||
|
info "Backing up existing configuration files..."
|
||||||
|
BACKUP_DIR="$HOME/.dotfiles_backup_$(date +%F_%H-%M-%S)"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
for file in .gitconfig .zshrc .tmux.conf .bashrc; do
|
||||||
|
[ -f "$HOME/$file" ] && mv "$HOME/$file" "$BACKUP_DIR/$file" && info "Backed up ~/$file to $BACKUP_DIR/$file"
|
||||||
|
done
|
||||||
|
|
||||||
|
for dir in .config/nvim .config/mc kam .oh-my-zsh .tmux; do
|
||||||
|
[ -d "$HOME/$dir" ] && mv "$HOME/$dir" "$BACKUP_DIR/$(basename $dir)" && info "Backed up ~/$dir to $BACKUP_DIR/$(basename $dir)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create symlinks with stow
|
||||||
|
info "Creating symlinks with stow..."
|
||||||
|
stow .
|
||||||
|
|
||||||
|
# Change shell to zsh
|
||||||
|
if [ "$(basename "$SHELL")" != "zsh" ]; then
|
||||||
|
info "Changing shell to zsh..."
|
||||||
|
ZSH_PATH=$(which zsh)
|
||||||
|
if [ -z "$ZSH_PATH" ]; then
|
||||||
|
error "zsh not found. Please install zsh and run 'chsh -s $(which zsh)' manually."
|
||||||
|
fi
|
||||||
|
chsh -s "$ZSH_PATH"
|
||||||
|
info "Shell changed to zsh. Please log out and log back in for the change to take effect."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Final instructions
|
||||||
|
info "Dotfiles setup complete!"
|
||||||
|
echo "To source tmux configuration:"
|
||||||
|
echo "1. Start tmux with 'tmux'"
|
||||||
|
echo "2. Press <prefix>: (default is Ctrl+b)"
|
||||||
|
echo "3. Type 'source ~/.tmux.conf' and press Enter"
|
||||||
|
echo
|
||||||
|
echo "Backup of previous configs is stored in: $BACKUP_DIR"
|
||||||
|
echo "You may need to log out and log back in for zsh to take effect."
|
91
local_seed.sh
Executable file
91
local_seed.sh
Executable file
@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
ANONYMOUS=false
|
||||||
|
USERNAME="goodhumored"
|
||||||
|
|
||||||
|
# Function to print messages
|
||||||
|
info() {
|
||||||
|
echo -e "${GREEN}[INFO] $1${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "${RED}[ERROR] $1${NC}" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate random username for anonymous mode
|
||||||
|
generate_random_username() {
|
||||||
|
echo "user$(head /dev/urandom | tr -dc a-z0-9 | head -c 8)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to display usage
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo "Options:"
|
||||||
|
echo " -u, --username Username to create (default: goodhumored)"
|
||||||
|
echo " -a, --anonymous Run in anonymous mode (random username, no dotfiles)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-u|--username) USERNAME="$2"; shift ;;
|
||||||
|
-a|--anonymous) ANONYMOUS=true ;;
|
||||||
|
*) echo "Unknown parameter: $1"; usage ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Set username for anonymous mode
|
||||||
|
if [ "$ANONYMOUS" = true ]; then
|
||||||
|
USERNAME=$(generate_random_username)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$(id -u)" -ne 0 ]; then
|
||||||
|
error "This script must be run with sudo privileges"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create user and setup home directory
|
||||||
|
info "Creating user $USERNAME..."
|
||||||
|
useradd -m -s /bin/bash -G sudo "$USERNAME"
|
||||||
|
chmod 700 "/home/$USERNAME"
|
||||||
|
|
||||||
|
# Setup SSH directory and authorized_keys
|
||||||
|
info "Setting up SSH directory..."
|
||||||
|
mkdir -p "/home/$USERNAME/.ssh"
|
||||||
|
chmod 700 "/home/$USERNAME/.ssh"
|
||||||
|
touch "/home/$USERNAME/.ssh/authorized_keys"
|
||||||
|
chmod 600 "/home/$USERNAME/.ssh/authorized_keys"
|
||||||
|
chown -R "$USERNAME:$USERNAME" "/home/$USERNAME/.ssh"
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
info "Installing dependencies..."
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y git stow
|
||||||
|
|
||||||
|
# Clone and setup dotfiles (non-anonymous mode only)
|
||||||
|
if [ "$ANONYMOUS" = false ]; then
|
||||||
|
info "Cloning dotfiles repository..."
|
||||||
|
su - "$USERNAME" -c "git clone https://github.com/goodhumored/dotfiles /home/$USERNAME/dotfiles"
|
||||||
|
info "Running init.sh..."
|
||||||
|
su - "$USERNAME" -c "cd /home/$USERNAME/dotfiles && ./init.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Local server setup complete!"
|
||||||
|
echo "Username: $USERNAME"
|
||||||
|
if [ "$ANONYMOUS" = false ]; then
|
||||||
|
echo "Dotfiles have been cloned and initialized."
|
||||||
|
else
|
||||||
|
echo "Anonymous mode: No dotfiles cloned."
|
||||||
|
fi
|
||||||
|
echo "You can now add an SSH public key to /home/$USERNAME/.ssh/authorized_keys"
|
150
seed.sh
Executable file
150
seed.sh
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
ANONYMOUS=false
|
||||||
|
PORT=22
|
||||||
|
NEW_USER="goodhumored"
|
||||||
|
PASS_DIR="$HOME/.password-store"
|
||||||
|
|
||||||
|
# Random username for anonymous mode
|
||||||
|
generate_random_username() {
|
||||||
|
echo "user$(head /dev/urandom | tr -dc a-z0-9 | head -c 8)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo " -h, --host Server IP"
|
||||||
|
echo " -p, --port SSH port (default: 22)"
|
||||||
|
echo " -r, --root_user Sudo user for SSH"
|
||||||
|
echo " -s, --server_name Server name for SSH config"
|
||||||
|
echo " -u, --username User to create (default: goodhumored)"
|
||||||
|
echo " -n, --pass_name Password store name"
|
||||||
|
echo " -a, --anonymous Anonymous mode"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check sshpass
|
||||||
|
if ! command -v sshpass &> /dev/null; then
|
||||||
|
echo "Ошибка: нужен sshpass."
|
||||||
|
echo "Установи: sudo apt-get install sshpass (Ubuntu) или sudo pacman -S sshpass (Arch)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Parse args
|
||||||
|
while [[ "$#" -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--host) HOST="$2"; shift ;;
|
||||||
|
-p|--port) PORT="$2"; shift ;;
|
||||||
|
-r|--root_user) ROOT_USER="$2"; shift ;;
|
||||||
|
-s|--server_name) SERVER_NAME="$2"; shift ;;
|
||||||
|
-u|--username) NEW_USER="$2"; shift ;;
|
||||||
|
-n|--pass_name) PASS_NAME="$2"; shift ;;
|
||||||
|
-a|--anonymous) ANONYMOUS=true ;;
|
||||||
|
*) echo "Неизвестный параметр: $1"; usage ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Validate args
|
||||||
|
if [ -z "$HOST" ] || [ -z "$ROOT_USER" ] || [ -z "$SERVER_NAME" ]; then
|
||||||
|
echo "Ошибка: нужны host, root_user и server_name"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Prompt for password
|
||||||
|
if [ "$ANONYMOUS" = false ]; then
|
||||||
|
if [ -z "$PASS_NAME" ]; then
|
||||||
|
read -p "Имя для хранения пароля: " PASS_NAME
|
||||||
|
fi
|
||||||
|
read -s -p "Пароль для SSH и sudo: " ROOT_PASS
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set username for anonymous
|
||||||
|
if [ "$ANONYMOUS" = true ]; then
|
||||||
|
NEW_USER=$(generate_random_username)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate SSH key
|
||||||
|
KEY_PATH="$HOME/.ssh/keys/$SERVER_NAME"
|
||||||
|
mkdir -p "$HOME/.ssh/keys"
|
||||||
|
ssh-keygen -t ed25519 -f "$KEY_PATH" -N "" -C "$SERVER_NAME"
|
||||||
|
|
||||||
|
# Read public key
|
||||||
|
PUBLIC_KEY=$(cat "$KEY_PATH.pub")
|
||||||
|
|
||||||
|
# Generate and store password
|
||||||
|
NEW_PASS=""
|
||||||
|
if [ "$ANONYMOUS" = false ]; then
|
||||||
|
mkdir -p "$PASS_DIR"
|
||||||
|
NEW_PASS="$(pass generate "$PASS_NAME" 16 | tail -n1)"
|
||||||
|
echo "DEBUG: Generated password: '$NEW_PASS'"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update SSH config
|
||||||
|
CONFIG_FILE="$HOME/.ssh/config"
|
||||||
|
touch "$CONFIG_FILE"
|
||||||
|
chmod 600 "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Remove old entry
|
||||||
|
sed -i "/Host $SERVER_NAME/,/^\s*$/d" "$CONFIG_FILE"
|
||||||
|
|
||||||
|
# Add new entry
|
||||||
|
cat << EOF >> "$CONFIG_FILE"
|
||||||
|
|
||||||
|
Host $SERVER_NAME
|
||||||
|
HostName $HOST
|
||||||
|
Port $PORT
|
||||||
|
User $NEW_USER
|
||||||
|
IdentityFile $KEY_PATH
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# SSH commands
|
||||||
|
SSH_COMMANDS=$(cat << ENDSSH
|
||||||
|
set -e
|
||||||
|
echo '\$PUBLIC_KEY'
|
||||||
|
|
||||||
|
# Create user
|
||||||
|
echo "\$SUDO_PASS" | sudo -S useradd -m -s /bin/bash -G sudo "\$NEW_USER"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S chmod 700 "/home/\$NEW_USER"
|
||||||
|
|
||||||
|
# Set password
|
||||||
|
if [ -n "\$NEW_PASS" ]; then
|
||||||
|
echo "DEBUG: Setting password for \$NEW_USER: \$NEW_PASS"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S bash -c "echo \"\$NEW_USER:\$NEW_PASS\" | chpasswd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Setup SSH dir
|
||||||
|
echo "\$SUDO_PASS" | sudo -S mkdir -p "/home/\$NEW_USER/.ssh"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S chmod 700 "/home/\$NEW_USER/.ssh"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S touch "/home/\$NEW_USER/.ssh/authorized_keys"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S chmod 600 "/home/\$NEW_USER/.ssh/authorized_keys"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S chown -R "\$NEW_USER:\$NEW_USER" "/home/\$NEW_USER/.ssh"
|
||||||
|
echo "\$SUDO_PASS" | sudo -S bash -c "echo \"\$PUBLIC_KEY\" >> /home/\$NEW_USER/.ssh/authorized_keys"
|
||||||
|
|
||||||
|
# Install deps
|
||||||
|
echo "\$SUDO_PASS" | sudo -S apt-get update
|
||||||
|
echo "\$SUDO_PASS" | sudo -S apt-get install -y git stow
|
||||||
|
ENDSSH
|
||||||
|
)
|
||||||
|
|
||||||
|
# Run SSH commands
|
||||||
|
SSHPASS="$ROOT_PASS" sshpass -e ssh -p "$PORT" "$ROOT_USER@$HOST" "SUDO_PASS='$ROOT_PASS' ANONYMOUS=$ANONYMOUS NEW_USER='$NEW_USER' PUBLIC_KEY='$PUBLIC_KEY' NEW_PASS='$NEW_PASS' bash -c '$SSH_COMMANDS'"
|
||||||
|
|
||||||
|
ssh "$SERVER_NAME" bash -c "$(cat << ENDSSH
|
||||||
|
set -e
|
||||||
|
git clone https://github.com/goodhumored/dotfiles
|
||||||
|
cd dotfiles
|
||||||
|
./init.sh
|
||||||
|
ENDSSH
|
||||||
|
)"
|
||||||
|
|
||||||
|
echo "Настройка завершена!"
|
||||||
|
echo "Пользователь: $NEW_USER"
|
||||||
|
echo "SSH команда: ssh $SERVER_NAME"
|
||||||
|
if [ "$ANONYMOUS" = false ]; then
|
||||||
|
echo "Пароль сохранен в: $PASS_NAME"
|
||||||
|
fi
|
114
seed_v2.sh
Normal file
114
seed_v2.sh
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# --- Константы ---
|
||||||
|
DEFAULT_PORT=22
|
||||||
|
DEFAULT_USER="goodhumored"
|
||||||
|
PASS_DIR="$HOME/.password-store"
|
||||||
|
KEYS_DIR="$HOME/.ssh/keys"
|
||||||
|
|
||||||
|
# --- Утилиты ---
|
||||||
|
require() {
|
||||||
|
if ! command -v "$1" &> /dev/null; then
|
||||||
|
echo "Ошибка: нужна утилита '$1'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
require sshpass
|
||||||
|
require ssh-keygen
|
||||||
|
require pass
|
||||||
|
|
||||||
|
# --- Параметры ---
|
||||||
|
ANONYMOUS=false
|
||||||
|
PORT="$DEFAULT_PORT"
|
||||||
|
NEW_USER="$DEFAULT_USER"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--host) HOST="$2"; shift ;;
|
||||||
|
-p|--port) PORT="$2"; shift ;;
|
||||||
|
-r|--root_user) ROOT_USER="$2"; shift ;;
|
||||||
|
-s|--server_name) SERVER_NAME="$2"; shift ;;
|
||||||
|
-u|--username) NEW_USER="$2"; shift ;;
|
||||||
|
-n|--pass_name) PASS_NAME="$2"; shift ;;
|
||||||
|
-a|--anonymous) ANONYMOUS=true ;;
|
||||||
|
*) echo "Неизвестный параметр: $1"; exit 1 ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -z "${HOST:-}" || -z "${ROOT_USER:-}" || -z "${SERVER_NAME:-}" ]] && {
|
||||||
|
echo "Ошибка: нужны --host, --root_user и --server_name"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Логика ---
|
||||||
|
if $ANONYMOUS; then
|
||||||
|
NEW_USER="user$(tr -dc a-z0-9 </dev/urandom | head -c 8)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${PASS_NAME:-}" ] && ! $ANONYMOUS; then
|
||||||
|
read -p "Имя для пароля: " PASS_NAME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $ANONYMOUS; then
|
||||||
|
read -s -p "Пароль root для подключения: " ROOT_PASS
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Генерация ключа
|
||||||
|
mkdir -p "$KEYS_DIR"
|
||||||
|
KEY_PATH="$KEYS_DIR/$SERVER_NAME"
|
||||||
|
ssh-keygen -t ed25519 -N "" -f "$KEY_PATH" -C "$SERVER_NAME"
|
||||||
|
|
||||||
|
# Получение нового пароля
|
||||||
|
if ! $ANONYMOUS; then
|
||||||
|
mkdir -p "$PASS_DIR"
|
||||||
|
NEW_PASS=$(pass generate -c "$PASS_NAME" 16 | tail -n1)
|
||||||
|
echo "$NEW_PASS" | pass insert -m "$PASS_NAME"
|
||||||
|
else
|
||||||
|
NEW_PASS=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Обновление SSH-конфига
|
||||||
|
CONFIG_FILE="$HOME/.ssh/config"
|
||||||
|
touch "$CONFIG_FILE"
|
||||||
|
chmod 600 "$CONFIG_FILE"
|
||||||
|
sed -i "/Host $SERVER_NAME/,/^\s*$/d" "$CONFIG_FILE"
|
||||||
|
cat <<EOF >> "$CONFIG_FILE"
|
||||||
|
|
||||||
|
Host $SERVER_NAME
|
||||||
|
HostName $HOST
|
||||||
|
Port $PORT
|
||||||
|
User $NEW_USER
|
||||||
|
IdentityFile $KEY_PATH
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# --- SSH Настройка сервера ---
|
||||||
|
SSH_COMMANDS=$(cat <<'EOS'
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sudo useradd -m -s /bin/bash -G sudo "$NEW_USER"
|
||||||
|
echo "$NEW_USER:$NEW_PASS" | sudo chpasswd
|
||||||
|
|
||||||
|
sudo mkdir -p "/home/$NEW_USER/.ssh"
|
||||||
|
sudo chmod 700 "/home/$NEW_USER/.ssh"
|
||||||
|
echo "$PUBLIC_KEY" | sudo tee "/home/$NEW_USER/.ssh/authorized_keys" > /dev/null
|
||||||
|
sudo chmod 600 "/home/$NEW_USER/.ssh/authorized_keys"
|
||||||
|
sudo chown -R "$NEW_USER:$NEW_USER" "/home/$NEW_USER/.ssh"
|
||||||
|
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git stow
|
||||||
|
|
||||||
|
if [ "$ANONYMOUS" = "false" ]; then
|
||||||
|
sudo -u "$NEW_USER" git clone https://github.com/goodhumored/dotfiles /home/"$NEW_USER"/dotfiles
|
||||||
|
sudo -u "$NEW_USER" bash -c "cd /home/$NEW_USER/dotfiles && ./init.sh"
|
||||||
|
fi
|
||||||
|
EOS
|
||||||
|
)
|
||||||
|
|
||||||
|
SSHPASS="$ROOT_PASS" sshpass -e ssh -p "$PORT" "$ROOT_USER@$HOST" \
|
||||||
|
env NEW_USER="$NEW_USER" NEW_PASS="$NEW_PASS" PUBLIC_KEY="$(cat "$KEY_PATH.pub")" ANONYMOUS="$ANONYMOUS" bash -c "$SSH_COMMANDS"
|
||||||
|
|
||||||
|
echo "Готово! Новый пользователь: $NEW_USER (SSH: ssh $SERVER_NAME)"
|
Loading…
x
Reference in New Issue
Block a user