refactor(nvim): streamline Neovim configuration and plugin management
This commit is contained in:
1 parent
06e0bab7dd
commit
bdf8ad1bb0
27 files changed
+1797
-476
No files matched your search
@@ -0,0 +1,182 @@
|
||||
# Code Templates
|
||||
|
||||
Essential templates for modern development with Cosmos SDK, Protobuf, and Vite+Cloudflare.
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### Quick Access
|
||||
- Press `<C-a><C-t>` to open the template picker
|
||||
- Or use `:TemplateSnacks` command
|
||||
|
||||
### Template Variables
|
||||
|
||||
Templates support the following placeholders:
|
||||
|
||||
- `{{_date_}}` - Current date and time
|
||||
- `{{_cursor_}}` - Cursor position after insertion
|
||||
- `{{_file_name_}}` - Current file name (without extension)
|
||||
- `{{_camel_case_file_}}` - File name converted to CamelCase
|
||||
- `{{_upper_file_}}` - File name in UPPERCASE
|
||||
- `{{_author_}}` - Author name (configured in plugin)
|
||||
- `{{_email_}}` - Email address (configured in plugin)
|
||||
- `{{_variable_}}` - Prompts for custom variable name
|
||||
- `{{_lua:<expr>_}}` - Execute Lua expression
|
||||
|
||||
## 📁 Available Templates
|
||||
|
||||
### Cosmos SDK (Go) - `/cosmos`
|
||||
|
||||
#### `keeper.go.tpl`
|
||||
Creates a Cosmos SDK keeper with store management and parameter store.
|
||||
|
||||
**Use for:** Module keeper implementation
|
||||
**Variables:** Uses `{{_file_name_}}` for module name
|
||||
|
||||
#### `msg_server.go.tpl`
|
||||
Creates a message server implementation for handling transactions.
|
||||
|
||||
**Use for:** Transaction message handlers
|
||||
**Variables:** `{{_variable_}}` for the message type name
|
||||
|
||||
#### `query_server.go.tpl`
|
||||
Creates a query server implementation for handling read queries.
|
||||
|
||||
**Use for:** Query handlers for module state
|
||||
**Variables:** `{{_variable_}}` for the query method name
|
||||
|
||||
#### `handler.go.tpl`
|
||||
Creates a message handler router for the module.
|
||||
|
||||
**Use for:** Main message routing logic
|
||||
|
||||
### Protobuf - `/proto`
|
||||
|
||||
#### `message.proto.tpl`
|
||||
Creates a basic protobuf message definition.
|
||||
|
||||
**Use for:** Data structures and types
|
||||
**Variables:** `{{_variable_}}` for the message name
|
||||
|
||||
#### `tx.proto.tpl`
|
||||
Creates a transaction message service with RPC definitions.
|
||||
|
||||
**Use for:** Transaction (Msg) service definitions
|
||||
**Variables:** `{{_variable_}}` for the transaction method name
|
||||
|
||||
#### `query.proto.tpl`
|
||||
Creates a query service with gRPC and HTTP annotations.
|
||||
|
||||
**Use for:** Query service definitions with REST endpoints
|
||||
**Variables:** `{{_variable_}}` for the query method name
|
||||
|
||||
### Vite + Cloudflare + TanStack - `/vite`
|
||||
|
||||
#### `worker.ts.tpl`
|
||||
Creates a Cloudflare Worker with proper TypeScript types.
|
||||
|
||||
**Use for:** Cloudflare Worker scripts
|
||||
**File type:** TypeScript
|
||||
|
||||
#### `pages-function.ts.tpl`
|
||||
Creates a Cloudflare Pages Function.
|
||||
|
||||
**Use for:** Cloudflare Pages API routes
|
||||
**File type:** TypeScript
|
||||
|
||||
#### `page.tsx.tpl`
|
||||
Creates a TanStack Router page component.
|
||||
|
||||
**Use for:** Full page routes with TanStack Router
|
||||
**File type:** TypeScript React
|
||||
|
||||
#### `component.tsx.tpl`
|
||||
Creates a memoized React component with TypeScript.
|
||||
|
||||
**Use for:** Reusable React components
|
||||
**File type:** TypeScript React
|
||||
|
||||
#### `hook.ts.tpl`
|
||||
Creates a custom React hook with TypeScript.
|
||||
|
||||
**Use for:** Reusable React hooks
|
||||
**File type:** TypeScript
|
||||
|
||||
#### `api.ts.tpl`
|
||||
Creates a TanStack Query API client with CRUD operations.
|
||||
|
||||
**Use for:** API integration with TanStack Query
|
||||
**File type:** TypeScript
|
||||
**Includes:** Query keys, fetch functions, and hooks
|
||||
|
||||
## 💡 Examples
|
||||
|
||||
### Creating a Cosmos SDK Message Server
|
||||
|
||||
1. Create/open a file: `msg_server_create_post.go`
|
||||
2. Press `<C-a><C-t>`
|
||||
3. Select `msg_server.go.tpl`
|
||||
4. Enter variable name when prompted: `CreatePost`
|
||||
5. Template is inserted with all placeholders filled
|
||||
|
||||
### Creating a TanStack Query API
|
||||
|
||||
1. Create/open a file: `posts.ts`
|
||||
2. Press `<C-a><C-t>`
|
||||
3. Select `api.ts.tpl`
|
||||
4. Template creates full API client with:
|
||||
- Query keys
|
||||
- Fetch functions
|
||||
- React hooks for queries and mutations
|
||||
|
||||
### Creating a React Component
|
||||
|
||||
1. Create/open a file: `user_card.tsx`
|
||||
2. Press `<C-a><C-t>`
|
||||
3. Select `component.tsx.tpl`
|
||||
4. Component created with name `UserCard` (auto-converted to CamelCase)
|
||||
|
||||
## 🎨 Customization
|
||||
|
||||
### Adding Your Own Templates
|
||||
|
||||
1. Create a new `.tpl` file in the templates directory
|
||||
2. Add filetype marker as first line: `;; <filetype>`
|
||||
3. Use template variables as needed
|
||||
4. Save and use with `<C-a><C-t>`
|
||||
|
||||
Example:
|
||||
```typescript
|
||||
;; typescript
|
||||
/**
|
||||
* {{_file_name_}}
|
||||
* @author {{_author_}}
|
||||
*/
|
||||
|
||||
export const {{_camel_case_file_}} = {{_cursor_}}
|
||||
```
|
||||
|
||||
### Template Organization
|
||||
|
||||
- Use subdirectories to organize templates by category
|
||||
- Template picker shows category in selection: `[category] filename`
|
||||
- Templates are filtered by current file type automatically
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
Edit template configuration in `lua/plugins/template.lua`:
|
||||
|
||||
```lua
|
||||
template.setup {
|
||||
temp_dir = vim.fn.stdpath "config" .. "/templates",
|
||||
author = "Your Name",
|
||||
email = "your.email@example.com",
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 Resources
|
||||
|
||||
- [template.nvim GitHub](https://github.com/glepnir/template.nvim)
|
||||
- [Cosmos SDK Docs](https://docs.cosmos.network/)
|
||||
- [Cloudflare Workers Docs](https://developers.cloudflare.com/workers/)
|
||||
- [TanStack Router](https://tanstack.com/router)
|
||||
- [TanStack Query](https://tanstack.com/query)
|
||||
@@ -0,0 +1,27 @@
|
||||
;; go
|
||||
package {{_file_name_}}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||
"github.com/sonr-io/sonr/x/{{_file_name_}}/keeper"
|
||||
"github.com/sonr-io/sonr/x/{{_file_name_}}/types"
|
||||
)
|
||||
|
||||
// NewHandler returns a handler for {{_file_name_}} module messages
|
||||
func NewHandler(k keeper.Keeper) sdk.Handler {
|
||||
msgServer := keeper.NewMsgServerImpl(k)
|
||||
|
||||
return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
|
||||
ctx = ctx.WithEventManager(sdk.NewEventManager())
|
||||
|
||||
switch msg := msg.(type) {
|
||||
{{_cursor_}}
|
||||
default:
|
||||
errMsg := fmt.Sprintf("unrecognized %s message type: %T", types.ModuleName, msg)
|
||||
return nil, sdkerrors.Wrap(sdkerrors.ErrUnknownRequest, errMsg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
;; go
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/sonr-io/sonr/x/{{_file_name_}}/types"
|
||||
)
|
||||
|
||||
type Keeper struct {
|
||||
storeKey sdk.StoreKey
|
||||
cdc codec.BinaryCodec
|
||||
paramstore paramtypes.Subspace
|
||||
}
|
||||
|
||||
func NewKeeper(
|
||||
cdc codec.BinaryCodec,
|
||||
storeKey sdk.StoreKey,
|
||||
ps paramtypes.Subspace,
|
||||
) *Keeper {
|
||||
// set KeyTable if it has not already been set
|
||||
if !ps.HasKeyTable() {
|
||||
ps = ps.WithKeyTable(types.ParamKeyTable())
|
||||
}
|
||||
|
||||
return &Keeper{
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
paramstore: ps,
|
||||
}
|
||||
}
|
||||
|
||||
// Logger returns a module-specific logger.
|
||||
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
|
||||
return ctx.Logger().With("module", "x/{{_file_name_}}")
|
||||
}
|
||||
|
||||
{{_cursor_}}
|
||||
@@ -0,0 +1,43 @@
|
||||
;; go
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/sonr-io/sonr/x/{{_file_name_}}/types"
|
||||
)
|
||||
|
||||
type msgServer struct {
|
||||
Keeper
|
||||
}
|
||||
|
||||
// NewMsgServerImpl returns an implementation of the {{_camel_case_file_}} MsgServer interface
|
||||
// for the provided Keeper.
|
||||
func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
||||
return &msgServer{Keeper: keeper}
|
||||
}
|
||||
|
||||
var _ types.MsgServer = msgServer{}
|
||||
|
||||
// {{_variable_}} implements types.MsgServer
|
||||
func (k msgServer) {{_variable_}}(goCtx context.Context, msg *types.Msg{{_variable_}}) (*types.Msg{{_variable_}}Response, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
// Validate message
|
||||
if err := msg.ValidateBasic(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
{{_cursor_}}
|
||||
|
||||
// Emit event
|
||||
ctx.EventManager().EmitEvent(
|
||||
sdk.NewEvent(
|
||||
types.EventType{{_variable_}},
|
||||
sdk.NewAttribute(types.AttributeKeyCreator, msg.Creator),
|
||||
),
|
||||
)
|
||||
|
||||
return &types.Msg{{_variable_}}Response{}, nil
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
;; go
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/sonr-io/sonr/x/{{_file_name_}}/types"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type queryServer struct {
|
||||
Keeper
|
||||
}
|
||||
|
||||
// NewQueryServerImpl returns an implementation of the {{_camel_case_file_}} QueryServer interface
|
||||
// for the provided Keeper.
|
||||
func NewQueryServerImpl(keeper Keeper) types.QueryServer {
|
||||
return &queryServer{Keeper: keeper}
|
||||
}
|
||||
|
||||
var _ types.QueryServer = queryServer{}
|
||||
|
||||
// {{_variable_}} implements types.QueryServer
|
||||
func (k queryServer) {{_variable_}}(goCtx context.Context, req *types.Query{{_variable_}}Request) (*types.Query{{_variable_}}Response, error) {
|
||||
if req == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "invalid request")
|
||||
}
|
||||
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
{{_cursor_}}
|
||||
|
||||
return &types.Query{{_variable_}}Response{}, nil
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
;; proto
|
||||
syntax = "proto3";
|
||||
package sonr.{{_file_name_}}.v1;
|
||||
|
||||
option go_package = "github.com/sonr-io/sonr/x/{{_file_name_}}/types";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "amino/amino.proto";
|
||||
|
||||
// {{_variable_}} defines the {{_variable_}} message
|
||||
message {{_variable_}} {
|
||||
option (gogoproto.equal) = true;
|
||||
option (amino.name) = "sonr/{{_file_name_}}/{{_variable_}}";
|
||||
|
||||
{{_cursor_}}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
;; proto
|
||||
syntax = "proto3";
|
||||
package sonr.{{_file_name_}}.v1;
|
||||
|
||||
option go_package = "github.com/sonr-io/sonr/x/{{_file_name_}}/types";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "google/api/annotations.proto";
|
||||
import "cosmos/base/query/v1beta1/pagination.proto";
|
||||
import "cosmos/query/v1/query.proto";
|
||||
|
||||
// Query defines the gRPC querier service
|
||||
service Query {
|
||||
// {{_variable_}} queries the {{_variable_}}
|
||||
rpc {{_variable_}}(Query{{_variable_}}Request) returns (Query{{_variable_}}Response) {
|
||||
option (cosmos.query.v1.module_query_safe) = true;
|
||||
option (google.api.http).get = "/sonr/{{_file_name_}}/v1/{{_variable_}}";
|
||||
}
|
||||
}
|
||||
|
||||
// Query{{_variable_}}Request is the request type for the Query/{{_variable_}} RPC method
|
||||
message Query{{_variable_}}Request {
|
||||
{{_cursor_}}
|
||||
}
|
||||
|
||||
// Query{{_variable_}}Response is the response type for the Query/{{_variable_}} RPC method
|
||||
message Query{{_variable_}}Response {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
;; proto
|
||||
syntax = "proto3";
|
||||
package sonr.{{_file_name_}}.v1;
|
||||
|
||||
option go_package = "github.com/sonr-io/sonr/x/{{_file_name_}}/types";
|
||||
|
||||
import "gogoproto/gogo.proto";
|
||||
import "cosmos_proto/cosmos.proto";
|
||||
import "cosmos/msg/v1/msg.proto";
|
||||
import "amino/amino.proto";
|
||||
|
||||
// Msg defines the {{_file_name_}} Msg service
|
||||
service Msg {
|
||||
option (cosmos.msg.v1.service) = true;
|
||||
|
||||
// {{_variable_}} defines the {{_variable_}} RPC method
|
||||
rpc {{_variable_}}(Msg{{_variable_}}) returns (Msg{{_variable_}}Response);
|
||||
}
|
||||
|
||||
// Msg{{_variable_}} defines the {{_variable_}} message
|
||||
message Msg{{_variable_}} {
|
||||
option (cosmos.msg.v1.signer) = "creator";
|
||||
option (amino.name) = "sonr/{{_file_name_}}/{{_variable_}}";
|
||||
|
||||
string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
{{_cursor_}}
|
||||
}
|
||||
|
||||
// Msg{{_variable_}}Response defines the {{_variable_}} response
|
||||
message Msg{{_variable_}}Response {}
|
||||
@@ -0,0 +1,58 @@
|
||||
;; typescript
|
||||
/**
|
||||
* {{_camel_case_file_}} API Client
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
|
||||
// API Types
|
||||
interface {{_camel_case_file_}}Data {
|
||||
{{_cursor_}}
|
||||
}
|
||||
|
||||
// Query Keys
|
||||
export const {{_file_name_}}Keys = {
|
||||
all: ['{{_file_name_}}'] as const,
|
||||
lists: () => [...{{_file_name_}}Keys.all, 'list'] as const,
|
||||
list: (filters: string) => [...{{_file_name_}}Keys.lists(), { filters }] as const,
|
||||
details: () => [...{{_file_name_}}Keys.all, 'detail'] as const,
|
||||
detail: (id: string) => [...{{_file_name_}}Keys.details(), id] as const,
|
||||
}
|
||||
|
||||
// API Functions
|
||||
async function fetch{{_camel_case_file_}}(id: string): Promise<{{_camel_case_file_}}Data> {
|
||||
const response = await fetch(`/api/{{_file_name_}}/${id}`)
|
||||
if (!response.ok) throw new Error('Failed to fetch {{_file_name_}}')
|
||||
return response.json()
|
||||
}
|
||||
|
||||
async function create{{_camel_case_file_}}(data: Partial<{{_camel_case_file_}}Data>): Promise<{{_camel_case_file_}}Data> {
|
||||
const response = await fetch('/api/{{_file_name_}}', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
if (!response.ok) throw new Error('Failed to create {{_file_name_}}')
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Hooks
|
||||
export function use{{_camel_case_file_}}(id: string) {
|
||||
return useQuery({
|
||||
queryKey: {{_file_name_}}Keys.detail(id),
|
||||
queryFn: () => fetch{{_camel_case_file_}}(id),
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreate{{_camel_case_file_}}() {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
return useMutation({
|
||||
mutationFn: create{{_camel_case_file_}},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: {{_file_name_}}Keys.lists() })
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
;; typescriptreact
|
||||
/**
|
||||
* {{_camel_case_file_}} Component
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
import { memo } from 'react'
|
||||
|
||||
interface {{_camel_case_file_}}Props {
|
||||
{{_cursor_}}
|
||||
}
|
||||
|
||||
export const {{_camel_case_file_}} = memo<{{_camel_case_file_}}Props>(({ }) => {
|
||||
return (
|
||||
<div>
|
||||
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
{{_camel_case_file_}}.displayName = '{{_camel_case_file_}}'
|
||||
@@ -0,0 +1,24 @@
|
||||
;; typescript
|
||||
/**
|
||||
* {{_camel_case_file_}} Hook
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
interface Use{{_camel_case_file_}}Options {
|
||||
{{_cursor_}}
|
||||
}
|
||||
|
||||
export function use{{_camel_case_file_}}(options?: Use{{_camel_case_file_}}Options) {
|
||||
const [data, setData] = useState()
|
||||
|
||||
useEffect(() => {
|
||||
// Hook logic here
|
||||
}, [])
|
||||
|
||||
return {
|
||||
data,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
;; typescriptreact
|
||||
/**
|
||||
* {{_camel_case_file_}} Page Component
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/{{_file_name_}}')({
|
||||
component: {{_camel_case_file_}}Page,
|
||||
})
|
||||
|
||||
function {{_camel_case_file_}}Page() {
|
||||
{{_cursor_}}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<h1 className="text-3xl font-bold mb-6">{{_camel_case_file_}}</h1>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
;; typescript
|
||||
/**
|
||||
* Cloudflare Pages Function - {{_file_name_}}
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
interface Env {
|
||||
// Add your environment bindings here
|
||||
}
|
||||
|
||||
export const onRequest: PagesFunction<Env> = async (context) => {
|
||||
const { request, env, params } = context
|
||||
|
||||
{{_cursor_}}
|
||||
|
||||
return new Response(JSON.stringify({ success: true }), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
;; typescript
|
||||
/**
|
||||
* Cloudflare Worker - {{_file_name_}}
|
||||
* @author {{_author_}}
|
||||
* @created {{_date_}}
|
||||
*/
|
||||
|
||||
export interface Env {
|
||||
// Add your environment bindings here
|
||||
// Example: DB: D1Database
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||
const url = new URL(request.url);
|
||||
|
||||
{{_cursor_}}
|
||||
|
||||
return new Response('Hello World!', {
|
||||
headers: { 'Content-Type': 'text/plain' },
|
||||
});
|
||||
},
|
||||
} satisfies ExportedHandler<Env>;
|
||||
Reference in new issue
Block a user