commit 5931cb012f7bcbed7935cb69f70e608acda1ff4b Author: Lucas F. Date: Tue Dec 10 19:07:29 2024 -0300 initial diff --git a/.stylua.toml b/.stylua.toml new file mode 100644 index 0000000..ecb6dca --- /dev/null +++ b/.stylua.toml @@ -0,0 +1,6 @@ +column_width = 120 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferDouble" +call_parentheses = "None" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..99cb5dc --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 django-nvim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5ac86e7 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# django.nvim + +Collection of commands for Django development. + +--- + +## Requirements + +- [Neovim (v0.9.0 or latest)](https://github.com/neovim/neovim) + +### Required dependencies + +- [nvim-lua/plenary.nvim](https://github.com/nvim-lua/plenary.nvim) +- [akinsho/toggleterm.nvim](https://github.com/akinsho/toggleterm.nvim) +- [MunifTanjim/nui.nvim](https://github.com/MunifTanjim/nui.nvim) + +--- + +## Installation + +Using [lazy.nvim](https://github.com/folke/lazy.nvim) + +```lua +return { + { + 'https://git.lucasf.dev/public/django.nvim', + config = function() + local django = require("django").setup() + end + } +} +``` + +Using [packer.nvim](https://github.com/wbthomason/packer.nvim) + +```lua +use {'https://git.lucasf.dev/public/django.nvim'} +``` + +Using [vim-plug.nvim](https://github.com/junegunn/vim-plug) + +```lua +Plug 'https://git.lucasf.dev/public/django.nvim' +``` + +--- + +## Usage + +### Default Mappings + +| Mappings | Action | +| ------------ | ------------------------------------- | +| `ja` | Create django app | +| `jc` | Perform manage.py check | +| `je` | Create `.env` file | +| `jh` | Perform manage.py showmigrations | +| `ji` | Perform manage.py migrate | +| `jm` | Perform manage.py makemigrations | +| `jp` | Create python package | +| `jr` | Perform manage.py runserver | +| `jr` | Perform manage.py shell or shell_plus | +| `jy` | Run celery | diff --git a/lua/django/helpers.lua b/lua/django/helpers.lua new file mode 100644 index 0000000..fe162f8 --- /dev/null +++ b/lua/django/helpers.lua @@ -0,0 +1,23 @@ +local plen_status_ok, _ = pcall(require, "plenary") +if not plen_status_ok then return end + +local M = {} +local Path = require "plenary.path" + +function M.get_path(str) return str:match "(.*[/\\])" end + +function M.add_trailing_slash(value) + if value:sub(-1) ~= Path.path.sep then return value .. Path.path.sep end + return value +end + +function M.split(inputstr, sep) + if sep == nil then sep = Path.path.sep end + local t = {} + for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do + table.insert(t, str) + end + return t +end + +return M diff --git a/lua/django/init.lua b/lua/django/init.lua new file mode 100644 index 0000000..842634f --- /dev/null +++ b/lua/django/init.lua @@ -0,0 +1,10 @@ +local mapping = require "django.mappings" + +local M = {} + +function M.setup() + mapping.setup_global_mappings() +end + + +return M diff --git a/lua/django/input.lua b/lua/django/input.lua new file mode 100644 index 0000000..2d0aefa --- /dev/null +++ b/lua/django/input.lua @@ -0,0 +1,399 @@ +local nui,_ = pcall(require, "nui.input") +if not nui then return end + +local M = { fn = {} } +local fn = {} + +local state = { + query = '', + history = nil, + idx_hist = 0, + hooks = {}, + cmdline = {}, + user_opts = {}, + prompt_length = 0, + prompt_content = '' +} + +local defaults = { + cmdline = { + enable_keymaps = true, + smart_history = true, + prompt = ': ' + }, + popup = { + position = { + row = '10%', + col = '50%', + }, + size = { + width = '60%', + }, + border = { + style = 'rounded', + }, + win_options = { + winhighlight = 'Normal:Normal,FloatBorder:FloatBorder', + }, + }, + hooks = { + before_mount = function(input) + end, + after_mount = function(input) + end, + set_keymaps = function(imap, feedkeys) + end + } +} + +M.inp = nil + +fn.check_nvim = function() + if vim.fn.has('nvim-0.7') == 1 then + fn.map = function(lhs, rhs) + vim.keymap.set('i', lhs, rhs, { buffer = M.inp.bufnr, noremap = true }) + end + + fn.nmap = function(lhs, rhs) + vim.keymap.set('n', lhs, rhs, { buffer = M.inp.bufnr, noremap = true }) + end + else + fn.map = function(lhs, rhs) + if type(rhs) == 'string' then + vim.api.nvim_buf_set_keymap(M.inp.bufnr, 'i', lhs, rhs, { noremap = true }) + else + M.inp:map('i', lhs, rhs, { noremap = true }, true) + end + end + + fn.nmap = function(lhs, rhs) + M.inp:map('n', lhs, rhs, { noremap = true }, true) + end + end +end + +M.setup = function(config, input_opts, callback) + config = config or {} + input_opts = input_opts or {} + + state.user_opts = config + + defaults.cmdline.prompt = input_opts.prompt or ": " + + local popup_options = fn.merge(defaults.popup, config.popup) + state.hooks = fn.merge(defaults.hooks, config.hooks) + state.cmdline = fn.merge(defaults.cmdline, config.cmdline) + + state.prompt_length = state.cmdline.prompt:len() + state.prompt_content = state.cmdline.prompt + + return { + popup = popup_options, + input = { + prompt = state.cmdline.prompt, + default_value = input_opts.default_value, + on_change = fn.on_change(), + on_close = function() fn.reset_history() end, + on_submit = callback + } + } +end + +M.open = function(opts, callback) + local ui = M.setup(state.user_opts, opts, callback) + fn.check_nvim() + + M.inp = require('nui.input')(ui.popup, ui.input) + state.hooks.before_mount(M.inp) + + M.inp:mount() + vim.bo.omnifunc = 'v:lua._fine_cmdline_omnifunc' + + if state.cmdline.enable_keymaps then + fn.keymaps() + end + + if vim.fn.has('nvim-0.7') == 0 then + fn.map('', function() fn.prompt_backspace(state.prompt_length) end) + end + + state.hooks.set_keymaps(fn.map, fn.feedkeys) + state.hooks.after_mount(M.inp) +end + +fn.on_change = function() + local prev_hist_idx = 0 + return function(value) + if prev_hist_idx == state.idx_hist then + state.query = value + return + end + if value == '' then + return + end + prev_hist_idx = state.idx_hist + end +end + +fn.keymaps = function() + fn.map('', M.fn.close) + fn.map('', M.fn.close) + + fn.nmap('', M.fn.close) + fn.nmap('', M.fn.close) + + fn.map('', M.fn.complete_or_next_item) + fn.map('', M.fn.stop_complete_or_previous_item) + + if state.cmdline.smart_history then + fn.map('', M.fn.up_search_history) + fn.map('', M.fn.down_search_history) + else + fn.map('', M.fn.up_history) + fn.map('', M.fn.down_history) + end +end + +M.fn.close = function() + if vim.fn.pumvisible() == 1 then + fn.feedkeys('') + else + fn.feedkeys('') + vim.defer_fn(function() + local ok = pcall(M.inp.input_props.on_close) + if not ok then + pcall(vim.api.nvim_win_close, M.inp.winid, true) + pcall(vim.api.nvim_buf_delete, M.inp.bufnr, { force = true }) + end + end, 3) + end +end + +M.fn.up_search_history = function() + if vim.fn.pumvisible() == 1 then return end + + local prompt = state.prompt_length + local line = vim.fn.getline('.') + local user_input = line:sub(prompt + 1, vim.fn.col('.')) + + if line:len() == prompt then + M.fn.up_history() + return + end + + fn.cmd_history() + local idx = state.idx_hist == 0 and 1 or (state.idx_hist + 1) + + while (state.history[idx]) do + local cmd = state.history[idx] + + if vim.startswith(cmd, state.query) then + state.idx_hist = idx + fn.replace_line(cmd) + return + end + + idx = idx + 1 + end + + state.idx_hist = 1 + if user_input ~= state.query then + fn.replace_line(state.query) + end +end + +M.fn.down_search_history = function() + if vim.fn.pumvisible() == 1 then return end + + local prompt = state.prompt_length + local line = vim.fn.getline('.') + local user_input = line:sub(prompt + 1, vim.fn.col('.')) + + if line:len() == prompt then + M.fn.down_history() + return + end + + fn.cmd_history() + local idx = state.idx_hist == 0 and #state.history or (state.idx_hist - 1) + + while (state.history[idx]) do + local cmd = state.history[idx] + + if vim.startswith(cmd, state.query) then + state.idx_hist = idx + fn.replace_line(cmd) + return + end + + idx = idx - 1 + end + + state.idx_hist = #state.history + if user_input ~= state.query then + fn.replace_line(state.query) + end +end + +M.fn.up_history = function() + if vim.fn.pumvisible() == 1 then return end + + fn.cmd_history() + state.idx_hist = state.idx_hist + 1 + local cmd = state.history[state.idx_hist] + + if not cmd then + state.idx_hist = 0 + return + end + + fn.replace_line(cmd) +end + +M.fn.down_history = function() + if vim.fn.pumvisible() == 1 then return end + + fn.cmd_history() + state.idx_hist = state.idx_hist - 1 + local cmd = state.history[state.idx_hist] + + if not cmd then + state.idx_hist = 0 + return + end + + fn.replace_line(cmd) +end + +M.fn.complete_or_next_item = function() + state.uses_completion = true + if vim.fn.pumvisible() == 1 then + fn.feedkeys('') + else + fn.feedkeys('') + end +end + +M.fn.stop_complete_or_previous_item = function() + if vim.fn.pumvisible() == 1 then + fn.feedkeys('') + else + fn.feedkeys('') + end +end + +M.fn.next_item = function() + if vim.fn.pumvisible() == 1 then + fn.feedkeys('') + end +end + +M.fn.previous_item = function() + if vim.fn.pumvisible() == 1 then + fn.feedkeys('') + end +end + +M.omnifunc = function(start, base) + local prompt_length = state.prompt_length + local line = vim.fn.getline('.') + local input = line:sub(prompt_length + 1) + + if start == 1 then + local split = vim.split(input, ' ') + local last_word = split[#split] + local len = #line - #last_word + + for i = #split - 1, 1, -1 do + local word = split[i] + if vim.endswith(word, [[\\]]) then + break + elseif vim.endswith(word, [[\]]) then + len = len - #word - 1 + else + break + end + end + + return len + end + + return vim.api.nvim_buf_call(vim.fn.bufnr('#'), function() + return vim.fn.getcompletion(input .. base, 'file') + end) +end + +fn.replace_line = function(cmd) + vim.cmd('normal! V"_c') + vim.api.nvim_buf_set_lines( + M.inp.bufnr, + vim.fn.line('.') - 1, + vim.fn.line('.'), + true, + { state.prompt_content .. cmd } + ) + + vim.api.nvim_win_set_cursor( + M.inp.winid, + { vim.fn.line('$'), vim.fn.getline('.'):len() } + ) +end + +fn.cmd_history = function() + if state.history then return end + + local history_string = vim.fn.execute('history cmd') + local history_list = vim.split(history_string, '\n') + + local results = {} + for i = #history_list, 3, -1 do + local item = history_list[i] + local _, finish = string.find(item, '%d+ +') + table.insert(results, string.sub(item, finish + 1)) + end + + state.history = results +end + +fn.reset_history = function() + state.idx_hist = 0 + state.history = nil + state.query = '' +end + +fn.merge = function(defaults, override) + return vim.tbl_deep_extend( + 'force', + {}, + defaults, + override or {} + ) +end + +fn.feedkeys = function(keys) + vim.api.nvim_feedkeys( + vim.api.nvim_replace_termcodes(keys, true, true, true), + 'n', + true + ) +end + +fn.prompt_backspace = function(prompt) + local cursor = vim.api.nvim_win_get_cursor(0) + local line = cursor[1] + local col = cursor[2] + + if col ~= prompt then + local completion = vim.fn.pumvisible() == 1 and state.uses_completion + if completion then fn.feedkeys('') end + + vim.api.nvim_buf_set_text(0, line - 1, col - 1, line - 1, col, { '' }) + vim.api.nvim_win_set_cursor(0, { line, col - 1 }) + + if completion then fn.feedkeys('') end + end +end + +_fine_cmdline_omnifunc = M.omnifunc + +return M diff --git a/lua/django/lazy.lua b/lua/django/lazy.lua new file mode 100644 index 0000000..65a5757 --- /dev/null +++ b/lua/django/lazy.lua @@ -0,0 +1,17 @@ +local lazy = {} + +--- Require on index. +--- +--- Will only require the module after the first index of a module. +--- Only works for modules that export a table. +---@param require_path string +---@return table +lazy.require = function(require_path) + return setmetatable({}, { + __index = function(_, key) return require(require_path)[key] end, + + __newindex = function(_, key, value) require(require_path)[key] = value end, + }) +end + +return lazy diff --git a/lua/django/mappings.lua b/lua/django/mappings.lua new file mode 100644 index 0000000..b35eab4 --- /dev/null +++ b/lua/django/mappings.lua @@ -0,0 +1,94 @@ +local django = require "django.utils" + +local mappings = { + n = { + ["j"] = { desc = " Django" }, + ["ja"] = { + function() + django.create_app() + end, + desc = "create app", + }, + ["jp"] = { + function() + django.create_package() + end, + desc = "create python package", + }, + ["js"] = { + function() + django.manage_shell_plus(true) + end, + desc = "shell plus", + }, + ["je"] = { + function() + django.create_env_file() + end, + desc = "create env file", + }, + + ["jr"] = { + function() + django.manage_run_server "make run" + end, + desc = "run server", + }, + ["jm"] = { + function() + django.manage_make_migrations() + end, + desc = "make migrations", + }, + ["ji"] = { + function() + django.manage_migrate() + end, + desc = "migrate", + }, + ["jc"] = { + function() + django.check() + end, + desc = "check", + }, + ["jh"] = { + function() + django.show_migrations() + end, + desc = "show migrations", + }, + ["jy"] = { + function() + django.run_celery() + end, + desc = "run celery", + }, + }, +} + +local M = {} + +local function key_map(mod, lhs, rhs, opts) + if type(lhs) == "string" then + vim.keymap.set(mod, lhs, rhs, opts) + elseif type(lhs) == "table" then + for _, key in pairs(lhs) do + vim.keymap.set(mod, key, rhs, opts) + end + end +end + +function M.setup_global_mappings() + if mappings then + for k, v in pairs(mappings.n) do + if unpack(v) == nil then + key_map("n", k, "", { desc = v.desc }) + else + key_map("n", k, unpack(v), { desc = v.desc }) + end + end + end +end + +return M diff --git a/lua/django/utils.lua b/lua/django/utils.lua new file mode 100644 index 0000000..916a01d --- /dev/null +++ b/lua/django/utils.lua @@ -0,0 +1,267 @@ +local plen_status_ok, _ = pcall(require, "plenary") +if not plen_status_ok then + return +end + +local term_stat_ok, _ = pcall(require, "toggleterm.terminal") +if not term_stat_ok then + return +end + +local inp = require "django.input" +local helpers = require "django.helpers" +local toggleterm = require "toggleterm" +local terms = require "toggleterm.terminal" + +local CHARS = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)" + +local function generate_secret_key() + local chars = {} + for x in CHARS:gmatch "[a-zA-Z0-9!@#$%^&*(-_=+)]" do + table.insert(chars, x) + end + local key = "" + math.randomseed(os.time()) + for _ = 1, 50 do + key = key .. chars[math.random(1, #chars)] + end + return key +end + +local M = {} + +local Path = require "plenary.path" + +local env_opts = { + secret_key = generate_secret_key(), + allowed_hosts = { "localhost", "10.0.2.2", "127.0.0.1" }, + local_ip = "", + debug = "True", + database = { + user = "postgres", + password = "postgres", + dbname = "db", + port = "5433", + address = "127.0.0.1", + }, + admin = { + username = "admin", + email = "adm@email.com", + password = "", + }, + email = { + host = "", + port = "587", + host_user = "", + host_password = "", + use_tls = "True", + default_from_email = "", + }, + celery = { + result_backend = "django-db", + broker_url = "redis://localhost:6379", + accept_content = "application/json", + result_serializer = "json", + task_serializer = "json", + timezone = "America/Sao_Paulo", + task_time_limit = "30 * 60", + }, +} + +M.title = "Django.nvim" + +local function execute_command(cmd, args) + local ok, err = pcall(cmd, args) + ---@diagnostic disable-next-line: param-type-mismatch + if not ok then + pcall(vim.notify, err, vim.log.levels.ERROR) + end +end + +local function setup_opts(opts) + vim.validate { opts = { opts, "table", true } } + opts = vim.tbl_deep_extend("force", env_opts, opts or {}) + + vim.validate { + secret_key = { opts.secret_key, "string" }, + allowed_hosts = { opts.allowed_hosts, "table" }, + database = { opts.database, "table" }, + admin = { opts.admin, "table" }, + email = { opts.email, "table" }, + celery = { opts.celery, "table" }, + } + return opts +end + +local function file_exists(name) + local f = io.open(name, "r") + if f ~= nil then + io.close(f) + return true + else + return false + end +end + +local function create_template_static_dirs(name, dir) + execute_command(os.execute, "mkdir -p " .. dir .. "/static/" .. name .. "/css") + execute_command(os.execute, "mkdir -p " .. dir .. "/static/" .. name .. "/img") + execute_command(os.execute, "mkdir -p " .. dir .. "/static/" .. name .. "/js") + execute_command(os.execute, "mkdir -p " .. dir .. "/templates/" .. name) +end + +local function get_app_name(path) + local name = helpers.split(helpers.add_trailing_slash(path)) + return name[#name] +end + +local function check_app(path) + return vim.loop.fs_stat(helpers.add_trailing_slash(path) .. "apps.py") ~= nil +end + +local function get_module_name(path) + return path:gsub(Path.path.sep, ".") +end + +local function perform_create_app(value) + local appname = get_app_name(value) + if appname then + if vim.loop.fs_stat(value) == nil then + execute_command(os.execute, "mkdir " .. value) + end + if check_app(value) == true then + vim.notify("This app already exists", vim.log.levels.ERROR, { title = M.title }) + return + end + execute_command(os.execute, "./manage.py startapp " .. appname .. " " .. value) + if check_app(value) == true then + create_template_static_dirs(value, value) + execute_command( + os.execute, + "echo -e \"from django.urls import path\n\napp_name = '" + .. appname + .. "'\n\nurlpatterns = []\" > " + .. value + .. "/urls.py" + ) + execute_command( + os.execute, + 'echo -e " internal_app = True" >> ' .. helpers.add_trailing_slash(value) .. "apps.py" + ) + local cmd = string.format( + 'sed -i "s/"%s"/"%s"/" %s', + appname, + get_module_name(value), + helpers.add_trailing_slash(value) .. "apps.py" + ) + os.execute(cmd) + end + vim.notify("App " .. value .. " created!", vim.log.levels.INFO, { title = M.title .. " - startapp" }) + end +end + +local function perform_create_package(value) + if vim.loop.fs_stat(value) == nil then + execute_command(os.execute, "mkdir -p " .. value) + execute_command(os.execute, "touch " .. helpers.add_trailing_slash(value) .. "__init__.py") + vim.notify("Package " .. value .. " created!", vim.log.levels.INFO, { title = M.title .. " - create package" }) + end +end + +local function env_ip(ip) + if #ip > 0 then + return ", " .. ip + end + return ip +end + +function M.create_app() + inp.open({ prompt = "create app: " }, perform_create_app) +end + +function M.create_package() + inp.open({ prompt = "create package: " }, perform_create_package) +end + +function M.create_env_file(opts) + local opts = setup_opts(opts) + + if file_exists ".env" then + vim.notify("File .env already exists", vim.log.levels.WARN, { title = "Create env file" }) + return + end + + local env_file = io.open(".env", "w") + local env_text = [[ +SECRET_KEY=']] .. opts.secret_key .. "'\n" .. "ALLOWED_HOSTS=localhost, 10.0.2.2, 127.0.0.1" .. env_ip(opts.local_ip) .. "\n" .. "DEBUG=" .. opts.debug .. "\n\n" .. "DATABASE_URL=postgres://" .. opts.database.user .. ":" .. opts.database.password .. "@" .. opts.database.address .. ":" .. opts.database.port .. "/" .. opts.database.dbname .. "\n\n" .. "DB_USER=\n" .. "DB_PASSWORD=\n" .. "DB_HOST=\n" .. "DB_PORT=\n" .. "\n" .. "ADMIN_USERNAME=" .. opts.admin.username .. "\n" .. "ADMIN_EMAIL=" .. opts.admin.email .. "\n" .. "ADMIN_PASSWORD=" .. opts.admin.password .. "\n\n" .. "EMAIL_HOST=" .. opts.email.host .. "\n" .. "EMAIL_PORT=" .. opts.email.port .. "\n" .. "EMAIL_HOST_USER=" .. opts.email.host_user .. "\n" .. "EMAIL_HOST_PASSWORD=" .. opts.email.host_password .. "\n" .. "EMAIL_USE_TLS=" .. opts.email.use_tls .. "\n" .. "DEFAULT_FROM_EMAIL=" .. opts.email.default_from_email .. "\n\n" .. "CELERY_RESULT_BACKEND=" .. opts.celery.result_backend .. "\n" .. "CELERY_BROKER_URL=" .. opts.celery.broker_url .. "\n" .. "CELERY_ACCEPT_CONTENT=" .. opts.celery.accept_content .. "\n" .. "CELERY_RESULT_SERIALIZER=" .. opts.celery.result_serializer .. "\n" .. "CELERY_TASK_SERIALIZER=" .. opts.celery.task_serializer .. "\n" .. "CELERY_TIMEZONE=" .. opts.celery.timezone .. "\n" .. "CELERY_TASK_TIME_LIMIT=" .. opts.celery.task_time_limit .. "\n\n" .. "AWS_ACCESS_KEY_ID=\n" .. "AWS_SECRET_ACCESS_KEY=\n" .. "AWS_STORAGE_BUCKET_NAME=\n" .. "AWS_S3_ENDPOINT_URL=\n" .. "AWS_LOCATION=\n" + + if env_file ~= nil then + env_file:write(env_text) + env_file:close() + end +end + +function M.manage_run_server(custom_command) + local term_num = 2 + local term = terms.get(term_num, true) + + if not file_exists "Makefile" then + if not file_exists "makefile" then + custom_command = "./manage.py runserver 0.0.0.0:8000" + end + end + + if term then + term:toggle() + else + toggleterm.exec(custom_command, term_num, 100, ".", "float", "runserver") + end +end + +function M.manage_shell_plus(is_plus) + local term_num = 10 + local term = terms.get(term_num, true) + + local cmd = "./manage.py shell" + if is_plus then + cmd = "./manage.py shell_plus" + end + + if term then + term:toggle() + else + toggleterm.exec(cmd, term_num, 100, ".", "float", "shell_plus", true) + end +end + +function M.manage_make_migrations() + local term_num = 3 + toggleterm.exec("./manage.py makemigrations", term_num, 100, ".", "float", "make_migrations", false) +end + +function M.manage_migrate() + local term_num = 4 + toggleterm.exec("./manage.py migrate", term_num, 100, ".", "float", "migrate", false) +end + +function M.check() + local term_num = 5 + toggleterm.exec("./manage.py check", term_num, 100, ".", "float", "check", false) +end + +function M.show_migrations() + local term_num = 6 + toggleterm.exec("./manage.py showmigrations", term_num, 100, ".", "float", "showmigrations", false) +end + +function M.run_celery() + local term_num = 7 + local term = terms.get(term_num, true) + if term then + term:toggle() + else + toggleterm.exec("make run_celery", term_num, 100, ".", "float", "run_celery", false) + end +end + +return M