Skip to content

Commit 1b3a46d

Browse files
committed
Add editor settings UI to code editor
Related to: #9071
1 parent a89c735 commit 1b3a46d

File tree

9 files changed

+79
-25
lines changed

9 files changed

+79
-25
lines changed

modules/templates/helper.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"html"
1010
"html/template"
1111
"net/url"
12+
"path"
1213
"strings"
1314
"time"
1415

@@ -49,6 +50,7 @@ func NewFuncMap() template.FuncMap {
4950

5051
"PathEscape": url.PathEscape,
5152
"PathEscapeSegments": util.PathEscapeSegments,
53+
"PathExt": path.Ext,
5254

5355
// utils
5456
"StringUtils": NewStringUtils,

options/locale/locale_en-US.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ filter.private = Private
163163
no_results_found = No results found.
164164
internal_error_skipped = Internal error occurred but is skipped: %s
165165

166+
characters_spaces = Spaces
167+
characters_tabs = Tabs
168+
text_indent_style = Indent Stype
169+
text_indent_size = Indent Size
170+
text_line_wrap = Wrap
171+
text_line_nowrap = No wrap
172+
text_line_wrap_mode = Line wrap mode
173+
166174
[search]
167175
search = Search...
168176
type_tooltip = Search type

routers/web/repo/cherry_pick.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func CherryPick(ctx *context.Context) {
5656
}
5757
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
5858
ctx.Data["last_commit"] = ctx.Repo.CommitID
59-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
59+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
6060
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL()
6161

6262
ctx.HTML(200, tplCherryPick)
@@ -84,7 +84,7 @@ func CherryPickPost(ctx *context.Context) {
8484
ctx.Data["commit_choice"] = form.CommitChoice
8585
ctx.Data["new_branch_name"] = form.NewBranchName
8686
ctx.Data["last_commit"] = ctx.Repo.CommitID
87-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
87+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
8888
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL()
8989

9090
if ctx.HasError() {

routers/web/repo/editor.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import (
2828
"code.gitea.io/gitea/services/context/upload"
2929
"code.gitea.io/gitea/services/forms"
3030
files_service "code.gitea.io/gitea/services/repository/files"
31+
32+
"github.com/editorconfig/editorconfig-core-go/v2"
3133
)
3234

3335
const (
@@ -191,8 +193,13 @@ func editFile(ctx *context.Context, isNewFile bool) {
191193
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
192194
ctx.Data["last_commit"] = ctx.Repo.CommitID
193195
ctx.Data["PreviewableExtensions"] = strings.Join(markup.PreviewableExtensions(), ",")
194-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
195-
ctx.Data["EditorconfigJson"] = GetEditorConfig(ctx, treePath)
196+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
197+
198+
ecDef := GetEditorConfig(ctx, treePath)
199+
ecBytes, _ := json.Marshal(ecDef)
200+
ctx.Data["EditorconfigJson"] = string(ecBytes)
201+
ctx.Data["EditorconfigIndentStyle"] = ecDef.IndentStyle
202+
ctx.Data["EditorconfigIndentSize"] = ecDef.IndentSize
196203

197204
ctx.Data["IsEditingFileOnly"] = ctx.FormString("return_uri") != ""
198205
ctx.Data["ReturnURI"] = ctx.FormString("return_uri")
@@ -201,16 +208,17 @@ func editFile(ctx *context.Context, isNewFile bool) {
201208
}
202209

203210
// GetEditorConfig returns a editorconfig JSON string for given treePath or "null"
204-
func GetEditorConfig(ctx *context.Context, treePath string) string {
211+
func GetEditorConfig(ctx *context.Context, treePath string) *editorconfig.Definition {
205212
ec, _, err := ctx.Repo.GetEditorconfig()
206213
if err == nil {
207214
def, err := ec.GetDefinitionForFilename(treePath)
208215
if err == nil {
209-
jsonStr, _ := json.Marshal(def)
210-
return string(jsonStr)
216+
return def
217+
} else {
218+
return nil
211219
}
212220
}
213-
return "null"
221+
return nil
214222
}
215223

216224
// EditFile render edit file page
@@ -245,7 +253,7 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
245253
ctx.Data["new_branch_name"] = form.NewBranchName
246254
ctx.Data["last_commit"] = ctx.Repo.CommitID
247255
ctx.Data["PreviewableExtensions"] = strings.Join(markup.PreviewableExtensions(), ",")
248-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
256+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
249257
ctx.Data["EditorconfigJson"] = GetEditorConfig(ctx, form.TreePath)
250258

251259
if ctx.HasError() {

routers/web/repo/patch.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func NewDiffPatch(ctx *context.Context) {
3636
}
3737
ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
3838
ctx.Data["last_commit"] = ctx.Repo.CommitID
39-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
39+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
4040
ctx.Data["BranchLink"] = ctx.Repo.RepoLink + "/src/" + ctx.Repo.RefTypeNameSubURL()
4141

4242
ctx.HTML(200, tplPatchFile)
@@ -59,7 +59,7 @@ func NewDiffPatchPost(ctx *context.Context) {
5959
ctx.Data["commit_choice"] = form.CommitChoice
6060
ctx.Data["new_branch_name"] = form.NewBranchName
6161
ctx.Data["last_commit"] = ctx.Repo.CommitID
62-
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
62+
ctx.Data["LineWrapExtensions"] = setting.Repository.Editor.LineWrapExtensions
6363

6464
if ctx.HasError() {
6565
ctx.HTML(200, tplPatchFile)

templates/repo/editor/edit.tmpl

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,24 @@
3030
</div>
3131
<div class="field">
3232
<div class="ui top attached header">
33-
<div class="ui compact small menu small-menu-items repo-editor-menu">
34-
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.new_file"}}{{else}}{{ctx.Locale.Tr "repo.editor.edit_file"}}{{end}}</a>
35-
<a class="item" data-tab="preview" data-preview-url="{{.Repository.Link}}/markup" data-preview-context-ref="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
36-
{{if not .IsNewFile}}
37-
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
38-
{{end}}
33+
<div class="tw-w-100 tw-flex tw-justify-between tw-flex-col md:tw-flex-row tw-gap-2 tw-items-stretch">
34+
<div class="ui compact small menu small-menu-items repo-editor-menu tw-self-start">
35+
<a class="active item" data-tab="write">{{svg "octicon-code"}} {{if .IsNewFile}}{{ctx.Locale.Tr "repo.editor.new_file"}}{{else}}{{ctx.Locale.Tr "repo.editor.edit_file"}}{{end}}</a>
36+
<a class="item" data-tab="preview" data-preview-url="{{.Repository.Link}}/markup" data-preview-context-ref="{{.RepoLink}}/src/{{.RefTypeNameSubURL}}">{{svg "octicon-eye"}} {{ctx.Locale.Tr "preview"}}</a>
37+
{{if not .IsNewFile}}
38+
<a class="item" data-tab="diff" hx-params="context,content" hx-vals='{"context":"{{.BranchLink}}"}' hx-include="#edit_area" hx-swap="innerHTML" hx-target=".tab[data-tab='diff']" hx-indicator=".tab[data-tab='diff']" hx-post="{{.RepoLink}}/_preview/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">{{svg "octicon-diff"}} {{ctx.Locale.Tr "repo.editor.preview_changes"}}</a>
39+
{{end}}
40+
</div>
41+
<div class="tw-flex tw-gap-3">
42+
{{template "repo/editor/options" .}}
43+
</div>
3944
</div>
4045
</div>
4146
<div class="ui bottom attached segment tw-p-0">
4247
<div class="ui active tab tw-rounded-b" data-tab="write">
4348
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-{{.TreePath}}"
4449
data-previewable-extensions="{{.PreviewableExtensions}}"
45-
data-line-wrap-extensions="{{.LineWrapExtensions}}">{{.FileContent}}</textarea>
50+
data-line-wrap-extensions="{{StringUtils.Join .LineWrapExtensions ","}}">{{.FileContent}}</textarea>
4651
<div class="editor-loading is-loading"></div>
4752
</div>
4853
<div class="ui tab markup tw-px-4 tw-py-3" data-tab="preview">

templates/repo/editor/options.tmpl

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<select class="js-indent-style-select tw-w-auto">
2+
<optgroup label="{{ctx.Locale.Tr "text_indent_style"}}">
3+
<option{{if eq .EditorconfigIndentStyle "space"}} selected{{end}} value="space">{{ctx.Locale.Tr "characters_spaces"}}</option>
4+
<option{{if eq .EditorconfigIndentStyle "tab"}} selected{{end}} value="tab">{{ctx.Locale.Tr "characters_tabs"}}</option>
5+
</optgroup>
6+
</select>
7+
<select class="js-indent-size-select tw-w-auto">
8+
<optgroup label="{{ctx.Locale.Tr "text_indent_size"}}">
9+
<option{{if eq .EditorconfigIndentSize "2"}} selected{{end}} value="2">2</option>
10+
<option{{if eq .EditorconfigIndentSize "4"}} selected{{end}} value="4">4</option>
11+
<option{{if eq .EditorconfigIndentSize "8"}} selected{{end}} value="8">8</option>
12+
</optgroup>
13+
</select>
14+
{{$mode := (Iif (SliceUtils.Contains .LineWrapExtensions (PathExt .TreePath)) "on" "off")}}
15+
<select class="js-line-wrap-select tw-w-auto">
16+
<optgroup label="{{ctx.Locale.Tr "text_line_wrap_mode"}}">
17+
<option{{if eq $mode "on"}} selected{{end}} value="on">{{ctx.Locale.Tr "text_line_wrap"}}</option>
18+
<option{{if eq $mode "off"}} selected{{end}} value="off">{{ctx.Locale.Tr "text_line_nowrap"}}</option>
19+
</optgroup>
20+
</select>

templates/repo/editor/patch.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
<div class="ui active tab segment tw-rounded tw-p-0" data-tab="write">
2929
<textarea id="edit_area" name="content" class="tw-hidden" data-id="repo-{{.Repository.Name}}-patch"
3030
data-context="{{.RepoLink}}"
31-
data-line-wrap-extensions="{{.LineWrapExtensions}}">
31+
data-line-wrap-extensions="{{StringUtils.Join .LineWrapExtensions ","}}">
3232
{{.FileContent}}</textarea>
3333
<div class="editor-loading is-loading"></div>
3434
</div>

web_src/js/features/codeeditor.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const baseOptions: MonacoOpts = {
3838
scrollbar: {horizontalScrollbarSize: 6, verticalScrollbarSize: 6},
3939
scrollBeyondLastLine: false,
4040
automaticLayout: true,
41+
indentSize: 'tabSize',
4142
};
4243

4344
function getEditorconfig(input: HTMLInputElement): EditorConfig | null {
@@ -163,6 +164,20 @@ export async function createMonaco(textarea: HTMLTextAreaElement, filename: stri
163164
textarea.dispatchEvent(new Event('change')); // seems to be needed for jquery-are-you-sure
164165
});
165166

167+
const form = textarea.closest('form');
168+
form.querySelector<HTMLSelectElement>('.js-indent-style-select').addEventListener('change', (e) => {
169+
const insertSpaces = (e.target as HTMLSelectElement).value === 'space';
170+
editor.updateOptions({insertSpaces, useTabStops: !insertSpaces});
171+
});
172+
form.querySelector<HTMLSelectElement>('.js-indent-size-select').addEventListener('change', (e) => {
173+
const tabSize = Number((e.target as HTMLSelectElement).value);
174+
editor.updateOptions({tabSize});
175+
});
176+
form.querySelector<HTMLSelectElement>('.js-line-wrap-select').addEventListener('change', (e) => {
177+
const wordWrap = (e.target as HTMLSelectElement).value as IEditorOptions['wordWrap'];
178+
editor.updateOptions({wordWrap});
179+
});
180+
166181
exportEditor(editor);
167182

168183
const loading = document.querySelector('.editor-loading');
@@ -225,12 +240,8 @@ function getEditorConfigOptions(ec: EditorConfig | null): MonacoOpts {
225240
const opts: MonacoOpts = {};
226241
opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec);
227242

228-
if ('indent_size' in ec) {
229-
opts.indentSize = Number(ec.indent_size);
230-
}
231-
if ('tab_width' in ec) {
232-
opts.tabSize = Number(ec.tab_width) || Number(ec.indent_size);
233-
}
243+
opts.tabSize = Number(ec.tab_width) || Number(ec.indent_size) || 4;
244+
234245
if ('max_line_length' in ec) {
235246
opts.rulers = [Number(ec.max_line_length)];
236247
}

0 commit comments

Comments
 (0)