mirror of
https://github.com/gogs/gogs.git
synced 2026-02-28 17:20:59 +01:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee28fd9255 | ||
|
|
13d492e92a | ||
|
|
e7fd65f0cf | ||
|
|
2eeb0ec9b0 | ||
|
|
b1133c9934 | ||
|
|
991ce42c48 | ||
|
|
10dc330640 | ||
|
|
dfab54d5a2 | ||
|
|
3e22ae3412 | ||
|
|
55b4e77a5e | ||
|
|
ad7ea88923 | ||
|
|
f2884d8e31 | ||
|
|
36a63dd059 | ||
|
|
03ba257ad2 | ||
|
|
fe60ca408b | ||
|
|
0402c803c6 | ||
|
|
29ccf047d8 | ||
|
|
8aa0a76702 | ||
|
|
2d76de2574 | ||
|
|
4d8b905541 | ||
|
|
452aefd025 | ||
|
|
899e799459 | ||
|
|
2295fafb34 | ||
|
|
a562228c5e | ||
|
|
e74630ae3b | ||
|
|
1f2e173a74 | ||
|
|
46e96c008c | ||
|
|
256cd6374a | ||
|
|
57a47bbc05 | ||
|
|
024fcc836b | ||
|
|
250be011c7 | ||
|
|
4e822c1911 | ||
|
|
26d52ceb48 | ||
|
|
d90acacd86 | ||
|
|
69f5308761 | ||
|
|
4b5e09e4d6 | ||
|
|
4f78abe7dc | ||
|
|
e63b2881b1 | ||
|
|
745167d57a | ||
|
|
d7bdc1de8d | ||
|
|
c912494609 | ||
|
|
69dae1ec1c | ||
|
|
cf85e9eb7b |
18
.github/ISSUE_TEMPLATE.md
vendored
18
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,17 +1,19 @@
|
||||
We DO NOT take questions or config/deploy problems on GitHub, please use our forum: https://discuss.gogs.io
|
||||
The issue will be closed without any reasons if it does not satisfy any of following requirements:
|
||||
|
||||
Please take a moment to search that an issue doesn't already exist.
|
||||
1. Please do NOT post questions or config/deploy problems on GitHub, please use our forum: https://discuss.gogs.io
|
||||
2. Please take a moment to search that an issue doesn't already exist.
|
||||
3. Please give all relevant information below for bug reports; incomplete details considered invalid report.
|
||||
|
||||
For bug reports, please give the relevant info:
|
||||
**You MUST delete above content including this line before posting; too lazy to take this action considered invalid report.**
|
||||
|
||||
- Gogs version (or commit ref):
|
||||
- Git version:
|
||||
- Operating system:
|
||||
- Database:
|
||||
- Gogs version (or commit ref):
|
||||
- Git version:
|
||||
- Operating system:
|
||||
- Database (use `[x]`):
|
||||
- [ ] PostgreSQL
|
||||
- [ ] MySQL
|
||||
- [ ] SQLite
|
||||
- Can you reproduce the bug at http://try.gogs.io:
|
||||
- Can you reproduce the bug at https://try.gogs.io:
|
||||
- [ ] Yes (provide example URL)
|
||||
- [ ] No
|
||||
- [ ] Not relevant
|
||||
|
||||
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
9
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,4 +1,9 @@
|
||||
Please, make sure you are targeting the `develop` branch!
|
||||
The pull request will be closed without any reasons if it does not satisfy any of following requirements:
|
||||
|
||||
More instructions about contributing with Gogs code can be found here:
|
||||
1. Please make sure you are targeting the `develop` branch.
|
||||
2. Please read contributing guidelines:
|
||||
https://github.com/gogits/gogs/wiki/Contributing-Code
|
||||
3. Please describe what your pull request does and which issue you're targeting
|
||||
4. ... if it is not related to any particular issues, explain why we should not reject your pull request.
|
||||
|
||||
**You MUST delete above content including this line before posting; too lazy to take this action considered invalid pull request.**
|
||||
|
||||
28
.gopmfile
28
.gopmfile
@@ -13,43 +13,43 @@ github.com/go-macaron/i18n = commit:ef57533
|
||||
github.com/go-macaron/inject = commit:c5ab7bf
|
||||
github.com/go-macaron/session = commit:66031fc
|
||||
github.com/go-macaron/toolbox = commit:82b5115
|
||||
github.com/go-sql-driver/mysql = commit:3654d25
|
||||
github.com/go-sql-driver/mysql = commit:0b58b37
|
||||
github.com/go-xorm/core = commit:bc1b7f8
|
||||
github.com/go-xorm/xorm = commit:b8b1711
|
||||
github.com/gogits/chardet = commit:2404f77
|
||||
github.com/gogits/cron = commit:96040e4
|
||||
github.com/gogits/git-module = commit:53bcb73
|
||||
github.com/gogits/go-gogs-client = commit:ee68cd9
|
||||
github.com/gogits/go-gogs-client = commit:d725743
|
||||
github.com/issue9/identicon = commit:d36b545
|
||||
github.com/jaytaylor/html2text = commit:52d9b78
|
||||
github.com/kardianos/minwinsvc = commit:cad6b2b
|
||||
github.com/klauspost/compress = commit:14eb9c4
|
||||
github.com/klauspost/cpuid = commit:09cded8
|
||||
github.com/klauspost/crc32 = commit:19b0b33
|
||||
github.com/lib/pq = commit:ee1442b
|
||||
github.com/mattn/go-sqlite3 = commit:38ee283
|
||||
github.com/lib/pq = commit:4dd446e
|
||||
github.com/mattn/go-sqlite3 = commit:e118d44
|
||||
github.com/mcuadros/go-version = commit:d52711f
|
||||
github.com/microcosm-cc/bluemonday = commit:4ac6f27
|
||||
github.com/microcosm-cc/bluemonday = commit:9dc1992
|
||||
github.com/msteinert/pam = commit:02ccfbf
|
||||
github.com/nfnt/resize = commit:4d93a29
|
||||
github.com/russross/blackfriday = commit:4e6f303
|
||||
github.com/satori/go.uuid = commit:879c588
|
||||
github.com/nfnt/resize = commit:891127d
|
||||
github.com/russross/blackfriday = commit:93622da
|
||||
github.com/satori/go.uuid = commit:0aa62d5
|
||||
github.com/sergi/go-diff = commit:ec7fdbb
|
||||
github.com/shurcooL/sanitized_anchor_name = commit:10ef21a
|
||||
github.com/Unknwon/cae = commit:7f5e046
|
||||
github.com/Unknwon/com = commit:28b053d
|
||||
github.com/Unknwon/i18n = commit:39d6f27
|
||||
github.com/Unknwon/paginater = commit:7748a72
|
||||
golang.org/x/crypto = commit:77f4136
|
||||
golang.org/x/net = commit:3f122ce
|
||||
golang.org/x/sys = commit:7f918dd
|
||||
golang.org/x/text = commit:e477511
|
||||
golang.org/x/crypto = commit:bc89c49
|
||||
golang.org/x/net = commit:57bfaa8
|
||||
golang.org/x/sys = commit:a646d33
|
||||
golang.org/x/text = commit:2910a50
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 = commit:2caba25
|
||||
gopkg.in/asn1-ber.v1 = commit:4e86f43
|
||||
gopkg.in/bufio.v1 = commit:567b2bf
|
||||
gopkg.in/gomail.v2 = commit:81ebce5
|
||||
gopkg.in/ini.v1 = commit:72ba3e6
|
||||
gopkg.in/ldap.v2 = commit:0e7db8e
|
||||
gopkg.in/ini.v1 = commit:cf53f92
|
||||
gopkg.in/ldap.v2 = commit:537128f
|
||||
gopkg.in/macaron.v1 = commit:2133042
|
||||
gopkg.in/redis.v2 = commit:e617904
|
||||
|
||||
|
||||
4
Makefile
4
Makefile
@@ -24,6 +24,10 @@ govet:
|
||||
go tool vet -composites=false -methods=false -structtags=false .
|
||||
|
||||
build-dev: $(GENERATED) govet
|
||||
go install $(BUILD_FLAGS) -tags '$(TAGS)'
|
||||
cp '$(GOPATH)/bin/gogs' .
|
||||
|
||||
build-dev-race: $(GENERATED) govet
|
||||
go install $(BUILD_FLAGS) -race -tags '$(TAGS)'
|
||||
cp '$(GOPATH)/bin/gogs' .
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ Gogs - Go Git Service [
|
||||
|
||||
##### Current tip version: 0.9.48 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions)
|
||||
##### Current tip version: 0.9.60 (see [Releases](https://github.com/gogits/gogs/releases) for binary versions)
|
||||
|
||||
| Web | UI | Preview |
|
||||
|:-------------:|:-------:|:-------:|
|
||||
@@ -77,6 +77,8 @@ There are 5 ways to install Gogs:
|
||||
|
||||
- [How To Set Up Gogs on Ubuntu 14.04](https://www.digitalocean.com/community/tutorials/how-to-set-up-gogs-on-ubuntu-14-04)
|
||||
- [Run your own GitHub-like service with the help of Docker](http://blog.hypriot.com/post/run-your-own-github-like-service-with-docker/)
|
||||
- [Dockerized Gogs git server and alpine postgres in 20 minutes or less](http://garthwaite.org/docker-gogs.html)
|
||||
- [Host Your Own Private GitHub with Gogs.io](https://eladnava.com/host-your-own-private-github-with-gogs-io/)
|
||||
- [使用 Gogs 搭建自己的 Git 服务器](https://mynook.info/blog/post/host-your-own-git-server-using-gogs) (Chinese)
|
||||
- [阿里云上 Ubuntu 14.04 64 位安装 Gogs](http://my.oschina.net/luyao/blog/375654) (Chinese)
|
||||
- [Installing Gogs on FreeBSD](https://www.codejam.info/2015/03/installing-gogs-on-freebsd.html)
|
||||
@@ -120,7 +122,7 @@ There are 5 ways to install Gogs:
|
||||
- Thanks [lavachen](http://www.lavachen.cn/) and [Rocker](http://weibo.com/rocker1989) for designing Logo.
|
||||
- Thanks [Crowdin](https://crowdin.com/project/gogs) for providing open source translation plan.
|
||||
- Thanks [DigitalOcean](https://www.digitalocean.com) for hosting home and demo sites.
|
||||
- Thanks [KeyCDN](https://www.keycdn.com/) for providing CDN service.
|
||||
- Thanks [KeyCDN](https://www.keycdn.com/) and [QiNiu](http://www.qiniu.com/) for providing CDN service.
|
||||
|
||||
## Contributors
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自
|
||||
- 感谢 [lavachen](http://www.lavachen.cn/) 和 [Rocker](http://weibo.com/rocker1989) 设计的 Logo。
|
||||
- 感谢 [Crowdin](https://crowdin.com/project/gogs) 提供免费的开源项目本地化支持。
|
||||
- 感谢 [DigitalOcean](https://www.digitalocean.com) 提供主站和体验站点的服务器赞助。
|
||||
- 感谢 [KeyCDN](https://www.keycdn.com/) 提供 CDN 服务赞助。
|
||||
- 感谢 [KeyCDN](https://www.keycdn.com/) 和 [七牛云存储](http://www.qiniu.com/) 提供 CDN 服务赞助。
|
||||
|
||||
## 贡献成员
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ func handleUpdateTask(uuid string, user, repoUser *models.User, reponame string,
|
||||
RefName: task.RefName,
|
||||
OldCommitID: task.OldCommitID,
|
||||
NewCommitID: task.NewCommitID,
|
||||
PusherID: user.Id,
|
||||
PusherID: user.ID,
|
||||
PusherName: user.Name,
|
||||
RepoUserName: repoUser.Name,
|
||||
RepoName: reponame,
|
||||
@@ -175,7 +175,7 @@ func runServ(c *cli.Context) error {
|
||||
fail("Internal error", "Failed to get repository owner (%s): %v", username, err)
|
||||
}
|
||||
|
||||
repo, err := models.GetRepositoryByName(repoUser.Id, reponame)
|
||||
repo, err := models.GetRepositoryByName(repoUser.ID, reponame)
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
fail(_ACCESS_DENIED_MESSAGE, "Repository does not exist: %s/%s", repoUser.Name, reponame)
|
||||
|
||||
@@ -88,7 +88,7 @@ func checkVersion() {
|
||||
{"gopkg.in/ini.v1", ini.Version, "1.8.4"},
|
||||
{"gopkg.in/macaron.v1", macaron.Version, "1.1.4"},
|
||||
{"github.com/gogits/git-module", git.Version, "0.3.3"},
|
||||
{"github.com/gogits/go-gogs-client", gogs.Version, "0.7.4"},
|
||||
{"github.com/gogits/go-gogs-client", gogs.Version, "0.10.1"},
|
||||
}
|
||||
for _, c := range checkers {
|
||||
if !version.Compare(c.Version(), c.Expected, ">=") {
|
||||
@@ -464,7 +464,10 @@ func runWeb(ctx *cli.Context) error {
|
||||
m.Post("/content", repo.UpdateIssueContent)
|
||||
})
|
||||
})
|
||||
m.Post("/comments/:id", repo.UpdateCommentContent)
|
||||
m.Group("/comments/:id", func() {
|
||||
m.Post("", repo.UpdateCommentContent)
|
||||
m.Post("/delete", repo.DeleteComment)
|
||||
})
|
||||
m.Group("/labels", func() {
|
||||
m.Post("/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||
m.Post("/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||
|
||||
@@ -44,6 +44,10 @@ NOTICE_PAGING_NUM = 25
|
||||
; Number of organization that are showed in one page
|
||||
ORG_PAGING_NUM = 50
|
||||
|
||||
[ui.user]
|
||||
; Number of repos that are showed in one page
|
||||
REPO_PAGING_NUM = 15
|
||||
|
||||
[markdown]
|
||||
; Enable hard line break extension
|
||||
ENABLE_HARD_LINE_BREAK = false
|
||||
@@ -314,7 +318,7 @@ RUN_AT_START = false
|
||||
|
||||
; Update mirrors
|
||||
[cron.update_mirrors]
|
||||
SCHEDULE = @every 1h
|
||||
SCHEDULE = @every 10m
|
||||
|
||||
; Repository health check
|
||||
[cron.repo_health_check]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Име или ел. поща
|
||||
password_holder=Парола
|
||||
switch_dashboard_context=Превключи контекст на таблото
|
||||
my_repos=Моите хранилища
|
||||
show_more_repos=Покажи още хранилища...
|
||||
collaborative_repos=Съвместни хранилища
|
||||
my_orgs=Моите организации
|
||||
my_mirrors=Моите огледала
|
||||
@@ -148,8 +149,8 @@ forget_password=Забравена парола?
|
||||
sign_up_now=Нуждаете се от профил? Регистрирайте се сега.
|
||||
confirmation_mail_sent_prompt=Ново писмо за потвърждение е изпратено до <b>%s</b>. Моля проверете пощенската си кутия в рамките на следващите %d часа, за да завършите процеса на регистрация.
|
||||
active_your_account=Активиране на профил
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Влизане забранено
|
||||
prohibit_login_desc=Вашият профил е със забрана за влизане, моля свържете се с администратора.
|
||||
resent_limit_prompt=За съжаление Вие съвсем наскоро изпратихте писмо за активация. Моля изчакайте 3 минути, след което опитайте отново.
|
||||
has_unconfirmed_mail=Здравейте %s, имате непотвърден адрес на ел. поща (<b>%s</b>). Ако не сте получили писмо за потвърждение или имате нужда да се изпрати ново писмо, моля щракнете бутона по-долу.
|
||||
resend_mail=Щракнете тук, за да се изпрати ново писмо за потвърждение
|
||||
@@ -159,7 +160,7 @@ reset_password=Нулиране на паролата
|
||||
invalid_code=За съжаление Вашия код за потвърждение е изтекъл или е невалиден.
|
||||
reset_password_helper=Щракнете тук, за да нулирате паролата си
|
||||
password_too_short=Размерът на паролата не може да бъде по-малък от 6 знака.
|
||||
non_local_account=Non-local accounts cannot change passwords through Gogs.
|
||||
non_local_account=Нелокални потребители не могат да сменят паролата си през Gogs.
|
||||
|
||||
[mail]
|
||||
activate_account=Моля активирайте Вашия профил
|
||||
@@ -222,7 +223,7 @@ org_still_own_repo=Тази организация все още притежа
|
||||
target_branch_not_exist=Целевият клон не съществува.
|
||||
|
||||
[user]
|
||||
change_avatar=Change your avatar
|
||||
change_avatar=Проми своя аватар
|
||||
join_on=Регистриран
|
||||
repositories=Хранилища
|
||||
activity=Публична дейност
|
||||
@@ -352,8 +353,8 @@ readme_helper=Изберете шаблон на readme
|
||||
auto_init=Инициализиране на това хранилище с избраните файлове и шаблон
|
||||
create_repo=Създай хранилище
|
||||
default_branch=Клон по подразбиране
|
||||
mirror_prune=Prune
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_prune=Окастряне
|
||||
mirror_prune_desc=Премахва всички препратки за отдалечено проследяване, които не съществуват отдалечено
|
||||
mirror_interval=Интервал на отразяване (часове)
|
||||
mirror_address=Адрес на огледало
|
||||
mirror_address_desc=Моля включете потребител и парола в адреса ако са нужни.
|
||||
@@ -411,7 +412,7 @@ file_raw=Директен файл
|
||||
file_history=История
|
||||
file_view_raw=Виж директен файл
|
||||
file_permalink=Постоянна връзка
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Този файл е твърде голям за да се визуализира
|
||||
|
||||
commits.commits=Ревизии
|
||||
commits.search=Търсене в ревизии
|
||||
@@ -465,7 +466,8 @@ issues.next=Следваща
|
||||
issues.open_title=Отворени
|
||||
issues.closed_title=Затворени
|
||||
issues.num_comments=%d коментара
|
||||
issues.commented_at=`коментира <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`коментира <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Желаете ли да изтриете този коментар?
|
||||
issues.no_content=Все още няма съдържание.
|
||||
issues.close_issue=Затвори
|
||||
issues.close_comment_issue=Kоментирай и затвори
|
||||
@@ -566,10 +568,10 @@ wiki.last_updated=Последна модификация на %s
|
||||
settings=Настройки
|
||||
settings.options=Опции
|
||||
settings.collaboration=Сътрудничество
|
||||
settings.collaboration.admin=Admin
|
||||
settings.collaboration.write=Write
|
||||
settings.collaboration.read=Read
|
||||
settings.collaboration.undefined=Undefined
|
||||
settings.collaboration.admin=За администрация
|
||||
settings.collaboration.write=За писане
|
||||
settings.collaboration.read=За четене
|
||||
settings.collaboration.undefined=Недефинирано
|
||||
settings.hooks=Уеб-куки
|
||||
settings.githooks=Git куки
|
||||
settings.basic_settings=Основни настройки
|
||||
@@ -584,9 +586,9 @@ settings.external_wiki_url_desc=Посетителите ще бъдат пре
|
||||
settings.issues_desc=Включва вградена система за проследяване на задачи
|
||||
settings.use_external_issue_tracker=Използвай външна система за проследяване на задачи
|
||||
settings.tracker_url_format=Формат на URL адрес на външна система за проследяване на задачи
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style=Стил на именуване на външна система за проследяване на задачи:
|
||||
settings.tracker_issue_style.numeric=Цифров
|
||||
settings.tracker_issue_style.alphanumeric=Символен
|
||||
settings.tracker_url_format_desc=Можете да използвате текстови маркери <code>{user} {repo} {index}</code> за потребителско име, име на хранилище и индекс на задача съответно.
|
||||
settings.pulls_desc=Включва заявки за сливане за да може да се приемат външни доработки
|
||||
settings.danger_zone=Опасна зона
|
||||
@@ -609,7 +611,7 @@ settings.delete=Изтрий това хранилище
|
||||
settings.delete_desc=След като изтриете хранилището, няма връщане назад. Моля, бъдете сигурни.
|
||||
settings.delete_notices_1=- Тази операция <strong>НЕ МОЖЕ</strong> да бъде отменена в последствие.
|
||||
settings.delete_notices_2=- Тази операция ще изтрие всичко от това хранилище, включително Git данни, задачи, коментари и достъпа на сътрудници.
|
||||
settings.delete_notices_fork_1=- All forks will become independent after deletion.
|
||||
settings.delete_notices_fork_1=- Всички разклонения ще станат независими след изтриването.
|
||||
settings.deletion_success=Хранилището е изтрито успешно!
|
||||
settings.update_settings_success=Настройките на хранилището са запазени успешно.
|
||||
settings.transfer_owner=Нов притежател
|
||||
@@ -693,8 +695,8 @@ diff.show_unified_view=Обединен изглед
|
||||
diff.stats_desc=променени са <strong>%d файла</strong>, в които са <strong>добавени %d</strong> реда и са <strong>изтрити %d</strong> реда
|
||||
diff.bin=BIN
|
||||
diff.view_file=Целия файл
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Some files were not shown because too many files changed in this diff
|
||||
diff.file_suppressed=Файловите разлики са ограничени, защото са твърде много
|
||||
diff.too_many_files=Някои файлове не бяха показани, защото твърде много файлове са промени
|
||||
|
||||
release.releases=Версии
|
||||
release.new_release=Нова версия
|
||||
@@ -725,6 +727,7 @@ release.deletion=Изтрий версията
|
||||
release.deletion_desc=При изтриване на тази версия ще се премахне и съответния Git маркер. Желаете ли да продължите?
|
||||
release.deletion_success=Версията беше изтрита успешно!
|
||||
release.tag_name_already_exist=Версия с това име на маркер вече съществува.
|
||||
release.tag_name_invalid=Името на етикета е невалидно.
|
||||
release.downloads=Изтегляния
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Редактирай профил
|
||||
users.max_repo_creation=Макс. брой хранилища
|
||||
users.max_repo_creation_desc=(Задайте -1 за да се използва глобалния лимит)
|
||||
users.is_activated=Този профил е активиран
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Този профил има забрана за влизане
|
||||
users.is_admin=Този профил има административни права
|
||||
users.allow_git_hook=Този профил има разрешение да създава Git куки
|
||||
users.allow_import_local=Този профил има права за импорт на локални хранилища
|
||||
@@ -923,7 +926,7 @@ auths.enabled=Активно
|
||||
auths.updated=Последна модификация
|
||||
auths.auth_type=Тип на удостоверяване
|
||||
auths.auth_name=Име на удостоверяване
|
||||
auths.security_protocol=Security Protocol
|
||||
auths.security_protocol=Протокол за защита
|
||||
auths.domain=Домейн
|
||||
auths.host=Сървър
|
||||
auths.port=Порт
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Uživatelské jméno nebo e-mailová adresa
|
||||
password_holder=Heslo
|
||||
switch_dashboard_context=Přepnout kontext přehledu
|
||||
my_repos=Mé repositáře
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Společné repositáře
|
||||
my_orgs=Mé organizace
|
||||
my_mirrors=Má zrcadla
|
||||
@@ -465,7 +466,8 @@ issues.next=Další
|
||||
issues.open_title=otevřený
|
||||
issues.closed_title=zavřený
|
||||
issues.num_comments=%d komentářů
|
||||
issues.commented_at=`komentoval <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Není zde žádný obsah.
|
||||
issues.close_issue=Zavřít
|
||||
issues.close_comment_issue=Okomentovat a zavřít
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Povolit vestavěný jednoduchý systém úkolů
|
||||
settings.use_external_issue_tracker=Použít externí systém úkolů
|
||||
settings.tracker_url_format=Formát URL externího systému úkolů
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=Můžete použít zástupné výrazy <code>{user} {repo} {index}</code> pro uživatelské jméno, název repositáře a index úkolu.
|
||||
settings.pulls_desc=Povolit požadavky na stažení, aby veřejné příspěvky mohly být akceptovány
|
||||
settings.danger_zone=Nebezpečná zóna
|
||||
@@ -725,6 +727,7 @@ release.deletion=Smazání vydání
|
||||
release.deletion_desc=Smazáním tohoto vydání se také smaže odpovídající značka. Chcete pokračovat?
|
||||
release.deletion_success=Vydání bylo úspěšně smazáno!
|
||||
release.tag_name_already_exist=Vydání s touto značkou již existuje.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Soubory ke stažení
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Benutzername oder E-Mail
|
||||
password_holder=Passwort
|
||||
switch_dashboard_context=Kontext der Übersichtsseite wechseln
|
||||
my_repos=Meine Repositories
|
||||
show_more_repos=Zeige mehr Repositories...
|
||||
collaborative_repos=Gemeinschaftliche Repositories
|
||||
my_orgs=Meine Organisationen
|
||||
my_mirrors=Meine Mirrors
|
||||
@@ -148,8 +149,8 @@ forget_password=Passwort vergessen?
|
||||
sign_up_now=Benötigen Sie ein Konto? Registrieren Sie sich jetzt.
|
||||
confirmation_mail_sent_prompt=Eine neue Bestätigungs-E-Mail wurde an <b>%s</b> gesendet. Bitte kontrollieren Sie Ihr Postfach innerhalb der nächsten %d Stunden, um die Registrierung abzuschließen.
|
||||
active_your_account=Aktivieren Sie Ihr Konto
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Anmelden verboten
|
||||
prohibit_login_desc=Ihrem Konto ist es nicht gestattet sich anzumelden. Bitte kontaktieren Sie den Administrator.
|
||||
resent_limit_prompt=Es tut uns leid, aber Sie haben bereits eine Aktivierungs-E-Mail angefordert. Bitte warten Sie 3 Minuten und probieren Sie es dann nochmal.
|
||||
has_unconfirmed_mail=Hallo %s, Sie haben eine unbestätigte E-Mail-Adresse (<b>%s</b>). Wenn Sie keine Bestätigungs-E-Mail erhalten haben oder eine neue benötigen, klicken Sie bitte auf den folgenden Button.
|
||||
resend_mail=Hier klicken, um die Aktivierungs-E-Mail erneut zu versenden
|
||||
@@ -411,7 +412,7 @@ file_raw=Originalformat
|
||||
file_history=Verlauf
|
||||
file_view_raw=Ansicht im Originalformat
|
||||
file_permalink=Permalink
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Diese Datei ist zu groß zum Anzeigen
|
||||
|
||||
commits.commits=Commits
|
||||
commits.search=Commits durchsuchen
|
||||
@@ -465,7 +466,8 @@ issues.next=Nächste
|
||||
issues.open_title=Offen
|
||||
issues.closed_title=Geschlossen
|
||||
issues.num_comments=%d Kommentare
|
||||
issues.commented_at=`hat <a id="%[1]s" href="#%[1]s">%[2]s</a> kommentiert`
|
||||
issues.commented_at=`kommentierte <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Sind Sie sich sicher, dass Sie diesen Kommentar löschen wollen?
|
||||
issues.no_content=Hier gibt es bis jetzt noch keinen Inhalt.
|
||||
issues.close_issue=Schließen
|
||||
issues.close_comment_issue=Kommentieren und schließen
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Eingebautes einfaches Issue-System verwenden
|
||||
settings.use_external_issue_tracker=Externes Issue-System verwenden
|
||||
settings.tracker_url_format=URL-Format des externen Issue-Systems
|
||||
settings.tracker_issue_style=Namenskonvention des externen Issue-Trackers:
|
||||
settings.tracker_issue_style.numeric=Numerisch <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumerisch <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numerisch
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumerisch
|
||||
settings.tracker_url_format_desc=Sie können die Platzhalter <code>{user} {repo} {index}</code> für den Benutzernamen, den Namen des Repositories und die Issue-Nummer verwenden.
|
||||
settings.pulls_desc=Pull-Requests aktivieren, um öffentliche Mitwirkung zu ermöglichen
|
||||
settings.danger_zone=Gefahrenzone
|
||||
@@ -693,7 +695,7 @@ diff.show_unified_view=Gesamtansicht
|
||||
diff.stats_desc=<strong> %d geänderte Dateien</strong> mit <strong>%d neuen</strong> und <strong>%d gelöschten</strong> Zeilen
|
||||
diff.bin=BIN
|
||||
diff.view_file=Datei anzeigen
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.file_suppressed=Datei-Diff unterdrückt, da er zu groß ist
|
||||
diff.too_many_files=Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.
|
||||
|
||||
release.releases=Releases
|
||||
@@ -725,6 +727,7 @@ release.deletion=Release löschen
|
||||
release.deletion_desc=Beim Löschen dieses Releases wird das entsprechende Git-Tag gelöscht. Möchten Sie fortfahren?
|
||||
release.deletion_success=Release wurde erfolgreich gelöscht!
|
||||
release.tag_name_already_exist=Ein Release mit diesem Tag existiert bereits.
|
||||
release.tag_name_invalid=Tag-Name ist nicht gültig.
|
||||
release.downloads=Downloads
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Konto bearbeiten
|
||||
users.max_repo_creation=Maximale Anzahl erstellbarer Repositories
|
||||
users.max_repo_creation_desc=(Auf -1 setzen, um das globale Standardlimit zu verwenden)
|
||||
users.is_activated=Dieses Konto ist aktiviert
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Diesem Konto ist es nicht gestattet sich anzumelden
|
||||
users.is_admin=Dieses Konto hat Administratorrechte
|
||||
users.allow_git_hook=Dieses Konto ist berechtigt Git-Hooks zu erstellen
|
||||
users.allow_import_local=Dieses Konto ist berechtigt, lokale Repositories zu importieren
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder = Username or email
|
||||
password_holder = Password
|
||||
switch_dashboard_context = Switch Dashboard Context
|
||||
my_repos = My Repositories
|
||||
show_more_repos = Show more repositories...
|
||||
collaborative_repos = Collaborative Repositories
|
||||
my_orgs = My Organizations
|
||||
my_mirrors = My Mirrors
|
||||
@@ -465,7 +466,8 @@ issues.next = Next
|
||||
issues.open_title = Open
|
||||
issues.closed_title = Closed
|
||||
issues.num_comments = %d comments
|
||||
issues.commented_at = `commented <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at = `commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm = Are you sure you want to delete this comment?
|
||||
issues.no_content = There is no content yet.
|
||||
issues.close_issue = Close
|
||||
issues.close_comment_issue = Comment and close
|
||||
@@ -577,16 +579,18 @@ settings.site = Official Site
|
||||
settings.update_settings = Update Settings
|
||||
settings.change_reponame_prompt = This change will affect how links relate to the repository.
|
||||
settings.advanced_settings = Advanced Settings
|
||||
settings.wiki_desc = Enable wiki to allow people write documents
|
||||
settings.wiki_desc = Enable wiki system
|
||||
settings.use_internal_wiki = Use builtin wiki
|
||||
settings.use_external_wiki = Use external wiki
|
||||
settings.external_wiki_url = External Wiki URL
|
||||
settings.external_wiki_url_desc = Visitors will be redirected to URL when they click on the tab.
|
||||
settings.issues_desc = Enable builtin lightweight issue tracker
|
||||
settings.issues_desc = Enable issue tracker
|
||||
settings.use_internal_issue_tracker = Use builtin lightweight issue tracker
|
||||
settings.use_external_issue_tracker = Use external issue tracker
|
||||
settings.tracker_url_format = External Issue Tracker URL Format
|
||||
settings.tracker_issue_style = External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric = Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric = Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric = Numeric
|
||||
settings.tracker_issue_style.alphanumeric = Alphanumeric
|
||||
settings.tracker_url_format_desc = You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc = Enable pull requests to accept public contributions
|
||||
settings.danger_zone = Danger Zone
|
||||
@@ -725,6 +729,7 @@ release.deletion = Release Deletion
|
||||
release.deletion_desc = Deleting this release will delete the corresponding Git tag. Do you want to continue?
|
||||
release.deletion_success = Release has been deleted successfully!
|
||||
release.tag_name_already_exist = Release with this tag name already exists.
|
||||
release.tag_name_invalid = Tag name is not valid.
|
||||
release.downloads = Downloads
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Nombre de usuario o correo electrónico
|
||||
password_holder=Contraseña
|
||||
switch_dashboard_context=Cambiar el contexto del Dashboard
|
||||
my_repos=Mis repositorios
|
||||
show_more_repos=Mostrar más repositorios...
|
||||
collaborative_repos=Repositorios colaborativos
|
||||
my_orgs=Mis organizaciones
|
||||
my_mirrors=Mis réplicas
|
||||
@@ -148,8 +149,8 @@ forget_password=¿Has olvidado tu contraseña?
|
||||
sign_up_now=¿Necesitas una cuenta? Regístrate ahora.
|
||||
confirmation_mail_sent_prompt=Un nuevo correo de confirmación se ha enviado a <b>%s</b>. Por favor, comprueba tu bandeja de entrada en las siguientes %d horas para completar el proceso de registro.
|
||||
active_your_account=Activa tu cuenta
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Ingreso prohibido
|
||||
prohibit_login_desc=Su cuenta tiene prohibido ingresar al sistema, fovor contactar al administrador del sistema.
|
||||
resent_limit_prompt=Lo sentimos, estás solicitando el reenvío del mail de activación con demasiada frecuencia. Por favor, espera 3 minutos.
|
||||
has_unconfirmed_mail=Hola %s, tu correo electrónico (<b>%s</b>) no está confirmado. Si no has recibido un correo de confirmación o necesitas que lo enviemos de nuevo, por favor, haz click en el siguiente botón.
|
||||
resend_mail=Haz click aquí para reenviar tu correo electrónico de activación
|
||||
@@ -352,8 +353,8 @@ readme_helper=Seleccione una plantilla de archivo readme
|
||||
auto_init=Inicializar los archivos seleccionados y plantillas de este repositorio
|
||||
create_repo=Crear repositorio
|
||||
default_branch=Rama por defecto
|
||||
mirror_prune=Prune
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_prune=Purgar
|
||||
mirror_prune_desc=Remover referencias remotas que no existan remotamente
|
||||
mirror_interval=Intervalo de la réplica (en horas)
|
||||
mirror_address=Dirección de la réplica
|
||||
mirror_address_desc=Por favor, incluya las credenciales de usuario necesarias en la dirección.
|
||||
@@ -411,7 +412,7 @@ file_raw=Raw
|
||||
file_history=Histórico
|
||||
file_view_raw=Ver Raw
|
||||
file_permalink=Permalink
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Este archivo es demasiado grande para ser mostrado
|
||||
|
||||
commits.commits=Commits
|
||||
commits.search=Buscar Commits
|
||||
@@ -465,7 +466,8 @@ issues.next=Página Siguiente
|
||||
issues.open_title=Abierta
|
||||
issues.closed_title=Cerrada
|
||||
issues.num_comments=%d comentarios
|
||||
issues.commented_at=`comentada <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at='comentado <a href="#%s"> %s'</a>
|
||||
issues.delete_comment_confirm=¿Seguro que deseas eliminar este comentario?
|
||||
issues.no_content=Aún no existe contenido.
|
||||
issues.close_issue=Cerrar
|
||||
issues.close_comment_issue=Comentar y cerrar
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Habilitar tracker ligero de incidencias
|
||||
settings.use_external_issue_tracker=Usar tracker externo de incidencias
|
||||
settings.tracker_url_format=Formato URL del tracker de incidencias externo
|
||||
settings.tracker_issue_style=Estilo de etiquetado del tracker externo de incidencias:
|
||||
settings.tracker_issue_style.numeric=Numérico <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alfanumérico <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numérico
|
||||
settings.tracker_issue_style.alphanumeric=Alfanumérico
|
||||
settings.tracker_url_format_desc=Puedes usar las plantillas <code>{user} {repo} {index}</code> para el nombre de usuario, nombre del repositorio e índice de la incidencia.
|
||||
settings.pulls_desc=Habilitar Pull Requests para aceptar contribuciones públicas
|
||||
settings.danger_zone=Zona de Peligro
|
||||
@@ -693,8 +695,8 @@ diff.show_unified_view=Unificar vista
|
||||
diff.stats_desc=Se han <strong>modificado %d ficheros</strong> con <strong>%d adiciones</strong> y <strong>%d borrados</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Ver fichero
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Some files were not shown because too many files changed in this diff
|
||||
diff.file_suppressed=La diferencia del archivo ha sido suprimido porque es demasiado grande
|
||||
diff.too_many_files=Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio
|
||||
|
||||
release.releases=Releases
|
||||
release.new_release=Nueva Release
|
||||
@@ -725,6 +727,7 @@ release.deletion=Eliminar Release
|
||||
release.deletion_desc=Eliminar este Release eliminará la etiqueta correspondiente. ¿Desea continuar?
|
||||
release.deletion_success=¡El release ha sido eliminado correctamente!
|
||||
release.tag_name_already_exist=Ya existe una Release con esta etiqueta.
|
||||
release.tag_name_invalid=Nombre de la etiqueta no es válido.
|
||||
release.downloads=Descargas
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Editar Cuenta
|
||||
users.max_repo_creation=Límite máximo de repositorios
|
||||
users.max_repo_creation_desc=(Configura a -1 para usar el límite global por defecto)
|
||||
users.is_activated=Esta cuenta está activada
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Esta cuenta no tiene permitido ingresar
|
||||
users.is_admin=Esta cuenta tiene permisos de administrador
|
||||
users.allow_git_hook=Esta cuenta tiene permisos para crear hooks de Git
|
||||
users.allow_import_local=Esta cuenta dispone de permisos para importar repositorios locales
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Käyttäjätunnus tai sähköposti
|
||||
password_holder=Salasana
|
||||
switch_dashboard_context=Vaihda kojelaudan kontekstia
|
||||
my_repos=Reponi
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Yhteistyö repot
|
||||
my_orgs=Organisaationi
|
||||
my_mirrors=Peilini
|
||||
@@ -465,7 +466,8 @@ issues.next=Seuraava
|
||||
issues.open_title=Avoinna
|
||||
issues.closed_title=Suljettu
|
||||
issues.num_comments=%d kommenttia
|
||||
issues.commented_at=`kommentoi <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Sisältöä ei vielä ole.
|
||||
issues.close_issue=Sulje
|
||||
issues.close_comment_issue=Kommentoi ja sulje
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Ota käyttöön sisäänrakennettu kevyt vikaseuranta
|
||||
settings.use_external_issue_tracker=Käytä ulkoista vikaseurantaa
|
||||
settings.tracker_url_format=Ulkoisen vikaseurannan URL muoto
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=Voit käyttää paikkamerkkiä <code>{user} {repo} {index}</code> käyttäjänimelle, reponimelle ja vikanumerolle.
|
||||
settings.pulls_desc=Ota käyttöön pull-pyynnöt salliaksesi julkiset koodilahjoitukset
|
||||
settings.danger_zone=Vaaravyöhyke
|
||||
@@ -725,6 +727,7 @@ release.deletion=Version poisto
|
||||
release.deletion_desc=Tämän version poistaminen poistaa vastaavan Git tagin. Haluatko jatkaa?
|
||||
release.deletion_success=Versio on poistettu onnistuneesti!
|
||||
release.tag_name_already_exist=Versio tällä taginimellä on jo olemassa.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Lataukset
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Nom d'utilisateur ou e-mail
|
||||
password_holder=Mot de passe
|
||||
switch_dashboard_context=Basculer le Contexte du Tableau de Bord
|
||||
my_repos=Mes dépôts
|
||||
show_more_repos=Afficher plus de dépôts...
|
||||
collaborative_repos=Dépôts collaboratifs
|
||||
my_orgs=Mes organisations
|
||||
my_mirrors=Mes miroirs
|
||||
@@ -148,8 +149,8 @@ forget_password=Mot de passe oublié ?
|
||||
sign_up_now=Pas de compte ? Inscrivez-vous maintenant.
|
||||
confirmation_mail_sent_prompt=Un nouveau mail de confirmation à été envoyé à <b>%s</b>. Veuillez vérifier votre boîte de réception dans un délai de %d heures pour compléter votre enregistrement.
|
||||
active_your_account=Activer votre compte
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Connexion interdite
|
||||
prohibit_login_desc=Votre compte est interdit de se connecter, contactez l’administrateur du site.
|
||||
resent_limit_prompt=Désolé, vos tentatives d'activation sont trop fréquentes. Veuillez réessayer dans 3 minutes.
|
||||
has_unconfirmed_mail=Bonjour %s, votre adresse e-mail (<b>%s</b>) n'a pas été confirmée. Si vous n'avez reçu aucun mail de confirmation ou souhaitez renouveler l'envoi, cliquez sur le bouton ci-dessous.
|
||||
resend_mail=Cliquez ici pour renvoyer un mail de confirmation
|
||||
@@ -411,7 +412,7 @@ file_raw=Raw
|
||||
file_history=Historique
|
||||
file_view_raw=Voir le Raw
|
||||
file_permalink=Lien permanent
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Ce fichier est trop gros pour être afficher
|
||||
|
||||
commits.commits=Commits
|
||||
commits.search=Rechercher des commits
|
||||
@@ -465,7 +466,8 @@ issues.next=Page Suivante
|
||||
issues.open_title=Ouvert
|
||||
issues.closed_title=Fermé
|
||||
issues.num_comments=%d commentaires
|
||||
issues.commented_at=`commenté à <a id="%[1]s" href="#%[1]s"> %[2]s</a>`
|
||||
issues.commented_at=`a commenté <a href="#%s"> %s</a>`
|
||||
issues.delete_comment_confirm=Êtes-vous certain de vouloir supprimer ce commentaire?
|
||||
issues.no_content=Il n'existe pas encore de contenu.
|
||||
issues.close_issue=Fermer
|
||||
issues.close_comment_issue=Commenter et fermer
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Activer le bug-tracker léger intégré
|
||||
settings.use_external_issue_tracker=Utiliser un bug-tracker externe
|
||||
settings.tracker_url_format=Format d'URL du bug tracker
|
||||
settings.tracker_issue_style=Style de nommage des bugs du tracker externe :
|
||||
settings.tracker_issue_style.numeric=Numérique <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumérique <span class="ui light grey text"> (ABC-123, DEFG-234,...)</span>
|
||||
settings.tracker_issue_style.numeric=Numérique
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumérique
|
||||
settings.tracker_url_format_desc=Vous pouvez utiliser l'espace réservé <code>{user} {repo} {index}</code> pour le nom d'utilisateur, le nom du dépôt et le numéro de bug.
|
||||
settings.pulls_desc=Activer les pull requests pour accepter les contributions publiques
|
||||
settings.danger_zone=Zone de danger
|
||||
@@ -693,7 +695,7 @@ diff.show_unified_view=Vue unifiée
|
||||
diff.stats_desc=<strong> %d fichiers modifiés</strong> avec <strong>%d ajouts</strong> et <strong>%d suppressions</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Voir le fichier
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.file_suppressed=Fichier diff supprimé car celui-ci est trop grand
|
||||
diff.too_many_files=Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff
|
||||
|
||||
release.releases=Versions
|
||||
@@ -725,6 +727,7 @@ release.deletion=Suppression de la Version
|
||||
release.deletion_desc=Supprimer cette version supprimera le tag Git correspondant. Voulez-vous continuer ?
|
||||
release.deletion_success=La version à été supprimée avec succès !
|
||||
release.tag_name_already_exist=Une version avec ce nom de tag existe déjà.
|
||||
release.tag_name_invalid=Nom de tag invalide.
|
||||
release.downloads=Téléchargements
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Modifier le Compte
|
||||
users.max_repo_creation=Nombre maximum de dépôts créés
|
||||
users.max_repo_creation_desc=(Mettre à -1 pour utiliser la limite globale par défaut)
|
||||
users.is_activated=Ce compte est activé
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Ce compte est interdit de se connecter
|
||||
users.is_admin=Ce compte possède un niveau d'accès administrateur
|
||||
users.allow_git_hook=Ce compte dispose des autorisations pour créer des crochets de Git
|
||||
users.allow_import_local=Ce compte dispose des permissions nécessaire à l'import des dépôts locaux
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Nome Utente o E-mail
|
||||
password_holder=Password
|
||||
switch_dashboard_context=Cambia Dashboard Context
|
||||
my_repos=I miei Repository
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Repository Condivisi
|
||||
my_orgs=Le mie Organizzazioni
|
||||
my_mirrors=I miei Mirror
|
||||
@@ -465,7 +466,8 @@ issues.next=Pagina successiva
|
||||
issues.open_title=Aperto
|
||||
issues.closed_title=Chiuso
|
||||
issues.num_comments=%d commenti
|
||||
issues.commented_at=`commented <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Non ci sono ancora contenuti.
|
||||
issues.close_issue=Chiudi
|
||||
issues.close_comment_issue=Commenta e chiudi
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Abilita l'issue tracker builtin leggero
|
||||
settings.use_external_issue_tracker=Utilizza gestore di problemi esterno
|
||||
settings.tracker_url_format=Formato URL Gestore Problemi Esterno
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Abilita le pull requests per accettare contributi pubblici
|
||||
settings.danger_zone=Zona Pericolosa
|
||||
@@ -725,6 +727,7 @@ release.deletion=Eliminazione Release
|
||||
release.deletion_desc=Eliminando questa release cancellarai anche i tag Git corrispondenti. Vuoi continuare?
|
||||
release.deletion_success=La release è stata eliminata con successo!
|
||||
release.tag_name_already_exist=Un rilascio con questo tag esiste già.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Download
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=ユーザー名またはEメール
|
||||
password_holder=パスワード
|
||||
switch_dashboard_context=ダッシュ ボードのコンテキストを切替
|
||||
my_repos=自分のリポジトリ
|
||||
show_more_repos=リポジトリをさらに表示…
|
||||
collaborative_repos=共同リポジトリ
|
||||
my_orgs=自分の組織
|
||||
my_mirrors=自分のミラー
|
||||
@@ -465,7 +466,8 @@ issues.next=次ページ
|
||||
issues.open_title=オープン
|
||||
issues.closed_title=クローズ
|
||||
issues.num_comments=%d コメント
|
||||
issues.commented_at=`コメント <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=まだコンテンツがありません
|
||||
issues.close_issue=閉じる
|
||||
issues.close_comment_issue=コメントしてクローズ
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=組み込み簡易課題トラッカーを有効
|
||||
settings.use_external_issue_tracker=外部課題トラッキングシステムを使用
|
||||
settings.tracker_url_format=外部課題トラッキングツール URLのフォーマット
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=You can use placeholder <code>{user} {repo} {index}</code> for user name, repository name and issue index.
|
||||
settings.pulls_desc=Enable pull requests to accept public contributions
|
||||
settings.danger_zone=危険地帯
|
||||
@@ -725,6 +727,7 @@ release.deletion=リリースの削除
|
||||
release.deletion_desc=このリリースを削除すると、対応するGitのタグも削除されます。よろしいですか?
|
||||
release.deletion_success=リリースが正常に削除されました。
|
||||
release.tag_name_already_exist=このタグ名には既にリリースが存在します。
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Downloads
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Lietotājvārds vai e-pasts
|
||||
password_holder=Parole
|
||||
switch_dashboard_context=Mainīt infopaneļa kontekstu
|
||||
my_repos=Mani repozitoriji
|
||||
show_more_repos=Parādīt vairāk repozitorojus...
|
||||
collaborative_repos=Sadarbības repozitoriji
|
||||
my_orgs=Manas organizācijas
|
||||
my_mirrors=Mani spoguļi
|
||||
@@ -148,8 +149,8 @@ forget_password=Aizmirsi paroli?
|
||||
sign_up_now=Nepieciešams konts? Reģistrējies tagad.
|
||||
confirmation_mail_sent_prompt=Jauns apstiprināšanas e-pasts ir nosūtīts uz <b>%s</b>, lūdzu, pārbaudies savu e-pasta kontu tuvāko %d stundu laikā, lai pabeigtu reģistrācijas procesu.
|
||||
active_your_account=Aktivizēt savu kontu
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Aizliegt pieteikšanos
|
||||
prohibit_login_desc=Ar Jūsu kontu nav atļauts pieteikties, sazinoties ar lapas administratoru.
|
||||
resent_limit_prompt=Atvainojiet, Jūs sūtījāt aktivizācijas e-pastu pārāk bieži. Lūdzu, gaidiet 3 minūtes.
|
||||
has_unconfirmed_mail=Sveiki %s, Jums ir neapstiprināta e-pasta adrese (<b>%s</b>). Ja neesat saņēmis apstiprināšanas e-pastu vai Jums ir nepieciešams nosūtīt jaunu, lūdzu, nospiediet pogu, kas atrodas zemāk.
|
||||
resend_mail=Nospiediet šeit, lai vēlreiz nosūtītu aktivizācijas e-pastu
|
||||
@@ -159,7 +160,7 @@ reset_password=Atjaunot savu paroli
|
||||
invalid_code=Atvainojiet, Jūsu apstiprināšanas kodam ir beidzies derīguma termiņš vai arī tas ir nepareizs.
|
||||
reset_password_helper=Nospiediet šeit, lai atjaunotu paroli
|
||||
password_too_short=Paroles garums nedrīkst būt mazāks par 6.
|
||||
non_local_account=Non-local accounts cannot change passwords through Gogs.
|
||||
non_local_account=Tikai lokālie konti var nomainīt savu paroli Gogs.
|
||||
|
||||
[mail]
|
||||
activate_account=Lūdzu, aktivizējiet savu kontu
|
||||
@@ -222,7 +223,7 @@ org_still_own_repo=Šī organizācija ir vismaz viena repozitorija īpašnieks,
|
||||
target_branch_not_exist=Mērķa atzars neeksistē
|
||||
|
||||
[user]
|
||||
change_avatar=Change your avatar
|
||||
change_avatar=Mainīt profila attēlu
|
||||
join_on=Pievienojās
|
||||
repositories=Repozitoriji
|
||||
activity=Publiskā aktivitāte
|
||||
@@ -352,8 +353,8 @@ readme_helper=Izvēlieties faila LasiMani sagatavi
|
||||
auto_init=Inicializēt šo repozitoriju ar izvēlētajiem failiem un sagatavi
|
||||
create_repo=Izveidot repozitoriju
|
||||
default_branch=Noklusējuma atzars
|
||||
mirror_prune=Prune
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_prune=Izmest
|
||||
mirror_prune_desc=Izdzēst visas ārējās atsauces, kas ārējā repozitorijā vairs neeksistē
|
||||
mirror_interval=Spoguļošanas intervāls (stundās)
|
||||
mirror_address=Spoguļa adrese
|
||||
mirror_address_desc=Lūdzu iekļaujiet adresē nepieciešamo lietotājvārdu/paroli.
|
||||
@@ -411,7 +412,7 @@ file_raw=Neapstrādāts
|
||||
file_history=Vēsture
|
||||
file_view_raw=Rādīt neapstrādātu
|
||||
file_permalink=Patstāvīgā saite
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Šis fails ir par lielu, lai to parādītu
|
||||
|
||||
commits.commits=Revīzijas
|
||||
commits.search=Meklēt revīzijas
|
||||
@@ -465,7 +466,8 @@ issues.next=Nākamā
|
||||
issues.open_title=Atvērta
|
||||
issues.closed_title=Slēgta
|
||||
issues.num_comments=%d komentāri
|
||||
issues.commented_at=`komentēja <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=` komentēja <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Vai patiešām vēlaties dzēst šo komentāru?
|
||||
issues.no_content=Vēl nav satura.
|
||||
issues.close_issue=Aizvērt
|
||||
issues.close_comment_issue=Komentēt un aizvērt
|
||||
@@ -566,10 +568,10 @@ wiki.last_updated=Pēdējo reizi labota %s
|
||||
settings=Iestatījumi
|
||||
settings.options=Opcijas
|
||||
settings.collaboration=Sadarbība
|
||||
settings.collaboration.admin=Admin
|
||||
settings.collaboration.write=Write
|
||||
settings.collaboration.read=Read
|
||||
settings.collaboration.undefined=Undefined
|
||||
settings.collaboration.admin=Administrators
|
||||
settings.collaboration.write=Rakstīšanas
|
||||
settings.collaboration.read=Skatīšanās
|
||||
settings.collaboration.undefined=Nedefinētas
|
||||
settings.hooks=Tīmekļa āķi
|
||||
settings.githooks=Git āķi
|
||||
settings.basic_settings=Pamatiestatījumi
|
||||
@@ -584,9 +586,9 @@ settings.external_wiki_url_desc=Apmeklētāji tiks novirzīti uz adresi, kad vi
|
||||
settings.issues_desc=Iespējot iebūvētu vieglu problēmu sekotāju
|
||||
settings.use_external_issue_tracker=Izmantot ārējo problēmu sekotāju
|
||||
settings.tracker_url_format=Ārējā problēmu sekotāja adreses formāts
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style=Ārējā problēmu reģistra nosaukumu stils:
|
||||
settings.tracker_issue_style.numeric=Cipari
|
||||
settings.tracker_issue_style.alphanumeric=Burti un cipari
|
||||
settings.tracker_url_format_desc=Jūs varat izmantot <code>{user}{repo}{index}</code> lietotājvārdam, repozitorija nosaukumam un problēmas identifikātoram.
|
||||
settings.pulls_desc=Iespējot izmaiņu pieprasījumus lai saņemtu publiskus ieguldījumus
|
||||
settings.danger_zone=Bīstamā zona
|
||||
@@ -609,7 +611,7 @@ settings.delete=Dzēst šo repozitoriju
|
||||
settings.delete_desc=Dzēšot repozitoriju, tā datus vairs nebūs iespējams atgūt. Pirms dzēšanas pārliecinieites vai patiešām vēlaties to darīt.
|
||||
settings.delete_notices_1=- Šī darbība ir <strong>NEATGRIEZENISKA</strong>.
|
||||
settings.delete_notices_2=- Šī darbība neatgriezeniski izdzēsīs visus šī repozitorija datus, tai skaitā Git datus, problēmu ziņojumus, komentārus un definētās piekļuves tiesības.
|
||||
settings.delete_notices_fork_1=- All forks will become independent after deletion.
|
||||
settings.delete_notices_fork_1=- Visi atdalītie repozitoriji kļūs neatkarīgi pēc dzēšanas.
|
||||
settings.deletion_success=Repozitorijs tika veiksmīgi dzēsts!
|
||||
settings.update_settings_success=Repozitorija opcijas ir veiksmīgi saglabātas.
|
||||
settings.transfer_owner=Jaunais īpašnieks
|
||||
@@ -693,8 +695,8 @@ diff.show_unified_view=Apvienotais skats
|
||||
diff.stats_desc=<strong>%d mainītis faili</strong> ar <strong>%d papildinājumiem</strong> un <strong>%d dzēšanām</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Parādīt failu
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Some files were not shown because too many files changed in this diff
|
||||
diff.file_suppressed=Failā izmaiņas netiks attēlotas, jo tās ir par lielu
|
||||
diff.too_many_files=Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels
|
||||
|
||||
release.releases=Laidieni
|
||||
release.new_release=Jauns laidiens
|
||||
@@ -725,6 +727,7 @@ release.deletion=Laidiena dzēšana
|
||||
release.deletion_desc=Dzēšot šo laidienu tiks dzēsts arī atbilstošs Git tags. Vai vēlaties turpināt?
|
||||
release.deletion_success=Laidiens tika veiksmīgi dzēsts!
|
||||
release.tag_name_already_exist=Laidiens ar šādu taga nosaukumu jau eksistē.
|
||||
release.tag_name_invalid=Nekorekts birkas nosaukams.
|
||||
release.downloads=Lejupielādes
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Labot kontu
|
||||
users.max_repo_creation=Maksimāls repozitoriju veidošanas limits
|
||||
users.max_repo_creation_desc=(Uzlikt -1 lai izmantotu globālu limitu pēc noklusējuma)
|
||||
users.is_activated=Konts ir aktivizēts
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Šim kontam ir aizliegts autorizēties
|
||||
users.is_admin=Šim kontam ir administratora piekļuves tiesības
|
||||
users.allow_git_hook=Šim kontam ir tiesības pievienot/labot Git āķus
|
||||
users.allow_import_local=Šim kontam ir tiesības importēt lokālus repozitorijus
|
||||
@@ -923,7 +926,7 @@ auths.enabled=Iespējota
|
||||
auths.updated=Atjaunināta
|
||||
auths.auth_type=Autentifikācijas tips
|
||||
auths.auth_name=Autentifikācijas nosaukums
|
||||
auths.security_protocol=Security Protocol
|
||||
auths.security_protocol=Drošības protokols
|
||||
auths.domain=Domēns
|
||||
auths.host=Resursdators
|
||||
auths.port=Ports
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Gebruikersnaam of e-mail
|
||||
password_holder=Wachtwoord
|
||||
switch_dashboard_context=Wissel voorpaginacontext
|
||||
my_repos=Mijn repositories
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Gedeelde repositories
|
||||
my_orgs=Mijn organisaties
|
||||
my_mirrors=Mijn mirrors
|
||||
@@ -465,7 +466,8 @@ issues.next=Volgende
|
||||
issues.open_title=Open
|
||||
issues.closed_title=Gesloten
|
||||
issues.num_comments=%d opmerkingen
|
||||
issues.commented_at=`gaf commentaar op <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Er is nog geen inhoud.
|
||||
issues.close_issue=Sluit
|
||||
issues.close_comment_issue=Sluit en geef commentaar
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Ingebouwde compacte issuetracker inschakelen
|
||||
settings.use_external_issue_tracker=Externe issuetracker gebruiken
|
||||
settings.tracker_url_format=URL-formaat externe issuetracker
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=U kan de aanduidingen <code>{user} {repo} {index}</code> gebruiken voor de gebruikersnaam, de naam van de repository en de lijst van open tickets.
|
||||
settings.pulls_desc=Schakel 'pull request' in om publieke bijdragen te mogelijk te maken
|
||||
settings.danger_zone=Gevaren zone
|
||||
@@ -725,6 +727,7 @@ release.deletion=Release verwijderen
|
||||
release.deletion_desc=Als deze release verwijdert, worden de bijbehorende Git tag ook gewist. Wilt u doorgaan?
|
||||
release.deletion_success=Release is verwijderd!
|
||||
release.tag_name_already_exist=Versie met deze naam bestaat al.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Downloads
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Nazwa użytkownika lub e-mail
|
||||
password_holder=Hasło
|
||||
switch_dashboard_context=Przełącz kontekst pulpitu
|
||||
my_repos=Moje repozytoria
|
||||
show_more_repos=Pokaż więcej repozytoriów...
|
||||
collaborative_repos=Wspólne repozytoria
|
||||
my_orgs=Moje organizacje
|
||||
my_mirrors=Moje kopie lustrzane
|
||||
@@ -148,8 +149,8 @@ forget_password=Zapomniałeś hasła?
|
||||
sign_up_now=Potrzebujesz konta? Zarejestruj się teraz.
|
||||
confirmation_mail_sent_prompt=Nowa wiadomość e-mail z potwierdzeniem została wysłana do <b>%s</b>, proszę sprawdzić swoją skrzynkę odbiorczą w ciągu najbliższych godzin %d aby dokończyć proces rejestracji.
|
||||
active_your_account=Aktywuj swoje konto
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Logowanie zabronione
|
||||
prohibit_login_desc=Nie możesz się zalogować na to konto, skontaktuj się z administratorem strony.
|
||||
resent_limit_prompt=Niestety, zbyt często wysyłasz e-mail aktywacyjny. Proszę odczekać 3 minuty.
|
||||
has_unconfirmed_mail=Witaj, %s, masz niepotwierdzony adres e-mail (<b>%s</b>). Jeśli nie otrzymałeś wiadomości e-mail z potwierdzeniem lub potrzebujesz wysłać nową, kliknij na poniższy przycisk.
|
||||
resend_mail=Kliknij tutaj, aby wysłać e-mail aktywacyjny
|
||||
@@ -159,7 +160,7 @@ reset_password=Resetowanie hasła
|
||||
invalid_code=Niestety, Twój kod potwierdzający wygasł lub jest nieprawidłowy.
|
||||
reset_password_helper=Kliknij tutaj, aby zresetować hasło
|
||||
password_too_short=Długość hasła nie może być mniejsza niż 6 znaków.
|
||||
non_local_account=Non-local accounts cannot change passwords through Gogs.
|
||||
non_local_account=Nie lokalne konta nie mogą zmieniać haseł przez Gogs.
|
||||
|
||||
[mail]
|
||||
activate_account=Prosimy aktywować swoje konto
|
||||
@@ -222,7 +223,7 @@ org_still_own_repo=Ta organizacja dalej jest właścicielem repozytorium, które
|
||||
target_branch_not_exist=Gałąź docelowa nie istnieje.
|
||||
|
||||
[user]
|
||||
change_avatar=Change your avatar
|
||||
change_avatar=Zmień swój awatar
|
||||
join_on=Dołączył
|
||||
repositories=Repozytoria
|
||||
activity=Publiczna aktywność
|
||||
@@ -352,8 +353,8 @@ readme_helper=Wybierz szablon readme
|
||||
auto_init=Zainicjuj to repozytorium używając wybranych plików i szablonu
|
||||
create_repo=Utwórz repozytorium
|
||||
default_branch=Domyślna gałąź
|
||||
mirror_prune=Prune
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_prune=Wyczyść
|
||||
mirror_prune_desc=Usuń wszystkie śledzone odwołania które nie istnieją w zdalnym repozytorium
|
||||
mirror_interval=Częstotliwość kopiowania (godziny)
|
||||
mirror_address=Adres kopii lustrzanej
|
||||
mirror_address_desc=Proszę podać wymagane poświadczenia użytkownika w adresie.
|
||||
@@ -411,7 +412,7 @@ file_raw=Czysty
|
||||
file_history=Historia
|
||||
file_view_raw=Zobacz czysty
|
||||
file_permalink=Bezpośredni odnośnik
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Ten plik jest zbyt duży, aby go wyświetlić
|
||||
|
||||
commits.commits=Commity
|
||||
commits.search=Przeszukaj commity
|
||||
@@ -465,7 +466,8 @@ issues.next=Następny
|
||||
issues.open_title=Otwarty
|
||||
issues.closed_title=Zamknięty
|
||||
issues.num_comments=%d komentarzy
|
||||
issues.commented_at=`komentuje <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`skomentował <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Czy na pewno chcesz usunąć ten komentarz?
|
||||
issues.no_content=Nie ma jeszcze treści.
|
||||
issues.close_issue=Zamknij
|
||||
issues.close_comment_issue=Skomentuj i zamknij
|
||||
@@ -566,10 +568,10 @@ wiki.last_updated=Ostatnia aktualizacja %s
|
||||
settings=Ustawienia
|
||||
settings.options=Opcje
|
||||
settings.collaboration=Współpraca
|
||||
settings.collaboration.admin=Admin
|
||||
settings.collaboration.write=Write
|
||||
settings.collaboration.read=Read
|
||||
settings.collaboration.undefined=Undefined
|
||||
settings.collaboration.admin=Administrator
|
||||
settings.collaboration.write=Zapis
|
||||
settings.collaboration.read=Odczyt
|
||||
settings.collaboration.undefined=Niezdefiniowany
|
||||
settings.hooks=Webhooki
|
||||
settings.githooks=Hooki Git
|
||||
settings.basic_settings=Ustawienia podstawowe
|
||||
@@ -584,9 +586,9 @@ settings.external_wiki_url_desc=Odwiedzający zostaną przekierowani do adresu U
|
||||
settings.issues_desc=Włącz wbudowany lekki system zgłaszania problemów
|
||||
settings.use_external_issue_tracker=Użyj zewnętrznego systemu zgłaszania problemów
|
||||
settings.tracker_url_format=Format dla adresu URL zewnętrznego systemu
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style=Styl nazw zewnętrznego systemu zgłaszania problemów:
|
||||
settings.tracker_issue_style.numeric=Numeryczny
|
||||
settings.tracker_issue_style.alphanumeric=Alfanumeryczne
|
||||
settings.tracker_url_format_desc=Symbole zastępcze <code>{user} {repo} {index}</code> mogą być użyte dla nazwy użytkownika, nazwy repozytorium i numeru problemu.
|
||||
settings.pulls_desc=Włącz obsługę pull request, aby akceptować publiczny wkład
|
||||
settings.danger_zone=Strefa niebezpieczeństwa
|
||||
@@ -609,7 +611,7 @@ settings.delete=Usuń to repozytorium
|
||||
settings.delete_desc=Po usunięciu repozytorium nie ma odwrotu. Upewnij się, że tego chcesz.
|
||||
settings.delete_notices_1=- Ta operacja <strong>NIE MOŻE</strong> zostać cofnięta.
|
||||
settings.delete_notices_2=- Ta operacja trwale usunie wszystko z tego repozytorium, w tym dane Git, problemy, komentarze i dostęp dla współpracowników.
|
||||
settings.delete_notices_fork_1=- All forks will become independent after deletion.
|
||||
settings.delete_notices_fork_1=Wszystkie forki staną się niezależne po usunięciu.
|
||||
settings.deletion_success=Repozytorium zostało pomyślnie usunięte!
|
||||
settings.update_settings_success=Opcje repozytorium zostały pomyślnie zaktualizowane.
|
||||
settings.transfer_owner=Nowy właściciel
|
||||
@@ -693,8 +695,8 @@ diff.show_unified_view=Zunifikowany widok
|
||||
diff.stats_desc=<strong>%d zmienionych plików</strong> z <strong>%d dodań</strong> i <strong>%d usunięć</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Wyświetl plik
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Some files were not shown because too many files changed in this diff
|
||||
diff.file_suppressed=Plik diff jest za duży
|
||||
diff.too_many_files=Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików
|
||||
|
||||
release.releases=Wydania
|
||||
release.new_release=Nowe wydanie
|
||||
@@ -715,7 +717,7 @@ release.write=Napisz
|
||||
release.preview=Podgląd
|
||||
release.loading=Ładowanie...
|
||||
release.prerelease_desc=To jest wersja wstępna
|
||||
release.prerelease_helper=Chcemy zwrócić uwagę, że ta wersja jest oznaczona jako eksperymentalna.
|
||||
release.prerelease_helper=Oznacz to wydanie jako wersję wstępną.
|
||||
release.cancel=Anuluj
|
||||
release.publish=Publikuj wersję
|
||||
release.save_draft=Zapisz szkic
|
||||
@@ -725,6 +727,7 @@ release.deletion=Usuwanie wydania
|
||||
release.deletion_desc=Usunięcie tego wydania spowoduje usunięcie odpowiednich tagów Git. Czy chcesz kontynuować?
|
||||
release.deletion_success=Wydanie zostało pomyślnie usunięte!
|
||||
release.tag_name_already_exist=Wersja o tej nazwie tagu już istnieje.
|
||||
release.tag_name_invalid=Nazwa tagu jest niepoprawna.
|
||||
release.downloads=Pliki do pobrania
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Edytuj konto
|
||||
users.max_repo_creation=Maksymalna liczba repozytoriów
|
||||
users.max_repo_creation_desc=(Ustaw -1, aby użyć globalnego limitu)
|
||||
users.is_activated=To konto jest aktywne
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Nie możesz się zalogować na to konto
|
||||
users.is_admin=To konto ma uprawnienia administratora
|
||||
users.allow_git_hook=To konto posiada uprawnienia do tworzenia hooków Git
|
||||
users.allow_import_local=To konto ma uprawnienia do importu lokalnych repozytoriów
|
||||
@@ -923,7 +926,7 @@ auths.enabled=Włączono
|
||||
auths.updated=Zaktualizowano
|
||||
auths.auth_type=Typ uwierzytelniania
|
||||
auths.auth_name=Nazwa uwierzytelniania
|
||||
auths.security_protocol=Security Protocol
|
||||
auths.security_protocol=Protokół zabezpieczeń
|
||||
auths.domain=Domena
|
||||
auths.host=Host
|
||||
auths.port=Port
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Nome de Usuário ou E-mail
|
||||
password_holder=Senha
|
||||
switch_dashboard_context=Trocar Contexto do Painel de Controle
|
||||
my_repos=Meus Repositórios
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Repositórios Colaborativos
|
||||
my_orgs=Minhas Organizações
|
||||
my_mirrors=Meus Espelhos
|
||||
@@ -148,8 +149,8 @@ forget_password=Esqueceu a senha?
|
||||
sign_up_now=Precisa de uma conta? Cadastre-se agora.
|
||||
confirmation_mail_sent_prompt=Um novo e-mail de confirmação foi enviado para <b>%s</b>, por favor, verifique sua caixa de entrada nas próximas %d horas para completar seu registro.
|
||||
active_your_account=Ativar Sua Conta
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Login proibido
|
||||
prohibit_login_desc=Sua conta foi proibida de efetuar login, por favor contate o administrador do site.
|
||||
resent_limit_prompt=Desculpe, você está enviando um e-mail de ativação com muita frequência. Por favor, aguarde 3 minutos.
|
||||
has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (<b>%s</b>). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo.
|
||||
resend_mail=Clique aqui para reenviar seu e-mail de ativação
|
||||
@@ -411,7 +412,7 @@ file_raw=Cru
|
||||
file_history=Histórico
|
||||
file_view_raw=Ver cru
|
||||
file_permalink=Link permanente
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Este arquivo é muito grande para ser exibido
|
||||
|
||||
commits.commits=Commits
|
||||
commits.search=Pesquisar commits
|
||||
@@ -465,7 +466,8 @@ issues.next=Próxima página
|
||||
issues.open_title=aberto
|
||||
issues.closed_title=fechado
|
||||
issues.num_comments=%d comentários
|
||||
issues.commented_at=`comentado <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Nenhum conteúdo textual.
|
||||
issues.close_issue=Fechar
|
||||
issues.close_comment_issue=Comentar e fechar
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Habilitar gerenciamento de "problemas" nativo
|
||||
settings.use_external_issue_tracker=Usar issue tracker externo
|
||||
settings.tracker_url_format=Formato de URL do issue tracker externo
|
||||
settings.tracker_issue_style=Estilo de nome de issue tracker externo:
|
||||
settings.tracker_issue_style.numeric=Numérico <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alfanumérico <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=Você pode usar o espaço reservado <code>{user} {repo} {index}</code> para o nome do usuário, índice de nome e a questão do repositório.
|
||||
settings.pulls_desc=Habilitar pull requests para aceitar contribuições públicas
|
||||
settings.danger_zone=Zona de Perigo
|
||||
@@ -693,7 +695,7 @@ diff.show_unified_view=Visão unificada
|
||||
diff.stats_desc=<strong> %d arquivos alterados</strong> com <strong>%d adições</strong> e <strong>%d exclusões</strong>
|
||||
diff.bin=BIN
|
||||
diff.view_file=Ver Arquivo
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.file_suppressed=Diferenças do arquivo suprimidas por serem muito extensas
|
||||
diff.too_many_files=Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff
|
||||
|
||||
release.releases=Versões
|
||||
@@ -725,6 +727,7 @@ release.deletion=Deleção de versão
|
||||
release.deletion_desc=Deletar esta versão vai deletar a tag do git correspondente. Você deseja continuar?
|
||||
release.deletion_success=A versão foi deletada com sucesso!
|
||||
release.tag_name_already_exist=Já existiu versão com esse nome de tag.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Downloads
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Editar Conta
|
||||
users.max_repo_creation=Limite máximo de criação de repositórios
|
||||
users.max_repo_creation_desc=(Use "-1" para utilizar o limite padrão)
|
||||
users.is_activated=Esta conta está ativada
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Esta conta está proibida de efetuar login
|
||||
users.is_admin=Esta conta tem permissões de administrador
|
||||
users.allow_git_hook=Esta conta tem permissões para criar hooks do Git
|
||||
users.allow_import_local=Esta conta tem permissões para importar repositórios locais
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Имя пользователь или E-mail
|
||||
password_holder=Пароль
|
||||
switch_dashboard_context=Переключить контекст панели управления
|
||||
my_repos=Мои репозитории
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=Совместные репозитории
|
||||
my_orgs=Мои организации
|
||||
my_mirrors=Мои зеркала
|
||||
@@ -465,7 +466,8 @@ issues.next=Следующая страница
|
||||
issues.open_title=Открыто
|
||||
issues.closed_title=Закрыто
|
||||
issues.num_comments=комментариев: %d
|
||||
issues.commented_at=` прокомментировал <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=Пока нет содержимого.
|
||||
issues.close_issue=Закрыть
|
||||
issues.close_comment_issue=Прокомментировать и закрыть
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=Включить встроенную, легковесну
|
||||
settings.use_external_issue_tracker=Использовать внешнюю систему отслеживания ошибок
|
||||
settings.tracker_url_format=Внешний формат ссылки системы отслеживания ошибок.
|
||||
settings.tracker_issue_style=Стиль Именования Внешней Системы Учета Задач:
|
||||
settings.tracker_issue_style.numeric=Числовой <span class="ui light grey text"> (1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Буквенно-цифровой <span class="ui light grey text"> (ABC-123, DEF-234,...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=Вы можете использовать шаблон <code>{user} {repo} {index}</code> для имени пользователя, репозитория и номера задачи.
|
||||
settings.pulls_desc=Включить публичные запросы на слияние
|
||||
settings.danger_zone=Опасная зона
|
||||
@@ -725,6 +727,7 @@ release.deletion=Удаление релиза
|
||||
release.deletion_desc=Удаление этого релиза удалит соответствующую Git метку. Вы хотите продолжить?
|
||||
release.deletion_success=Релиз был успешно удален!
|
||||
release.tag_name_already_exist=Релиз с этим именем метки уже существует.
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=Загрузки
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=Kullanıcı Adı veya E-Posta
|
||||
password_holder=Parola
|
||||
switch_dashboard_context=Panoya Geçiş Yap
|
||||
my_repos=Depolarım
|
||||
show_more_repos=Daha fazla depo göster...
|
||||
collaborative_repos=Katkıya Açık Depolar
|
||||
my_orgs=Organizasyonlarım
|
||||
my_mirrors=Yansılarım
|
||||
@@ -148,8 +149,8 @@ forget_password=Parolanızı mı unuttunuz?
|
||||
sign_up_now=Bir hesaba mı ihtiyacınız var? Şimdi kaydolun.
|
||||
confirmation_mail_sent_prompt=<b>%s</b> adresinize yeni bir doğrulama e-postası gönderildi, kaydolma aşamalarını tamamlamak için lütfen %d saat içinde e-posta adresinizi kontrol edin.
|
||||
active_your_account=Hesabınızı Aktifleştirin
|
||||
prohibit_login=Login Prohibited
|
||||
prohibit_login_desc=Your account is prohibited to login, please contact site admin.
|
||||
prohibit_login=Oturum açılması yasak
|
||||
prohibit_login_desc=Hesabınızla oturum açmanız yasaklanmış, lütfen site yöneticisi ile iletişime geçin.
|
||||
resent_limit_prompt=Üzgünüz, zaten bir doğrulama e-postası talep ettiniz. Lütfen 3 dakika bekleyip tekrar deneyin.
|
||||
has_unconfirmed_mail=Merhaba %s, doğrulanmamış bir e-posta adresin var (<b>%s</b>). Bir doğrulama e-postası almadıysanız ya da yenisine ihtiyacınız varsa lütfen aşağıdaki düğmeye tıklayın.
|
||||
resend_mail=Doğrulama e-postasını tekrar almak için buraya tıklayın
|
||||
@@ -159,7 +160,7 @@ reset_password=Parolanızı Sıfırlayın
|
||||
invalid_code=Üzgünüz, doğrulama kodunuz geçersiz veya süresi dolmuş.
|
||||
reset_password_helper=Parolanızı sıfırlamak için buraya tıklayın
|
||||
password_too_short=Parola uzunluğu 6 karakterden az olamaz.
|
||||
non_local_account=Non-local accounts cannot change passwords through Gogs.
|
||||
non_local_account=Yerel olmayan hesapların şifrelerini Gogs aracılığıyla değiştiremezsiniz.
|
||||
|
||||
[mail]
|
||||
activate_account=Lütfen hesabınızı aktifleştirin
|
||||
@@ -222,7 +223,7 @@ org_still_own_repo=Bu organizasyon hala bazı depoların sahibi durumunda. Önce
|
||||
target_branch_not_exist=Hedef dal mevcut değil.
|
||||
|
||||
[user]
|
||||
change_avatar=Change your avatar
|
||||
change_avatar=Profil resmini değiştir
|
||||
join_on=Şuna katıldınız
|
||||
repositories=Depolar
|
||||
activity=Genel Aktivite
|
||||
@@ -352,8 +353,8 @@ readme_helper=Bir benioku şablonu seçin
|
||||
auto_init=Bu depoyu seçilen dosya ve şablonlarla oluştur
|
||||
create_repo=Depo Oluştur
|
||||
default_branch=Varsayılan Dal
|
||||
mirror_prune=Prune
|
||||
mirror_prune_desc=Remove any remote-tracking references that no longer exist on the remote
|
||||
mirror_prune=Buda
|
||||
mirror_prune_desc=Uzakta olmayan bütün uzaktan-izleme referanslarını sil
|
||||
mirror_interval=Yansı Aralığı (saat)
|
||||
mirror_address=Yansı Adresi
|
||||
mirror_address_desc=Lütfen gerekli kimlik bilgilerini adreste bulundurun.
|
||||
@@ -411,7 +412,7 @@ file_raw=Ham
|
||||
file_history=Geçmiş
|
||||
file_view_raw=Ham Görünüm
|
||||
file_permalink=Kalıcı Bağlantı
|
||||
file_too_large=This file is too large to be shown
|
||||
file_too_large=Bu dosya sergilenmek için çok büyük
|
||||
|
||||
commits.commits=İşlemeler
|
||||
commits.search=İşleme Arama
|
||||
@@ -465,7 +466,8 @@ issues.next=Sonraki
|
||||
issues.open_title=Açık
|
||||
issues.closed_title=Kapalı
|
||||
issues.num_comments=%d yorum
|
||||
issues.commented_at=`<a id="%[1]s" href="#%[1]s">%[2]s</a> yorum yaptı`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Bu yorumu silmek istediğinizden emin misiniz?
|
||||
issues.no_content=Henüz bir içerik yok.
|
||||
issues.close_issue=Kapat
|
||||
issues.close_comment_issue=Yorum yap ve kapat
|
||||
@@ -566,10 +568,10 @@ wiki.last_updated=Son güncelleme %s
|
||||
settings=Ayarlar
|
||||
settings.options=Tercihler
|
||||
settings.collaboration=İş birliği
|
||||
settings.collaboration.admin=Admin
|
||||
settings.collaboration.admin=Yönetici
|
||||
settings.collaboration.write=Write
|
||||
settings.collaboration.read=Read
|
||||
settings.collaboration.undefined=Undefined
|
||||
settings.collaboration.undefined=Belirsiz
|
||||
settings.hooks=Web İstekleri
|
||||
settings.githooks=Git İstekleri
|
||||
settings.basic_settings=Temel Ayarlar
|
||||
@@ -584,9 +586,9 @@ settings.external_wiki_url_desc=Ziyaretçiler, sekmeye tıkladıklarında bağla
|
||||
settings.issues_desc=Hazır gelen hafif sorun takipçisini etkinleştir
|
||||
settings.use_external_issue_tracker=Harici sorun takipçisi kullan
|
||||
settings.tracker_url_format=Harici Sorun Takipçisi Bağlantı Formatı
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style=Harici Hata İzleyicisi Adlandırma Stili:
|
||||
settings.tracker_issue_style.numeric=Sayısal
|
||||
settings.tracker_issue_style.alphanumeric=Alfanumerik
|
||||
settings.tracker_url_format_desc=Kullanıcı adı, depo ismi ve hata indeksi için <code>{kullanıcı} {depo} {indeks}</code> tutucusunu kullanabilirsiniz.
|
||||
settings.pulls_desc=Herkese açık katkıları kabul etmek için değişiklik isteklerini etkinleştirin
|
||||
settings.danger_zone=Tehlike Alanı
|
||||
@@ -609,7 +611,7 @@ settings.delete=Bu Depoyu Sil
|
||||
settings.delete_desc=Bir depoyu bir kez sildiğiniz taktirde geri getiremezsiniz. Lütfen emin olun.
|
||||
settings.delete_notices_1=- Bu işlem geri <strong>ALINAMAZ</strong>.
|
||||
settings.delete_notices_2=- Bu işlem, bu depodaki her şeyi (Git verisini, sorunları, yorumları ve katkıcı erişimlerini) kalıcı olarak silecektir.
|
||||
settings.delete_notices_fork_1=- All forks will become independent after deletion.
|
||||
settings.delete_notices_fork_1=Silme işleminden sonra bütün çatallar bağımsız hale gelir.
|
||||
settings.deletion_success=Depo başarıyla silindi!
|
||||
settings.update_settings_success=Depo seçenekleri başarıyla güncellendi.
|
||||
settings.transfer_owner=Yeni Sahip
|
||||
@@ -694,7 +696,7 @@ diff.stats_desc=<strong> %d değiştirilmiş dosya</strong> ile <strong>%d eklem
|
||||
diff.bin=BIN
|
||||
diff.view_file=Dosyayı Görüntüle
|
||||
diff.file_suppressed=File diff suppressed because it is too large
|
||||
diff.too_many_files=Some files were not shown because too many files changed in this diff
|
||||
diff.too_many_files=Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor
|
||||
|
||||
release.releases=Sürümler
|
||||
release.new_release=Yeni Sürüm
|
||||
@@ -725,6 +727,7 @@ release.deletion=Sürüm Silme
|
||||
release.deletion_desc=Bu sürümü silerseniz buna uyan tüm Git biçim imleri de silinecektir. Devam etmek istiyor musunuz?
|
||||
release.deletion_success=Sürüm başarıyla silindi!
|
||||
release.tag_name_already_exist=Bu biçim imi adıyla başka bir sürüm zaten var.
|
||||
release.tag_name_invalid=Etiket adı geçerli değil.
|
||||
release.downloads=İndirmeler
|
||||
|
||||
[org]
|
||||
@@ -892,7 +895,7 @@ users.edit_account=Hesabı Düzenle
|
||||
users.max_repo_creation=Maksimum Depo Oluşturma Limiti
|
||||
users.max_repo_creation_desc=(Genel varsayılan limiti kullanmak için -1 yazın)
|
||||
users.is_activated=Bu hesap aktivleştirildi
|
||||
users.prohibit_login=This account is prohibited to login
|
||||
users.prohibit_login=Bu hesap oturum açmaya engellenmiş
|
||||
users.is_admin=Bu hesap, yönetici izinlerine sahiptir
|
||||
users.allow_git_hook=Bu hesap, Git istekleri oluşturmak için gereken yetkilere sahip
|
||||
users.allow_import_local=Bu hesap, yerel depoları içeri aktarmak için gereken yetkilere sahip
|
||||
@@ -923,7 +926,7 @@ auths.enabled=Aktifleştirilmiş
|
||||
auths.updated=Güncellendi
|
||||
auths.auth_type=Yetki Türü
|
||||
auths.auth_name=Yetki İsmi
|
||||
auths.security_protocol=Security Protocol
|
||||
auths.security_protocol=Güvenlik Protokolü
|
||||
auths.domain=Alan Adı
|
||||
auths.host=Sunucu
|
||||
auths.port=Port
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=用户名或邮箱
|
||||
password_holder=密码
|
||||
switch_dashboard_context=切换控制面板用户
|
||||
my_repos=我的仓库
|
||||
show_more_repos=显示更多仓库...
|
||||
collaborative_repos=参与协作的仓库
|
||||
my_orgs=我的组织
|
||||
my_mirrors=我的镜像
|
||||
@@ -465,7 +466,8 @@ issues.next=下一页
|
||||
issues.open_title=开启中
|
||||
issues.closed_title=已关闭
|
||||
issues.num_comments=%d 条评论
|
||||
issues.commented_at=`于 <a id="%[1]s" href="#%[1]s">%[2]s</a> 评论`
|
||||
issues.commented_at=`评论于 <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=您确定要删除该条评论吗?
|
||||
issues.no_content=这个人很懒,什么都没留下。
|
||||
issues.close_issue=关闭
|
||||
issues.close_comment_issue=评论并关闭
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=启用内置的轻量级工单管理系统
|
||||
settings.use_external_issue_tracker=使用外部的工单管理系统
|
||||
settings.tracker_url_format=外部工单管理系统的 URL 格式
|
||||
settings.tracker_issue_style=外部工单管理系统命名风格:
|
||||
settings.tracker_issue_style.numeric=纯数字 <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=字母和数字结合 <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=纯数字形式
|
||||
settings.tracker_issue_style.alphanumeric=英文字母数字组合形式
|
||||
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分别作为用户名、仓库名和工单索引的占位符。
|
||||
settings.pulls_desc=启用合并请求以接受社区贡献
|
||||
settings.danger_zone=危险操作区
|
||||
@@ -725,6 +727,7 @@ release.deletion=删除版本发布操作
|
||||
release.deletion_desc=删除该版本发布将会移除相应的 Git 标签。是否继续?
|
||||
release.deletion_success=版本发布删除成功!
|
||||
release.tag_name_already_exist=已经存在使用相同标签进行发布的版本。
|
||||
release.tag_name_invalid=标签名称不是有效的名称。
|
||||
release.downloads=下载附件
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=用戶名或郵箱
|
||||
password_holder=密碼
|
||||
switch_dashboard_context=切換控制面版用戶
|
||||
my_repos=我的倉庫
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=參與協作的倉庫
|
||||
my_orgs=我的組織
|
||||
my_mirrors=我的鏡像
|
||||
@@ -465,7 +466,8 @@ issues.next=下一頁
|
||||
issues.open_title=開啟中
|
||||
issues.closed_title=已關閉
|
||||
issues.num_comments=%d 條評論
|
||||
issues.commented_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 評論`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=尚未有任何內容
|
||||
issues.close_issue=關閉
|
||||
issues.close_comment_issue=關閉及評論
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=啟用內置的輕量級問題管理系統
|
||||
settings.use_external_issue_tracker=使用外部的問題管理系統
|
||||
settings.tracker_url_format=外部問題管理系統的 URL 格式
|
||||
settings.tracker_issue_style=External Issue Tracker Naming Style:
|
||||
settings.tracker_issue_style.numeric=Numeric <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
|
||||
settings.pulls_desc=啟用合併請求以接受社區貢獻
|
||||
settings.danger_zone=危險操作區
|
||||
@@ -725,6 +727,7 @@ release.deletion=刪除版本發布操作
|
||||
release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
|
||||
release.deletion_success=版本發布刪除成功!
|
||||
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=下載附件
|
||||
|
||||
[org]
|
||||
|
||||
@@ -124,6 +124,7 @@ uname_holder=用戶名或郵箱
|
||||
password_holder=密碼
|
||||
switch_dashboard_context=切換控制面版用戶
|
||||
my_repos=我的倉庫
|
||||
show_more_repos=Show more repositories...
|
||||
collaborative_repos=參與協作的倉庫
|
||||
my_orgs=我的組織
|
||||
my_mirrors=我的鏡像
|
||||
@@ -465,7 +466,8 @@ issues.next=下一頁
|
||||
issues.open_title=開啟中
|
||||
issues.closed_title=已關閉
|
||||
issues.num_comments=%d 條評論
|
||||
issues.commented_at=`於 <a id="%[1]s" href="#%[1]s">%[2]s</a> 評論`
|
||||
issues.commented_at=`commented <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Are you sure you want to delete this comment?
|
||||
issues.no_content=尚未有任何內容
|
||||
issues.close_issue=關閉
|
||||
issues.close_comment_issue=關閉及評論
|
||||
@@ -585,8 +587,8 @@ settings.issues_desc=啟用內置的輕量級問題管理系統
|
||||
settings.use_external_issue_tracker=使用外部的問題管理系統
|
||||
settings.tracker_url_format=外部問題管理系統的 URL 格式
|
||||
settings.tracker_issue_style=外部公單管理系統命名風格:
|
||||
settings.tracker_issue_style.numeric=僅數字 <span class="ui light grey text">(1234)</span>
|
||||
settings.tracker_issue_style.alphanumeric=數字與字母結合 <span class="ui light grey text">(ABC-123, DEFG-234, ...)</span>
|
||||
settings.tracker_issue_style.numeric=Numeric
|
||||
settings.tracker_issue_style.alphanumeric=Alphanumeric
|
||||
settings.tracker_url_format_desc=您可以使用 <code>{user} {repo} {index}</code> 分別作為用戶名、倉庫名和問題索引的占位符。
|
||||
settings.pulls_desc=啟用合併請求以接受社區貢獻
|
||||
settings.danger_zone=危險操作區
|
||||
@@ -725,6 +727,7 @@ release.deletion=刪除版本發布操作
|
||||
release.deletion_desc=刪除該版本發布將會移除相應的 Git 標籤。是否繼續?
|
||||
release.deletion_success=版本發布刪除成功!
|
||||
release.tag_name_already_exist=已經存在使用相同標籤的發佈版本。
|
||||
release.tag_name_invalid=Tag name is not valid.
|
||||
release.downloads=下載附件
|
||||
|
||||
[org]
|
||||
|
||||
28
glide.lock
generated
28
glide.lock
generated
@@ -31,7 +31,7 @@ imports:
|
||||
- name: github.com/go-macaron/toolbox
|
||||
version: 82b511550b0aefc36b3a28062ad3a52e812bee38
|
||||
- name: github.com/go-sql-driver/mysql
|
||||
version: 3654d25ec346ee8ce71a68431025458d52a38ac0
|
||||
version: 0b58b37b664c21f3010e836f1b931e1d0b0b0685
|
||||
- name: github.com/go-xorm/core
|
||||
version: bc1b7f81f0e369289078424064634a5ee7d21051
|
||||
- name: github.com/go-xorm/xorm
|
||||
@@ -43,7 +43,7 @@ imports:
|
||||
- name: github.com/gogits/git-module
|
||||
version: 53bcb7352ff838610c537c9b589ca79bca92c661
|
||||
- name: github.com/gogits/go-gogs-client
|
||||
version: ee68cd9eefff11615f336e9965762f6736eeecc8
|
||||
version: d725743594dfcd8eea25024f8456c9c103dadb1a
|
||||
- name: github.com/issue9/identicon
|
||||
version: d36b54562f4cf70c83653e13dc95c220c79ef521
|
||||
- name: github.com/jaytaylor/html2text
|
||||
@@ -60,23 +60,23 @@ imports:
|
||||
- name: github.com/klauspost/crc32
|
||||
version: 19b0b332c9e4516a6370a0456e6182c3b5036720
|
||||
- name: github.com/lib/pq
|
||||
version: ee1442bda7bd1b6a84e913bdb421cb1874ec629d
|
||||
version: 4dd446efc17690bc53e154025146f73203b18309
|
||||
subpackages:
|
||||
- oid
|
||||
- name: github.com/mattn/go-sqlite3
|
||||
version: 38ee283dabf11c9cbdb968eebd79b1fa7acbabe6
|
||||
version: e118d4451349065b8e7ce0f0af32e033995363f8
|
||||
- name: github.com/mcuadros/go-version
|
||||
version: d52711f8d6bea8dc01efafdb68ad95a4e2606630
|
||||
- name: github.com/microcosm-cc/bluemonday
|
||||
version: 4ac6f27528d0a3f2a59e0b0a6f6b3ff0bb89fe20
|
||||
version: 9dc199233bf72cc1aad9b61f73daf2f0075b9ee4
|
||||
- name: github.com/msteinert/pam
|
||||
version: 02ccfbfaf0cc627aa3aec8ef7ed5cfeec5b43f63
|
||||
- name: github.com/nfnt/resize
|
||||
version: 4d93a29130b1b6aba503e2aa8b50f516213ea80e
|
||||
version: 891127d8d1b52734debe1b3c3d7e747502b6c366
|
||||
- name: github.com/russross/blackfriday
|
||||
version: 4e6f303e8d936855981ddcdbfc092b03d2b2b68e
|
||||
version: 93622da34e54fb6529bfb7c57e710f37a8d9cbd8
|
||||
- name: github.com/satori/go.uuid
|
||||
version: 879c5887cd475cd7864858769793b2ceb0d44feb
|
||||
version: 0aa62d5ddceb50dbcb909d790b5345affd3669b6
|
||||
- name: github.com/sergi/go-diff
|
||||
version: ec7fdbb58eb3e300c8595ad5ac74a5aa50019cc7
|
||||
subpackages:
|
||||
@@ -94,25 +94,25 @@ imports:
|
||||
- name: github.com/Unknwon/paginater
|
||||
version: 7748a72e01415173a27d79866b984328e7b0c12b
|
||||
- name: golang.org/x/crypto
|
||||
version: 77f4136a99ffb5ecdbdd0226bd5cb146cf56bc0e
|
||||
version: bc89c496413265e715159bdc8478ee9a92fdc265
|
||||
subpackages:
|
||||
- ssh
|
||||
- curve25519
|
||||
- ed25519
|
||||
- ed25519/internal/edwards25519
|
||||
- name: golang.org/x/net
|
||||
version: 3f122ce3dbbe488b7e6a8bdb26f41edec852a40b
|
||||
version: 57bfaa875b96fb91b4766077f34470528d4b03e9
|
||||
subpackages:
|
||||
- html
|
||||
- html/charset
|
||||
- html/atom
|
||||
- name: golang.org/x/sys
|
||||
version: 7f918dd405547ecb864d14a8ecbbfe205b5f930f
|
||||
version: a646d33e2ee3172a661fc09bca23bb4889a41bc8
|
||||
subpackages:
|
||||
- windows/svc
|
||||
- windows
|
||||
- name: golang.org/x/text
|
||||
version: e4775119bd79944a15a741ac4be61e43509a70d9
|
||||
version: 2910a502d2bf9e43193af9d68ca516529614eed3
|
||||
subpackages:
|
||||
- transform
|
||||
- language
|
||||
@@ -138,9 +138,9 @@ imports:
|
||||
- name: gopkg.in/gomail.v2
|
||||
version: 81ebce5c23dfd25c6c67194b37d3dd3f338c98b1
|
||||
- name: gopkg.in/ini.v1
|
||||
version: 72ba3e6b9e6b87e0c74c9a7a4dc86e8dd8ba4355
|
||||
version: cf53f9204df4fbdd7ec4164b57fa6184ba168292
|
||||
- name: gopkg.in/ldap.v2
|
||||
version: 0e7db8eb77695b5a952f0e5d78df9ab160050c73
|
||||
version: 537128fee7cca108d8ce74e4309fdfcdd9c7f496
|
||||
- name: gopkg.in/macaron.v1
|
||||
version: 2133042f8d1022b8253e4e23f7940467941409ce
|
||||
- name: gopkg.in/redis.v2
|
||||
|
||||
2
gogs.go
2
gogs.go
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const APP_VER = "0.9.48.0722"
|
||||
const APP_VER = "0.9.60.0803"
|
||||
|
||||
func init() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
|
||||
@@ -67,11 +67,11 @@ func accessLevel(e Engine, u *User, repo *Repository) (AccessMode, error) {
|
||||
return mode, nil
|
||||
}
|
||||
|
||||
if u.Id == repo.OwnerID {
|
||||
if u.ID == repo.OwnerID {
|
||||
return ACCESS_MODE_OWNER, nil
|
||||
}
|
||||
|
||||
a := &Access{UserID: u.Id, RepoID: repo.ID}
|
||||
a := &Access{UserID: u.ID, RepoID: repo.ID}
|
||||
if has, err := e.Get(a); !has || err != nil {
|
||||
return mode, err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func HasAccess(u *User, repo *Repository, testMode AccessMode) (bool, error) {
|
||||
// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
|
||||
func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
|
||||
accesses := make([]*Access, 0, 10)
|
||||
if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
|
||||
if err := x.Find(&accesses, &Access{UserID: u.ID}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
|
||||
}
|
||||
if err = repo.GetOwner(); err != nil {
|
||||
return nil, err
|
||||
} else if repo.OwnerID == u.Id {
|
||||
} else if repo.OwnerID == u.ID {
|
||||
continue
|
||||
}
|
||||
repos[repo] = access.Mode
|
||||
@@ -121,23 +121,17 @@ func (u *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
// GetAccessibleRepositories finds all repositories where a user has access but does not own.
|
||||
func (u *User) GetAccessibleRepositories() ([]*Repository, error) {
|
||||
accesses := make([]*Access, 0, 10)
|
||||
if err := x.Find(&accesses, &Access{UserID: u.Id}); err != nil {
|
||||
return nil, err
|
||||
// GetAccessibleRepositories finds repositories which the user has access but does not own.
|
||||
// If limit is smaller than 1 means returns all found results.
|
||||
func (user *User) GetAccessibleRepositories(limit int) (repos []*Repository, _ error) {
|
||||
sess := x.Where("owner_id !=? ", user.ID).Desc("updated_unix")
|
||||
if limit > 0 {
|
||||
sess.Limit(limit)
|
||||
repos = make([]*Repository, 0, limit)
|
||||
} else {
|
||||
repos = make([]*Repository, 0, 10)
|
||||
}
|
||||
|
||||
if len(accesses) == 0 {
|
||||
return []*Repository{}, nil
|
||||
}
|
||||
|
||||
repoIDs := make([]int64, 0, len(accesses))
|
||||
for _, access := range accesses {
|
||||
repoIDs = append(repoIDs, access.RepoID)
|
||||
}
|
||||
repos := make([]*Repository, 0, len(repoIDs))
|
||||
return repos, x.Where("owner_id != ?", u.Id).In("id", repoIDs).Desc("updated_unix").Find(&repos)
|
||||
return repos, sess.Join("INNER", "access", "access.user_id = ? AND access.repo_id = repository.id", user.ID).Find(&repos)
|
||||
}
|
||||
|
||||
func maxAccessMode(modes ...AccessMode) AccessMode {
|
||||
@@ -227,7 +221,7 @@ func (repo *Repository) recalculateTeamAccesses(e Engine, ignTeamID int64) (err
|
||||
return fmt.Errorf("getMembers '%d': %v", t.ID, err)
|
||||
}
|
||||
for _, m := range t.Members {
|
||||
accessMap[m.Id] = maxAccessMode(accessMap[m.Id], t.Authorize)
|
||||
accessMap[m.ID] = maxAccessMode(accessMap[m.ID], t.Authorize)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ type Action struct {
|
||||
}
|
||||
|
||||
func (a *Action) BeforeInsert() {
|
||||
a.CreatedUnix = time.Now().UTC().Unix()
|
||||
a.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (a *Action) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -184,7 +184,7 @@ func (a *Action) GetIssueContent() string {
|
||||
|
||||
func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
|
||||
if err = notifyWatchers(e, &Action{
|
||||
ActUserID: u.Id,
|
||||
ActUserID: u.ID,
|
||||
ActUserName: u.Name,
|
||||
ActEmail: u.Email,
|
||||
OpType: ACTION_CREATE_REPO,
|
||||
@@ -193,7 +193,7 @@ func newRepoAction(e Engine, u *User, repo *Repository) (err error) {
|
||||
RepoName: repo.Name,
|
||||
IsPrivate: repo.IsPrivate,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("notify watchers '%d/%d': %v", u.Id, repo.ID, err)
|
||||
return fmt.Errorf("notify watchers '%d/%d': %v", u.ID, repo.ID, err)
|
||||
}
|
||||
|
||||
log.Trace("action.newRepoAction: %s/%s", u.Name, repo.Name)
|
||||
@@ -207,7 +207,7 @@ func NewRepoAction(u *User, repo *Repository) (err error) {
|
||||
|
||||
func renameRepoAction(e Engine, actUser *User, oldRepoName string, repo *Repository) (err error) {
|
||||
if err = notifyWatchers(e, &Action{
|
||||
ActUserID: actUser.Id,
|
||||
ActUserID: actUser.ID,
|
||||
ActUserName: actUser.Name,
|
||||
ActEmail: actUser.Email,
|
||||
OpType: ACTION_RENAME_REPO,
|
||||
@@ -470,8 +470,8 @@ func CommitRepoAction(
|
||||
}
|
||||
}
|
||||
|
||||
if len(commit.Commits) > setting.FeedMaxCommitNum {
|
||||
commit.Commits = commit.Commits[:setting.FeedMaxCommitNum]
|
||||
if len(commit.Commits) > setting.UI.FeedMaxCommitNum {
|
||||
commit.Commits = commit.Commits[:setting.UI.FeedMaxCommitNum]
|
||||
}
|
||||
|
||||
bs, err := json.Marshal(commit)
|
||||
@@ -482,7 +482,7 @@ func CommitRepoAction(
|
||||
refName := git.RefEndName(refFullName)
|
||||
|
||||
if err = NotifyWatchers(&Action{
|
||||
ActUserID: u.Id,
|
||||
ActUserID: u.ID,
|
||||
ActUserName: userName,
|
||||
ActEmail: actEmail,
|
||||
OpType: opType,
|
||||
@@ -506,7 +506,7 @@ func CommitRepoAction(
|
||||
}
|
||||
payloadSender := &api.PayloadUser{
|
||||
UserName: pusher.Name,
|
||||
ID: pusher.Id,
|
||||
ID: pusher.ID,
|
||||
AvatarUrl: pusher.AvatarLink(),
|
||||
}
|
||||
|
||||
@@ -553,7 +553,7 @@ func CommitRepoAction(
|
||||
|
||||
func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repository) (err error) {
|
||||
if err = notifyWatchers(e, &Action{
|
||||
ActUserID: actUser.Id,
|
||||
ActUserID: actUser.ID,
|
||||
ActUserName: actUser.Name,
|
||||
ActEmail: actUser.Email,
|
||||
OpType: ACTION_TRANSFER_REPO,
|
||||
@@ -563,12 +563,12 @@ func transferRepoAction(e Engine, actUser, oldOwner, newOwner *User, repo *Repos
|
||||
IsPrivate: repo.IsPrivate,
|
||||
Content: path.Join(oldOwner.Name, repo.Name),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("notify watchers '%d/%d': %v", actUser.Id, repo.ID, err)
|
||||
return fmt.Errorf("notify watchers '%d/%d': %v", actUser.ID, repo.ID, err)
|
||||
}
|
||||
|
||||
// Remove watch for organization.
|
||||
if repo.Owner.IsOrganization() {
|
||||
if err = watchRepo(e, repo.Owner.Id, repo.ID, false); err != nil {
|
||||
if err = watchRepo(e, repo.Owner.ID, repo.ID, false); err != nil {
|
||||
return fmt.Errorf("watch repository: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -584,7 +584,7 @@ func TransferRepoAction(actUser, oldOwner, newOwner *User, repo *Repository) err
|
||||
|
||||
func mergePullRequestAction(e Engine, actUser *User, repo *Repository, pull *Issue) error {
|
||||
return notifyWatchers(e, &Action{
|
||||
ActUserID: actUser.Id,
|
||||
ActUserID: actUser.ID,
|
||||
ActUserName: actUser.Name,
|
||||
ActEmail: actUser.Email,
|
||||
OpType: ACTION_MERGE_PULL_REQUEST,
|
||||
@@ -602,21 +602,22 @@ func MergePullRequestAction(actUser *User, repo *Repository, pull *Issue) error
|
||||
}
|
||||
|
||||
// GetFeeds returns action list of given user in given context.
|
||||
// userID is the user who's requesting, ctxUserID is the user/org that is requested.
|
||||
// userID can be -1, if isProfile is true or in order to skip the permission check.
|
||||
func GetFeeds(ctxUserID, userID, offset int64, isProfile bool) ([]*Action, error) {
|
||||
// actorID is the user who's requesting, ctxUserID is the user/org that is requested.
|
||||
// actorID can be -1 when isProfile is true or to skip the permission check.
|
||||
func GetFeeds(ctxUser *User, actorID, offset int64, isProfile bool) ([]*Action, error) {
|
||||
actions := make([]*Action, 0, 20)
|
||||
sess := x.Limit(20, int(offset)).Desc("id").Where("user_id=?", ctxUserID)
|
||||
sess := x.Limit(20, int(offset)).Desc("id").Where("user_id = ?", ctxUser.ID)
|
||||
if isProfile {
|
||||
sess.And("is_private=?", false).And("act_user_id=?", ctxUserID)
|
||||
} else if ctxUserID != -1 {
|
||||
ctxUser := &User{Id: ctxUserID}
|
||||
if err := ctxUser.GetUserRepositories(userID); err != nil {
|
||||
return nil, err
|
||||
sess.And("is_private = ?", false).And("act_user_id = ?", ctxUser.ID)
|
||||
} else if actorID != -1 && ctxUser.IsOrganization() {
|
||||
// FIXME: only need to get IDs here, not all fields of repository.
|
||||
repos, _, err := ctxUser.GetUserRepositories(actorID, 1, ctxUser.NumRepos)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetUserRepositories: %v", err)
|
||||
}
|
||||
|
||||
var repoIDs []int64
|
||||
for _, repo := range ctxUser.Repos {
|
||||
for _, repo := range repos {
|
||||
repoIDs = append(repoIDs, repo.ID)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ type Notice struct {
|
||||
}
|
||||
|
||||
func (n *Notice) BeforeInsert() {
|
||||
n.CreatedUnix = time.Now().UTC().Unix()
|
||||
n.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (n *Notice) AfterSet(colName string, _ xorm.Cell) {
|
||||
|
||||
@@ -387,7 +387,7 @@ func IsErrReleaseAlreadyExist(err error) bool {
|
||||
}
|
||||
|
||||
func (err ErrReleaseAlreadyExist) Error() string {
|
||||
return fmt.Sprintf("Release tag already exist [tag_name: %s]", err.TagName)
|
||||
return fmt.Sprintf("release tag already exist [tag_name: %s]", err.TagName)
|
||||
}
|
||||
|
||||
type ErrReleaseNotExist struct {
|
||||
@@ -401,7 +401,20 @@ func IsErrReleaseNotExist(err error) bool {
|
||||
}
|
||||
|
||||
func (err ErrReleaseNotExist) Error() string {
|
||||
return fmt.Sprintf("Release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
|
||||
return fmt.Sprintf("release tag does not exist [id: %d, tag_name: %s]", err.ID, err.TagName)
|
||||
}
|
||||
|
||||
type ErrInvalidTagName struct {
|
||||
TagName string
|
||||
}
|
||||
|
||||
func IsErrInvalidTagName(err error) bool {
|
||||
_, ok := err.(ErrInvalidTagName)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrInvalidTagName) Error() string {
|
||||
return fmt.Sprintf("release tag name is not valid [tag_name: %s]", err.TagName)
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
@@ -421,7 +434,7 @@ func IsErrBranchNotExist(err error) bool {
|
||||
}
|
||||
|
||||
func (err ErrBranchNotExist) Error() string {
|
||||
return fmt.Sprintf("Branch does not exist [name: %s]", err.Name)
|
||||
return fmt.Sprintf("branch does not exist [name: %s]", err.Name)
|
||||
}
|
||||
|
||||
// __ __ ___. .__ __
|
||||
@@ -520,7 +533,8 @@ func (err ErrCommentNotExist) Error() string {
|
||||
// \/ \/ \/ \/
|
||||
|
||||
type ErrLabelNotExist struct {
|
||||
ID int64
|
||||
LabelID int64
|
||||
RepoID int64
|
||||
}
|
||||
|
||||
func IsErrLabelNotExist(err error) bool {
|
||||
@@ -529,7 +543,7 @@ func IsErrLabelNotExist(err error) bool {
|
||||
}
|
||||
|
||||
func (err ErrLabelNotExist) Error() string {
|
||||
return fmt.Sprintf("label does not exist [id: %d]", err.ID)
|
||||
return fmt.Sprintf("label does not exist [label_id: %d, repo_id: %d]", err.LabelID, err.RepoID)
|
||||
}
|
||||
|
||||
// _____ .__.__ __
|
||||
|
||||
@@ -160,6 +160,7 @@ type DiffFile struct {
|
||||
IsDeleted bool
|
||||
IsBin bool
|
||||
IsRenamed bool
|
||||
IsSubmodule bool
|
||||
Sections []*DiffSection
|
||||
IsIncomplete bool
|
||||
}
|
||||
@@ -184,6 +185,7 @@ func (diff *Diff) NumFiles() int {
|
||||
|
||||
const DIFF_HEAD = "diff --git "
|
||||
|
||||
// TODO: move this function to gogits/git-module
|
||||
func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*Diff, error) {
|
||||
var (
|
||||
diff = &Diff{Files: make([]*DiffFile, 0)}
|
||||
@@ -306,7 +308,7 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
|
||||
}
|
||||
curFileLinesCount = 0
|
||||
|
||||
// Check file diff type.
|
||||
// Check file diff type and is submodule.
|
||||
for {
|
||||
line, err := input.ReadString('\n')
|
||||
if err != nil {
|
||||
@@ -333,6 +335,9 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
|
||||
curFile.Name = b
|
||||
}
|
||||
if curFile.Type > 0 {
|
||||
if strings.HasSuffix(line, " 160000\n") {
|
||||
curFile.IsSubmodule = true
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -367,13 +372,13 @@ func ParsePatch(maxLines, maxLineCharacteres, maxFiles int, reader io.Reader) (*
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
func GetDiffRange(repoPath, beforeCommitID string, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
|
||||
repo, err := git.OpenRepository(repoPath)
|
||||
func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
|
||||
gitRepo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
commit, err := repo.GetCommit(afterCommitID)
|
||||
commit, err := gitRepo.GetCommit(afterCommitID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -418,6 +423,59 @@ func GetDiffRange(repoPath, beforeCommitID string, afterCommitID string, maxLine
|
||||
return diff, nil
|
||||
}
|
||||
|
||||
func GetDiffCommit(repoPath, commitId string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
|
||||
return GetDiffRange(repoPath, "", commitId, maxLines, maxLineCharacteres, maxFiles)
|
||||
type RawDiffType string
|
||||
|
||||
const (
|
||||
RAW_DIFF_NORMAL RawDiffType = "diff"
|
||||
RAW_DIFF_PATCH RawDiffType = "patch"
|
||||
)
|
||||
|
||||
// GetRawDiff dumps diff results of repository in given commit ID to io.Writer.
|
||||
// TODO: move this function to gogits/git-module
|
||||
func GetRawDiff(repoPath, commitID string, diffType RawDiffType, writer io.Writer) error {
|
||||
repo, err := git.OpenRepository(repoPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("OpenRepository: %v", err)
|
||||
}
|
||||
|
||||
commit, err := repo.GetCommit(commitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetCommit: %v", err)
|
||||
}
|
||||
|
||||
var cmd *exec.Cmd
|
||||
switch diffType {
|
||||
case RAW_DIFF_NORMAL:
|
||||
if commit.ParentCount() == 0 {
|
||||
cmd = exec.Command("git", "show", commitID)
|
||||
} else {
|
||||
c, _ := commit.Parent(0)
|
||||
cmd = exec.Command("git", "diff", "-M", c.ID.String(), commitID)
|
||||
}
|
||||
case RAW_DIFF_PATCH:
|
||||
if commit.ParentCount() == 0 {
|
||||
cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", "--root", commitID)
|
||||
} else {
|
||||
c, _ := commit.Parent(0)
|
||||
query := fmt.Sprintf("%s...%s", commitID, c.ID.String())
|
||||
cmd = exec.Command("git", "format-patch", "--no-signature", "--stdout", query)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid diffType: %s", diffType)
|
||||
}
|
||||
|
||||
stderr := new(bytes.Buffer)
|
||||
|
||||
cmd.Dir = repoPath
|
||||
cmd.Stdout = writer
|
||||
cmd.Stderr = stderr
|
||||
|
||||
if err = cmd.Run(); err != nil {
|
||||
return fmt.Errorf("Run: %v - %s", err, stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetDiffCommit(repoPath, commitID string, maxLines, maxLineCharacteres, maxFiles int) (*Diff, error) {
|
||||
return GetDiffRange(repoPath, "", commitID, maxLines, maxLineCharacteres, maxFiles)
|
||||
}
|
||||
|
||||
@@ -64,13 +64,13 @@ type Issue struct {
|
||||
}
|
||||
|
||||
func (i *Issue) BeforeInsert() {
|
||||
i.CreatedUnix = time.Now().UTC().Unix()
|
||||
i.CreatedUnix = time.Now().Unix()
|
||||
i.UpdatedUnix = i.CreatedUnix
|
||||
}
|
||||
|
||||
func (i *Issue) BeforeUpdate() {
|
||||
i.UpdatedUnix = time.Now().UTC().Unix()
|
||||
i.DeadlineUnix = i.Deadline.UTC().Unix()
|
||||
i.UpdatedUnix = time.Now().Unix()
|
||||
i.DeadlineUnix = i.Deadline.Unix()
|
||||
}
|
||||
|
||||
func (issue *Issue) loadAttributes(e Engine) (err error) {
|
||||
@@ -82,7 +82,7 @@ func (issue *Issue) loadAttributes(e Engine) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (issue *Issue) LoadAttributes() (err error) {
|
||||
func (issue *Issue) LoadAttributes() error {
|
||||
return issue.loadAttributes(x)
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ func (i *Issue) addLabel(e *xorm.Session, label *Label) error {
|
||||
return newIssueLabel(e, i, label)
|
||||
}
|
||||
|
||||
// AddLabel adds new label to issue by given ID.
|
||||
// AddLabel adds a new label to the issue.
|
||||
func (i *Issue) AddLabel(label *Label) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
@@ -196,52 +196,76 @@ func (i *Issue) AddLabel(label *Label) (err error) {
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func (i *Issue) getLabels(e Engine) (err error) {
|
||||
if len(i.Labels) > 0 {
|
||||
func (issue *Issue) addLabels(e *xorm.Session, labels []*Label) error {
|
||||
return newIssueLabels(e, issue, labels)
|
||||
}
|
||||
|
||||
// AddLabels adds a list of new labels to the issue.
|
||||
func (issue *Issue) AddLabels(labels []*Label) error {
|
||||
return NewIssueLabels(issue, labels)
|
||||
}
|
||||
|
||||
func (issue *Issue) getLabels(e Engine) (err error) {
|
||||
if len(issue.Labels) > 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
i.Labels, err = getLabelsByIssueID(e, i.ID)
|
||||
issue.Labels, err = getLabelsByIssueID(e, issue.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getLabelsByIssueID: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Issue) removeLabel(e *xorm.Session, label *Label) error {
|
||||
return deleteIssueLabel(e, i, label)
|
||||
func (issue *Issue) removeLabel(e *xorm.Session, label *Label) error {
|
||||
return deleteIssueLabel(e, issue, label)
|
||||
}
|
||||
|
||||
// RemoveLabel removes a label from issue by given ID.
|
||||
func (i *Issue) RemoveLabel(label *Label) (err error) {
|
||||
func (issue *Issue) RemoveLabel(label *Label) (err error) {
|
||||
return DeleteIssueLabel(issue, label)
|
||||
}
|
||||
|
||||
func (issue *Issue) clearLabels(e *xorm.Session) (err error) {
|
||||
if err = issue.getLabels(e); err != nil {
|
||||
return fmt.Errorf("getLabels: %v", err)
|
||||
}
|
||||
|
||||
for i := range issue.Labels {
|
||||
if err = issue.removeLabel(e, issue.Labels[i]); err != nil {
|
||||
return fmt.Errorf("removeLabel: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (issue *Issue) ClearLabels() (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = i.removeLabel(sess, label); err != nil {
|
||||
if err = issue.clearLabels(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func (i *Issue) ClearLabels() (err error) {
|
||||
// ReplaceLabels removes all current labels and add new labels to the issue.
|
||||
func (issue *Issue) ReplaceLabels(labels []*Label) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = i.getLabels(sess); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for idx := range i.Labels {
|
||||
if err = i.removeLabel(sess, i.Labels[idx]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = issue.clearLabels(sess); err != nil {
|
||||
return fmt.Errorf("clearLabels: %v", err)
|
||||
} else if err = issue.addLabels(sess, labels); err != nil {
|
||||
return fmt.Errorf("addLabels: %v", err)
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
@@ -336,7 +360,7 @@ func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64,
|
||||
|
||||
if issue.AssigneeID > 0 {
|
||||
// Silently drop invalid assignee
|
||||
valid, err := hasAccess(e, &User{Id: issue.AssigneeID}, repo, ACCESS_MODE_WRITE)
|
||||
valid, err := hasAccess(e, &User{ID: issue.AssigneeID}, repo, ACCESS_MODE_WRITE)
|
||||
if err != nil {
|
||||
return fmt.Errorf("hasAccess: %v", err)
|
||||
} else if !valid {
|
||||
@@ -428,7 +452,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
|
||||
|
||||
// Notify watchers.
|
||||
act := &Action{
|
||||
ActUserID: issue.Poster.Id,
|
||||
ActUserID: issue.Poster.ID,
|
||||
ActUserName: issue.Poster.Name,
|
||||
ActEmail: issue.Poster.Email,
|
||||
OpType: ACTION_CREATE_ISSUE,
|
||||
@@ -521,7 +545,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||
opts.Page = 1
|
||||
}
|
||||
|
||||
sess := x.Limit(setting.IssuePagingNum, (opts.Page-1)*setting.IssuePagingNum)
|
||||
sess := x.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)
|
||||
|
||||
if opts.RepoID > 0 {
|
||||
sess.Where("issue.repo_id=?", opts.RepoID).And("issue.is_closed=?", opts.IsClosed)
|
||||
@@ -567,7 +591,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||
if len(opts.Labels) > 0 && opts.Labels != "0" {
|
||||
labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
|
||||
if len(labelIDs) > 0 {
|
||||
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").In("issue.label_id", labelIDs)
|
||||
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").In("issue_label.label_id", labelIDs)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,7 +603,7 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
||||
}
|
||||
}
|
||||
|
||||
issues := make([]*Issue, 0, setting.IssuePagingNum)
|
||||
issues := make([]*Issue, 0, setting.UI.IssuePagingNum)
|
||||
return issues, sess.Find(&issues)
|
||||
}
|
||||
|
||||
@@ -632,7 +656,7 @@ func newIssueUsers(e *xorm.Session, repo *Repository, issue *Issue) error {
|
||||
isNeedAddPoster := true
|
||||
for _, u := range users {
|
||||
iu.ID = 0
|
||||
iu.UID = u.Id
|
||||
iu.UID = u.ID
|
||||
iu.IsPoster = iu.UID == issue.PosterID
|
||||
if isNeedAddPoster && iu.IsPoster {
|
||||
isNeedAddPoster = false
|
||||
@@ -736,15 +760,15 @@ func UpdateIssueMentions(issueID int64, mentions []string) error {
|
||||
|
||||
ids := make([]int64, 0, len(mentions))
|
||||
for _, user := range users {
|
||||
ids = append(ids, user.Id)
|
||||
ids = append(ids, user.ID)
|
||||
if !user.IsOrganization() || user.NumMembers == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
memberIDs := make([]int64, 0, user.NumMembers)
|
||||
orgUsers, err := GetOrgUsersByOrgID(user.Id)
|
||||
orgUsers, err := GetOrgUsersByOrgID(user.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetOrgUsersByOrgID [%d]: %v", user.Id, err)
|
||||
return fmt.Errorf("GetOrgUsersByOrgID [%d]: %v", user.ID, err)
|
||||
}
|
||||
|
||||
for _, orgUser := range orgUsers {
|
||||
@@ -1046,7 +1070,7 @@ type Milestone struct {
|
||||
}
|
||||
|
||||
func (m *Milestone) BeforeInsert() {
|
||||
m.DeadlineUnix = m.Deadline.UTC().Unix()
|
||||
m.DeadlineUnix = m.Deadline.Unix()
|
||||
}
|
||||
|
||||
func (m *Milestone) BeforeUpdate() {
|
||||
@@ -1056,8 +1080,8 @@ func (m *Milestone) BeforeUpdate() {
|
||||
m.Completeness = 0
|
||||
}
|
||||
|
||||
m.DeadlineUnix = m.Deadline.UTC().Unix()
|
||||
m.ClosedDateUnix = m.ClosedDate.UTC().Unix()
|
||||
m.DeadlineUnix = m.Deadline.Unix()
|
||||
m.ClosedDateUnix = m.ClosedDate.Unix()
|
||||
}
|
||||
|
||||
func (m *Milestone) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -1143,10 +1167,10 @@ func GetAllRepoMilestones(repoID int64) ([]*Milestone, error) {
|
||||
|
||||
// GetMilestones returns a list of milestones of given repository and status.
|
||||
func GetMilestones(repoID int64, page int, isClosed bool) ([]*Milestone, error) {
|
||||
miles := make([]*Milestone, 0, setting.IssuePagingNum)
|
||||
miles := make([]*Milestone, 0, setting.UI.IssuePagingNum)
|
||||
sess := x.Where("repo_id=? AND is_closed=?", repoID, isClosed)
|
||||
if page > 0 {
|
||||
sess = sess.Limit(setting.IssuePagingNum, (page-1)*setting.IssuePagingNum)
|
||||
sess = sess.Limit(setting.UI.IssuePagingNum, (page-1)*setting.UI.IssuePagingNum)
|
||||
}
|
||||
return miles, sess.Find(&miles)
|
||||
}
|
||||
@@ -1361,7 +1385,7 @@ type Attachment struct {
|
||||
}
|
||||
|
||||
func (a *Attachment) BeforeInsert() {
|
||||
a.CreatedUnix = time.Now().UTC().Unix()
|
||||
a.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (a *Attachment) AfterSet(colName string, _ xorm.Cell) {
|
||||
|
||||
@@ -69,7 +69,7 @@ type Comment struct {
|
||||
}
|
||||
|
||||
func (c *Comment) BeforeInsert() {
|
||||
c.CreatedUnix = time.Now().UTC().Unix()
|
||||
c.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (c *Comment) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -140,7 +140,7 @@ func (cmt *Comment) MailParticipants(opType ActionType, issue *Issue) (err error
|
||||
func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err error) {
|
||||
comment := &Comment{
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.Id,
|
||||
PosterID: opts.Doer.ID,
|
||||
Poster: opts.Doer,
|
||||
IssueID: opts.Issue.ID,
|
||||
CommitID: opts.CommitID,
|
||||
@@ -155,7 +155,7 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
||||
// Compose comment action, could be plain comment, close or reopen issue/pull request.
|
||||
// This object will be used to notify watchers in the end of function.
|
||||
act := &Action{
|
||||
ActUserID: opts.Doer.Id,
|
||||
ActUserID: opts.Doer.ID,
|
||||
ActUserName: opts.Doer.Name,
|
||||
ActEmail: opts.Doer.Email,
|
||||
Content: fmt.Sprintf("%d|%s", opts.Issue.Index, strings.Split(opts.Content, "\n")[0]),
|
||||
@@ -345,3 +345,29 @@ func UpdateComment(c *Comment) error {
|
||||
_, err := x.Id(c.ID).AllCols().Update(c)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCommentByID deletes a comment by given ID.
|
||||
func DeleteCommentByID(id int64) error {
|
||||
comment, err := GetCommentByID(id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Id(comment.ID).Delete(new(Comment)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if comment.Type == COMMENT_TYPE_COMMENT {
|
||||
if _, err = sess.Exec("UPDATE `issue` SET num_comments = num_comments - 1 WHERE id = ?", comment.IssueID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
)
|
||||
|
||||
// Label represents a label of repository for issues.
|
||||
@@ -56,48 +58,65 @@ func NewLabel(l *Label) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func getLabelByID(e Engine, id int64) (*Label, error) {
|
||||
if id <= 0 {
|
||||
return nil, ErrLabelNotExist{id}
|
||||
// getLabelInRepoByID returns a label by ID in given repository.
|
||||
// If pass repoID as 0, then ORM will ignore limitation of repository
|
||||
// and can return arbitrary label with any valid ID.
|
||||
func getLabelInRepoByID(e Engine, repoID, labelID int64) (*Label, error) {
|
||||
if labelID <= 0 {
|
||||
return nil, ErrLabelNotExist{labelID, repoID}
|
||||
}
|
||||
|
||||
l := &Label{ID: id}
|
||||
l := &Label{
|
||||
ID: labelID,
|
||||
RepoID: repoID,
|
||||
}
|
||||
has, err := x.Get(l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
return nil, ErrLabelNotExist{l.ID}
|
||||
return nil, ErrLabelNotExist{l.ID, l.RepoID}
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// GetLabelByID returns a label by given ID.
|
||||
func GetLabelByID(id int64) (*Label, error) {
|
||||
return getLabelByID(x, id)
|
||||
return getLabelInRepoByID(x, 0, id)
|
||||
}
|
||||
|
||||
// GetLabelInRepoByID returns a label by ID in given repository.
|
||||
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) {
|
||||
return getLabelInRepoByID(x, repoID, labelID)
|
||||
}
|
||||
|
||||
// GetLabelsInRepoByIDs returns a list of labels by IDs in given repository,
|
||||
// it silently ignores label IDs that are not belong to the repository.
|
||||
func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
return labels, x.Where("repo_id = ?", repoID).In("id", base.Int64sToStrings(labelIDs)).Find(&labels)
|
||||
}
|
||||
|
||||
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
|
||||
func GetLabelsByRepoID(repoID int64) ([]*Label, error) {
|
||||
labels := make([]*Label, 0, 10)
|
||||
return labels, x.Where("repo_id=?", repoID).Find(&labels)
|
||||
return labels, x.Where("repo_id = ?", repoID).Find(&labels)
|
||||
}
|
||||
|
||||
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
|
||||
issueLabels, err := getIssueLabels(e, issueID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getIssueLabels: %v", err)
|
||||
} else if len(issueLabels) == 0 {
|
||||
return []*Label{}, nil
|
||||
}
|
||||
|
||||
var label *Label
|
||||
labels := make([]*Label, 0, len(issueLabels))
|
||||
for idx := range issueLabels {
|
||||
label, err = getLabelByID(e, issueLabels[idx].LabelID)
|
||||
if err != nil && !IsErrLabelNotExist(err) {
|
||||
return nil, fmt.Errorf("getLabelByID: %v", err)
|
||||
}
|
||||
labels = append(labels, label)
|
||||
labelIDs := make([]int64, len(issueLabels))
|
||||
for i := range issueLabels {
|
||||
labelIDs[i] = issueLabels[i].LabelID
|
||||
}
|
||||
return labels, nil
|
||||
|
||||
labels := make([]*Label, 0, len(labelIDs))
|
||||
return labels, e.Where("id > 0").In("id", base.Int64sToStrings(labelIDs)).Find(&labels)
|
||||
}
|
||||
|
||||
// GetLabelsByIssueID returns all labels that belong to given issue by ID.
|
||||
@@ -117,7 +136,7 @@ func UpdateLabel(l *Label) error {
|
||||
|
||||
// DeleteLabel delete a label of given repository.
|
||||
func DeleteLabel(repoID, labelID int64) error {
|
||||
l, err := GetLabelByID(labelID)
|
||||
_, err := GetLabelInRepoByID(repoID, labelID)
|
||||
if err != nil {
|
||||
if IsErrLabelNotExist(err) {
|
||||
return nil
|
||||
@@ -131,11 +150,12 @@ func DeleteLabel(repoID, labelID int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = x.Where("label_id=?", labelID).Delete(new(IssueLabel)); err != nil {
|
||||
if _, err = sess.Id(labelID).Delete(new(Label)); err != nil {
|
||||
return err
|
||||
} else if _, err = sess.Delete(l); err != nil {
|
||||
} else if _, err = sess.Where("label_id = ?", labelID).Delete(new(IssueLabel)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
@@ -154,7 +174,7 @@ type IssueLabel struct {
|
||||
}
|
||||
|
||||
func hasIssueLabel(e Engine, issueID, labelID int64) bool {
|
||||
has, _ := e.Where("issue_id=? AND label_id=?", issueID, labelID).Get(new(IssueLabel))
|
||||
has, _ := e.Where("issue_id = ? AND label_id = ?", issueID, labelID).Get(new(IssueLabel))
|
||||
return has
|
||||
}
|
||||
|
||||
@@ -180,6 +200,10 @@ func newIssueLabel(e *xorm.Session, issue *Issue, label *Label) (err error) {
|
||||
|
||||
// NewIssueLabel creates a new issue-label relation.
|
||||
func NewIssueLabel(issue *Issue, label *Label) (err error) {
|
||||
if HasIssueLabel(issue.ID, label.ID) {
|
||||
return nil
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
@@ -193,6 +217,35 @@ func NewIssueLabel(issue *Issue, label *Label) (err error) {
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func newIssueLabels(e *xorm.Session, issue *Issue, labels []*Label) (err error) {
|
||||
for i := range labels {
|
||||
if hasIssueLabel(e, issue.ID, labels[i].ID) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err = newIssueLabel(e, issue, labels[i]); err != nil {
|
||||
return fmt.Errorf("newIssueLabel: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewIssueLabels creates a list of issue-label relations.
|
||||
func NewIssueLabels(issue *Issue, labels []*Label) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = newIssueLabels(sess, issue, labels); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
func getIssueLabels(e Engine, issueID int64) ([]*IssueLabel, error) {
|
||||
issueLabels := make([]*IssueLabel, 0, 10)
|
||||
return issueLabels, e.Where("issue_id=?", issueID).Asc("label_id").Find(&issueLabels)
|
||||
|
||||
@@ -33,7 +33,7 @@ func mailIssueCommentToParticipants(issue *Issue, doer *User, mentions []string)
|
||||
tos := make([]string, 0, len(watchers)) // List of email addresses.
|
||||
names := make([]string, 0, len(watchers))
|
||||
for i := range watchers {
|
||||
if watchers[i].UserID == doer.Id {
|
||||
if watchers[i].UserID == doer.ID {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -120,12 +120,12 @@ type LoginSource struct {
|
||||
}
|
||||
|
||||
func (s *LoginSource) BeforeInsert() {
|
||||
s.CreatedUnix = time.Now().UTC().Unix()
|
||||
s.CreatedUnix = time.Now().Unix()
|
||||
s.UpdatedUnix = s.CreatedUnix
|
||||
}
|
||||
|
||||
func (s *LoginSource) BeforeUpdate() {
|
||||
s.UpdatedUnix = time.Now().UTC().Unix()
|
||||
s.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Cell2Int64 converts a xorm.Cell type to int64,
|
||||
@@ -534,7 +534,7 @@ func UserSignIn(uname, passwd string) (*User, error) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
return nil, ErrUserNotExist{u.Id, u.Name}
|
||||
return nil, ErrUserNotExist{u.ID, u.Name}
|
||||
|
||||
default:
|
||||
var source LoginSource
|
||||
@@ -563,5 +563,5 @@ func UserSignIn(uname, passwd string) (*User, error) {
|
||||
log.Warn("Failed to login '%s' via '%s': %v", uname, source.Name, err)
|
||||
}
|
||||
|
||||
return nil, ErrUserNotExist{u.Id, u.Name}
|
||||
return nil, ErrUserNotExist{u.ID, u.Name}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func SendUserMail(c *macaron.Context, u *User, tpl base.TplName, code, subject,
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, %s", u.Id, info)
|
||||
msg.Info = fmt.Sprintf("UID: %d, %s", u.ID, info)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
}
|
||||
@@ -99,7 +99,7 @@ func SendActivateEmailMail(c *macaron.Context, u *User, email *EmailAddress) {
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{email.Email}, c.Tr("mail.activate_email"), body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, activate email", u.Id)
|
||||
msg.Info = fmt.Sprintf("UID: %d, activate email", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func SendRegisterNotifyMail(c *macaron.Context, u *User) {
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, c.Tr("mail.register_notify"), body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.Id)
|
||||
msg.Info = fmt.Sprintf("UID: %d, registration notify", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
}
|
||||
@@ -138,7 +138,7 @@ func SendCollaboratorMail(u, doer *User, repo *Repository) {
|
||||
}
|
||||
|
||||
msg := mailer.NewMessage([]string{u.Email}, subject, body)
|
||||
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.Id)
|
||||
msg.Info = fmt.Sprintf("UID: %d, add collaborator", u.ID)
|
||||
|
||||
mailer.SendAsync(msg)
|
||||
}
|
||||
|
||||
@@ -646,17 +646,17 @@ func convertDateToUnix(x *xorm.Engine) (err error) {
|
||||
if bean.Deadline.IsZero() {
|
||||
continue
|
||||
}
|
||||
fieldSQL += com.ToStr(bean.Deadline.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.Deadline.Unix())
|
||||
case "created":
|
||||
fieldSQL += com.ToStr(bean.Created.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.Created.Unix())
|
||||
case "updated":
|
||||
fieldSQL += com.ToStr(bean.Updated.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.Updated.Unix())
|
||||
case "closed_date":
|
||||
fieldSQL += com.ToStr(bean.ClosedDate.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.ClosedDate.Unix())
|
||||
case "merged":
|
||||
fieldSQL += com.ToStr(bean.Merged.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.Merged.Unix())
|
||||
case "next_update":
|
||||
fieldSQL += com.ToStr(bean.NextUpdate.UTC().Unix())
|
||||
fieldSQL += com.ToStr(bean.NextUpdate.Unix())
|
||||
}
|
||||
|
||||
valSQLs = append(valSQLs, fieldSQL)
|
||||
|
||||
@@ -27,9 +27,10 @@ type Engine interface {
|
||||
Exec(string, ...interface{}) (sql.Result, error)
|
||||
Find(interface{}, ...interface{}) error
|
||||
Get(interface{}) (bool, error)
|
||||
Id(interface{}) *xorm.Session
|
||||
Insert(...interface{}) (int64, error)
|
||||
InsertOne(interface{}) (int64, error)
|
||||
Id(interface{}) *xorm.Session
|
||||
Iterate(interface{}, xorm.IterFunc) error
|
||||
Sql(string, ...interface{}) *xorm.Session
|
||||
Where(string, ...interface{}) *xorm.Session
|
||||
}
|
||||
@@ -98,8 +99,8 @@ func LoadConfigs() {
|
||||
func getEngine() (*xorm.Engine, error) {
|
||||
cnnstr := ""
|
||||
var Param string = "?"
|
||||
if strings.Contains(DbCfg.Name,Param) {
|
||||
Param="&"
|
||||
if strings.Contains(DbCfg.Name, Param) {
|
||||
Param = "&"
|
||||
}
|
||||
switch DbCfg.Type {
|
||||
case "mysql":
|
||||
@@ -206,7 +207,7 @@ func GetStatistic() (stats Statistic) {
|
||||
stats.Counter.User = CountUsers()
|
||||
stats.Counter.Org = CountOrganizations()
|
||||
stats.Counter.PublicKey, _ = x.Count(new(PublicKey))
|
||||
stats.Counter.Repo = CountRepositories()
|
||||
stats.Counter.Repo = CountRepositories(true)
|
||||
stats.Counter.Watch, _ = x.Count(new(Watch))
|
||||
stats.Counter.Star, _ = x.Count(new(Star))
|
||||
stats.Counter.Action, _ = x.Count(new(Action))
|
||||
|
||||
219
models/org.go
219
models/org.go
@@ -10,8 +10,10 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -21,16 +23,16 @@ var (
|
||||
|
||||
// IsOwnedBy returns true if given user is in the owner team.
|
||||
func (org *User) IsOwnedBy(uid int64) bool {
|
||||
return IsOrganizationOwner(org.Id, uid)
|
||||
return IsOrganizationOwner(org.ID, uid)
|
||||
}
|
||||
|
||||
// IsOrgMember returns true if given user is member of organization.
|
||||
func (org *User) IsOrgMember(uid int64) bool {
|
||||
return org.IsOrganization() && IsOrganizationMember(org.Id, uid)
|
||||
return org.IsOrganization() && IsOrganizationMember(org.ID, uid)
|
||||
}
|
||||
|
||||
func (org *User) getTeam(e Engine, name string) (*Team, error) {
|
||||
return getTeam(e, org.Id, name)
|
||||
return getTeam(e, org.ID, name)
|
||||
}
|
||||
|
||||
// GetTeam returns named team of organization.
|
||||
@@ -48,7 +50,7 @@ func (org *User) GetOwnerTeam() (*Team, error) {
|
||||
}
|
||||
|
||||
func (org *User) getTeams(e Engine) error {
|
||||
return e.Where("org_id=?", org.Id).Find(&org.Teams)
|
||||
return e.Where("org_id=?", org.ID).Find(&org.Teams)
|
||||
}
|
||||
|
||||
// GetTeams returns all teams that belong to organization.
|
||||
@@ -58,7 +60,7 @@ func (org *User) GetTeams() error {
|
||||
|
||||
// GetMembers returns all members of organization.
|
||||
func (org *User) GetMembers() error {
|
||||
ous, err := GetOrgUsersByOrgID(org.Id)
|
||||
ous, err := GetOrgUsersByOrgID(org.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -75,16 +77,16 @@ func (org *User) GetMembers() error {
|
||||
|
||||
// AddMember adds new member to organization.
|
||||
func (org *User) AddMember(uid int64) error {
|
||||
return AddOrgUser(org.Id, uid)
|
||||
return AddOrgUser(org.ID, uid)
|
||||
}
|
||||
|
||||
// RemoveMember removes member from organization.
|
||||
func (org *User) RemoveMember(uid int64) error {
|
||||
return RemoveOrgUser(org.Id, uid)
|
||||
return RemoveOrgUser(org.ID, uid)
|
||||
}
|
||||
|
||||
func (org *User) removeOrgRepo(e Engine, repoID int64) error {
|
||||
return removeOrgRepo(e, org.Id, repoID)
|
||||
return removeOrgRepo(e, org.ID, repoID)
|
||||
}
|
||||
|
||||
// RemoveOrgRepo removes all team-repository relations of organization.
|
||||
@@ -94,7 +96,7 @@ func (org *User) RemoveOrgRepo(repoID int64) error {
|
||||
|
||||
// CreateOrganization creates record of a new organization.
|
||||
func CreateOrganization(org, owner *User) (err error) {
|
||||
if err = IsUsableName(org.Name); err != nil {
|
||||
if err = IsUsableUsername(org.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -106,7 +108,6 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
}
|
||||
|
||||
org.LowerName = strings.ToLower(org.Name)
|
||||
org.FullName = org.Name
|
||||
org.Rands = GetUserSalt()
|
||||
org.Salt = GetUserSalt()
|
||||
org.UseCustomAvatar = true
|
||||
@@ -127,8 +128,8 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
|
||||
// Add initial creator to organization and owner team.
|
||||
if _, err = sess.Insert(&OrgUser{
|
||||
Uid: owner.Id,
|
||||
OrgID: org.Id,
|
||||
Uid: owner.ID,
|
||||
OrgID: org.ID,
|
||||
IsOwner: true,
|
||||
NumTeams: 1,
|
||||
}); err != nil {
|
||||
@@ -137,7 +138,7 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
|
||||
// Create default owner team.
|
||||
t := &Team{
|
||||
OrgID: org.Id,
|
||||
OrgID: org.ID,
|
||||
LowerName: strings.ToLower(OWNER_TEAM),
|
||||
Name: OWNER_TEAM,
|
||||
Authorize: ACCESS_MODE_OWNER,
|
||||
@@ -148,8 +149,8 @@ func CreateOrganization(org, owner *User) (err error) {
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(&TeamUser{
|
||||
Uid: owner.Id,
|
||||
OrgID: org.Id,
|
||||
Uid: owner.ID,
|
||||
OrgID: org.ID,
|
||||
TeamID: t.ID,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("insert team-user relation: %v", err)
|
||||
@@ -205,9 +206,9 @@ func DeleteOrganization(org *User) (err error) {
|
||||
}
|
||||
|
||||
if err = deleteBeans(sess,
|
||||
&Team{OrgID: org.Id},
|
||||
&OrgUser{OrgID: org.Id},
|
||||
&TeamUser{OrgID: org.Id},
|
||||
&Team{OrgID: org.ID},
|
||||
&OrgUser{OrgID: org.ID},
|
||||
&TeamUser{OrgID: org.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
@@ -314,9 +315,9 @@ func GetOrgUsersByOrgID(orgID int64) ([]*OrgUser, error) {
|
||||
}
|
||||
|
||||
// ChangeOrgUserStatus changes public or private membership status.
|
||||
func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
|
||||
func ChangeOrgUserStatus(orgID, uid int64, public bool) error {
|
||||
ou := new(OrgUser)
|
||||
has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
|
||||
has, err := x.Where("uid=?", uid).And("org_id=?", orgID).Get(ou)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
@@ -329,8 +330,8 @@ func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
|
||||
}
|
||||
|
||||
// AddOrgUser adds new user to given organization.
|
||||
func AddOrgUser(orgId, uid int64) error {
|
||||
if IsOrganizationMember(orgId, uid) {
|
||||
func AddOrgUser(orgID, uid int64) error {
|
||||
if IsOrganizationMember(orgID, uid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -342,13 +343,13 @@ func AddOrgUser(orgId, uid int64) error {
|
||||
|
||||
ou := &OrgUser{
|
||||
Uid: uid,
|
||||
OrgID: orgId,
|
||||
OrgID: orgID,
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(ou); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgId); err != nil {
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgID); err != nil {
|
||||
sess.Rollback()
|
||||
return err
|
||||
}
|
||||
@@ -357,35 +358,39 @@ func AddOrgUser(orgId, uid int64) error {
|
||||
}
|
||||
|
||||
// RemoveOrgUser removes user from given organization.
|
||||
func RemoveOrgUser(orgId, uid int64) error {
|
||||
func RemoveOrgUser(orgID, userID int64) error {
|
||||
ou := new(OrgUser)
|
||||
|
||||
has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
|
||||
has, err := x.Where("uid=?", userID).And("org_id=?", orgID).Get(ou)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get org-user: %v", err)
|
||||
} else if !has {
|
||||
return nil
|
||||
}
|
||||
|
||||
u, err := GetUserByID(uid)
|
||||
user, err := GetUserByID(userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetUserById: %v", err)
|
||||
return fmt.Errorf("GetUserByID [%d]: %v", userID, err)
|
||||
}
|
||||
org, err := GetUserByID(orgId)
|
||||
org, err := GetUserByID(orgID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get organization: %v", err)
|
||||
} else if err = org.GetRepositories(); err != nil {
|
||||
return fmt.Errorf("GetRepositories: %v", err)
|
||||
return fmt.Errorf("GetUserByID [%d]: %v", orgID, err)
|
||||
}
|
||||
|
||||
// FIXME: only need to get IDs here, not all fields of repository.
|
||||
repos, _, err := org.GetUserRepositories(user.ID, 1, org.NumRepos)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetUserRepositories [%d]: %v", user.ID, err)
|
||||
}
|
||||
|
||||
// Check if the user to delete is the last member in owner team.
|
||||
if IsOrganizationOwner(orgId, uid) {
|
||||
if IsOrganizationOwner(orgID, userID) {
|
||||
t, err := org.GetOwnerTeam()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t.NumMembers == 1 {
|
||||
return ErrLastOrgOwner{UID: uid}
|
||||
return ErrLastOrgOwner{UID: userID}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,28 +402,29 @@ func RemoveOrgUser(orgId, uid int64) error {
|
||||
|
||||
if _, err := sess.Id(ou.ID).Delete(ou); err != nil {
|
||||
return err
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgId); err != nil {
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete all repository accesses.
|
||||
access := &Access{UserID: u.Id}
|
||||
for _, repo := range org.Repos {
|
||||
access.RepoID = repo.ID
|
||||
if _, err = sess.Delete(access); err != nil {
|
||||
return err
|
||||
} else if err = watchRepo(sess, u.Id, repo.ID, false); err != nil {
|
||||
// Delete all repository accesses and unwatch them.
|
||||
repoIDs := make([]int64, len(repos))
|
||||
for i := range repos {
|
||||
repoIDs = append(repoIDs, repos[i].ID)
|
||||
if err = watchRepo(sess, user.ID, repos[i].ID, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if _, err = sess.Where("user_id = ?", user.ID).In("repo_id", repoIDs).Delete(new(Access)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete member in his/her teams.
|
||||
teams, err := getUserTeams(sess, org.Id, u.Id)
|
||||
teams, err := getUserTeams(sess, org.ID, user.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range teams {
|
||||
if err = removeTeamMember(sess, org.Id, t.ID, u.Id); err != nil {
|
||||
if err = removeTeamMember(sess, org.ID, t.ID, user.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -439,55 +445,100 @@ func RemoveOrgRepo(orgID, repoID int64) error {
|
||||
return removeOrgRepo(x, orgID, repoID)
|
||||
}
|
||||
|
||||
// GetUserRepositories gets all repositories of an organization,
|
||||
// that the user with the given userID has access to.
|
||||
func (org *User) GetUserRepositories(userID int64) (err error) {
|
||||
func (org *User) getUserTeams(e Engine, userID int64, cols ...string) ([]*Team, error) {
|
||||
teams := make([]*Team, 0, org.NumTeams)
|
||||
if err = x.Sql(`SELECT team.id FROM team
|
||||
INNER JOIN team_user ON team_user.team_id = team.id
|
||||
WHERE team_user.org_id = ? AND team_user.uid = ?`, org.Id, userID).Find(&teams); err != nil {
|
||||
return fmt.Errorf("get teams: %v", err)
|
||||
return teams, e.Where("team_user.org_id = ?", org.ID).
|
||||
And("team_user.uid = ?", userID).
|
||||
Join("INNER", "team_user", "team_user.team_id = team.id").
|
||||
Cols(cols...).Find(&teams)
|
||||
}
|
||||
|
||||
// GetUserTeamIDs returns of all team IDs of the organization that user is memeber of.
|
||||
func (org *User) GetUserTeamIDs(userID int64) ([]int64, error) {
|
||||
teams, err := org.getUserTeams(x, userID, "team.id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getUserTeams [%d]: %v", userID, err)
|
||||
}
|
||||
|
||||
teamIDs := make([]string, len(teams))
|
||||
teamIDs := make([]int64, len(teams))
|
||||
for i := range teams {
|
||||
teamIDs[i] = com.ToStr(teams[i].ID)
|
||||
teamIDs[i] = teams[i].ID
|
||||
}
|
||||
if len(teamIDs) == 0 {
|
||||
// user has no team but "IN ()" is invalid SQL
|
||||
teamIDs = append(teamIDs, "-1") // there is no repo with id=-1
|
||||
}
|
||||
|
||||
repos := make([]*Repository, 0, 5)
|
||||
if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
|
||||
INNER JOIN team_repo ON team_repo.repo_id = repository.id
|
||||
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
|
||||
GROUP BY repository.id`, strings.Join(teamIDs, ",")), org.Id, false).Find(&repos); err != nil {
|
||||
return fmt.Errorf("get repositories: %v", err)
|
||||
}
|
||||
org.Repos = repos
|
||||
|
||||
// FIXME: should I change this value inside method,
|
||||
// or only in location of caller where it's really needed?
|
||||
org.NumRepos = len(org.Repos)
|
||||
return nil
|
||||
return teamIDs, nil
|
||||
}
|
||||
|
||||
// GetTeams returns all teams that belong to organization,
|
||||
// and that the user has joined.
|
||||
func (org *User) GetUserTeams(userID int64) error {
|
||||
teams := make([]*Team, 0, 5)
|
||||
if err := x.Sql(`SELECT team.* FROM team
|
||||
INNER JOIN team_user ON team_user.team_id = team.id
|
||||
WHERE team_user.org_id = ? AND team_user.uid = ?`,
|
||||
org.Id, userID).Find(&teams); err != nil {
|
||||
return fmt.Errorf("get teams: %v", err)
|
||||
func (org *User) GetUserTeams(userID int64) ([]*Team, error) {
|
||||
return org.getUserTeams(x, userID)
|
||||
}
|
||||
|
||||
// GetUserRepositories returns a range of repositories in organization
|
||||
// that the user with the given userID has access to,
|
||||
// and total number of records based on given condition.
|
||||
func (org *User) GetUserRepositories(userID int64, page, pageSize int) ([]*Repository, int64, error) {
|
||||
teamIDs, err := org.GetUserTeamIDs(userID)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("GetUserTeamIDs: %v", err)
|
||||
}
|
||||
if len(teamIDs) == 0 {
|
||||
// user has no team but "IN ()" is invalid SQL
|
||||
teamIDs = []int64{-1} // there is no repo with id=-1
|
||||
}
|
||||
|
||||
org.Teams = teams
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
repos := make([]*Repository, 0, pageSize)
|
||||
// FIXME: use XORM chain operations instead of raw SQL.
|
||||
if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
|
||||
INNER JOIN team_repo
|
||||
ON team_repo.repo_id = repository.id
|
||||
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
|
||||
GROUP BY repository.id
|
||||
ORDER BY updated_unix DESC
|
||||
LIMIT %d OFFSET %d`,
|
||||
strings.Join(base.Int64sToStrings(teamIDs), ","), pageSize, (page-1)*pageSize),
|
||||
org.ID, false).Find(&repos); err != nil {
|
||||
return nil, 0, fmt.Errorf("get repositories: %v", err)
|
||||
}
|
||||
|
||||
// FIXME: should I change this value inside method,
|
||||
// or only in location of caller where it's really needed?
|
||||
org.NumTeams = len(org.Teams)
|
||||
return nil
|
||||
results, err := x.Query(fmt.Sprintf(`SELECT repository.id FROM repository
|
||||
INNER JOIN team_repo
|
||||
ON team_repo.repo_id = repository.id
|
||||
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
|
||||
GROUP BY repository.id
|
||||
ORDER BY updated_unix DESC`,
|
||||
strings.Join(base.Int64sToStrings(teamIDs), ",")),
|
||||
org.ID, false)
|
||||
if err != nil {
|
||||
log.Error(4, "count user repositories in organization: %v", err)
|
||||
}
|
||||
|
||||
return repos, int64(len(results)), nil
|
||||
}
|
||||
|
||||
// GetUserRepositories returns mirror repositories of the organization
|
||||
// that the user with the given userID has access to.
|
||||
func (org *User) GetUserMirrorRepositories(userID int64) ([]*Repository, error) {
|
||||
teamIDs, err := org.GetUserTeamIDs(userID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("GetUserTeamIDs: %v", err)
|
||||
}
|
||||
if len(teamIDs) == 0 {
|
||||
teamIDs = []int64{-1}
|
||||
}
|
||||
|
||||
repos := make([]*Repository, 0, 10)
|
||||
if err = x.Sql(fmt.Sprintf(`SELECT repository.* FROM repository
|
||||
INNER JOIN team_repo
|
||||
ON team_repo.repo_id = repository.id AND repository.is_mirror = ?
|
||||
WHERE (repository.owner_id = ? AND repository.is_private = ?) OR team_repo.team_id IN (%s)
|
||||
GROUP BY repository.id
|
||||
ORDER BY updated_unix DESC`,
|
||||
strings.Join(base.Int64sToStrings(teamIDs), ",")),
|
||||
true, org.ID, false).Find(&repos); err != nil {
|
||||
return nil, fmt.Errorf("get repositories: %v", err)
|
||||
}
|
||||
return repos, nil
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ func (t *Team) addRepository(e Engine, repo *Repository) (err error) {
|
||||
return fmt.Errorf("getMembers: %v", err)
|
||||
}
|
||||
for _, u := range t.Members {
|
||||
if err = watchRepo(e, u.Id, repo.ID, true); err != nil {
|
||||
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
|
||||
return fmt.Errorf("watchRepo: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func (t *Team) removeRepository(e Engine, repo *Repository, recalculate bool) (e
|
||||
continue
|
||||
}
|
||||
|
||||
if err = watchRepo(e, u.Id, repo.ID, false); err != nil {
|
||||
if err = watchRepo(e, u.ID, repo.ID, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -341,7 +341,7 @@ func DeleteTeam(t *Team) error {
|
||||
}
|
||||
|
||||
// Delete team-user.
|
||||
if _, err = sess.Where("org_id=?", org.Id).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil {
|
||||
if _, err = sess.Where("org_id=?", org.ID).Where("team_id=?", t.ID).Delete(new(TeamUser)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -538,7 +538,7 @@ func removeTeamMember(e Engine, orgID, teamID, uid int64) error {
|
||||
|
||||
// This must exist.
|
||||
ou := new(OrgUser)
|
||||
_, err = e.Where("uid = ?", uid).And("org_id = ?", org.Id).Get(ou)
|
||||
_, err = e.Where("uid = ?", uid).And("org_id = ?", org.ID).Get(ou)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ type PullRequest struct {
|
||||
}
|
||||
|
||||
func (pr *PullRequest) BeforeUpdate() {
|
||||
pr.MergedUnix = pr.Merged.UTC().Unix()
|
||||
pr.MergedUnix = pr.Merged.Unix()
|
||||
}
|
||||
|
||||
// Note: don't try to get Pull because will end up recursive querying.
|
||||
@@ -163,7 +163,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
|
||||
pr.HasMerged = true
|
||||
pr.Merged = time.Now()
|
||||
pr.MergerID = doer.Id
|
||||
pr.MergerID = doer.ID
|
||||
if _, err = sess.Id(pr.ID).AllCols().Update(pr); err != nil {
|
||||
return fmt.Errorf("update pull request: %v", err)
|
||||
}
|
||||
@@ -245,7 +245,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
||||
},
|
||||
Sender: &api.PayloadUser{
|
||||
UserName: doer.Name,
|
||||
ID: doer.Id,
|
||||
ID: doer.ID,
|
||||
AvatarUrl: setting.AppUrl + doer.RelAvatarLink(),
|
||||
},
|
||||
}
|
||||
@@ -332,7 +332,7 @@ func NewPullRequest(repo *Repository, pull *Issue, labelIDs []int64, uuids []str
|
||||
|
||||
// Notify watchers.
|
||||
act := &Action{
|
||||
ActUserID: pull.Poster.Id,
|
||||
ActUserID: pull.Poster.ID,
|
||||
ActUserName: pull.Poster.Name,
|
||||
ActEmail: pull.Poster.Email,
|
||||
OpType: ACTION_CREATE_PULL_REQUEST,
|
||||
|
||||
@@ -39,7 +39,7 @@ type Release struct {
|
||||
}
|
||||
|
||||
func (r *Release) BeforeInsert() {
|
||||
r.CreatedUnix = time.Now().UTC().Unix()
|
||||
r.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (r *Release) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -67,9 +67,12 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
|
||||
return fmt.Errorf("GetBranchCommit: %v", err)
|
||||
}
|
||||
|
||||
// Trim '--' prefix to prevent command line argument vulnerability
|
||||
// Trim '--' prefix to prevent command line argument vulnerability.
|
||||
rel.TagName = strings.TrimPrefix(rel.TagName, "--")
|
||||
if err = gitRepo.CreateTag(rel.TagName, commit.ID.String()); err != nil {
|
||||
if strings.Contains(err.Error(), "is not a valid tag name") {
|
||||
return ErrInvalidTagName{rel.TagName}
|
||||
}
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -78,6 +81,7 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
|
||||
return fmt.Errorf("GetTagCommit: %v", err)
|
||||
}
|
||||
|
||||
rel.Sha1 = commit.ID.String()
|
||||
rel.NumCommits, err = commit.CommitsCount()
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsCount: %v", err)
|
||||
|
||||
252
models/repo.go
252
models/repo.go
@@ -19,7 +19,6 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
"github.com/Unknwon/com"
|
||||
@@ -185,12 +184,12 @@ type Repository struct {
|
||||
}
|
||||
|
||||
func (repo *Repository) BeforeInsert() {
|
||||
repo.CreatedUnix = time.Now().UTC().Unix()
|
||||
repo.CreatedUnix = time.Now().Unix()
|
||||
repo.UpdatedUnix = repo.CreatedUnix
|
||||
}
|
||||
|
||||
func (repo *Repository) BeforeUpdate() {
|
||||
repo.UpdatedUnix = time.Now().UTC().Unix()
|
||||
repo.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (repo *Repository) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -477,7 +476,7 @@ func (repo *Repository) ComposePayload() *api.PayloadRepo {
|
||||
|
||||
func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) {
|
||||
has, err := e.Get(&Repository{
|
||||
OwnerID: u.Id,
|
||||
OwnerID: u.ID,
|
||||
LowerName: strings.ToLower(repoName),
|
||||
})
|
||||
return has && com.IsDir(RepoPath(u.Name, repoName)), err
|
||||
@@ -517,34 +516,6 @@ func (repo *Repository) CloneLink() (cl *CloneLink) {
|
||||
return repo.cloneLink(false)
|
||||
}
|
||||
|
||||
var (
|
||||
reservedNames = []string{"debug", "raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin", "new", ".", ".."}
|
||||
reservedPatterns = []string{"*.git", "*.keys", "*.wiki"}
|
||||
)
|
||||
|
||||
// IsUsableName checks if name is reserved or pattern of name is not allowed.
|
||||
func IsUsableName(name string) error {
|
||||
name = strings.TrimSpace(strings.ToLower(name))
|
||||
if utf8.RuneCountInString(name) == 0 {
|
||||
return ErrNameEmpty
|
||||
}
|
||||
|
||||
for i := range reservedNames {
|
||||
if name == reservedNames[i] {
|
||||
return ErrNameReserved{name}
|
||||
}
|
||||
}
|
||||
|
||||
for _, pat := range reservedPatterns {
|
||||
if pat[0] == '*' && strings.HasSuffix(name, pat[1:]) ||
|
||||
(pat[len(pat)-1] == '*' && strings.HasPrefix(name, pat[:len(pat)-1])) {
|
||||
return ErrNamePatternNotAllowed{pat}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mirror represents a mirror information of repository.
|
||||
type Mirror struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
@@ -562,12 +533,12 @@ type Mirror struct {
|
||||
}
|
||||
|
||||
func (m *Mirror) BeforeInsert() {
|
||||
m.NextUpdateUnix = m.NextUpdate.UTC().Unix()
|
||||
m.NextUpdateUnix = m.NextUpdate.Unix()
|
||||
}
|
||||
|
||||
func (m *Mirror) BeforeUpdate() {
|
||||
m.UpdatedUnix = time.Now().UTC().Unix()
|
||||
m.NextUpdateUnix = m.NextUpdate.UTC().Unix()
|
||||
m.UpdatedUnix = time.Now().Unix()
|
||||
m.NextUpdateUnix = m.NextUpdate.Unix()
|
||||
}
|
||||
|
||||
func (m *Mirror) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -940,8 +911,17 @@ func initRepository(e Engine, repoPath string, u *User, repo *Repository, opts C
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
reservedRepoNames = []string{".", ".."}
|
||||
reservedRepoPatterns = []string{"*.git", "*.wiki"}
|
||||
)
|
||||
|
||||
func IsUsableRepoName(name string) error {
|
||||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name)
|
||||
}
|
||||
|
||||
func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
if err = IsUsableName(repo.Name); err != nil {
|
||||
if err = IsUsableRepoName(repo.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -978,7 +958,7 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = watchRepo(e, u.Id, repo.ID, true); err != nil {
|
||||
if err = watchRepo(e, u.ID, repo.ID, true); err != nil {
|
||||
return fmt.Errorf("watchRepo: %v", err)
|
||||
} else if err = newRepoAction(e, u, repo); err != nil {
|
||||
return fmt.Errorf("newRepoAction: %v", err)
|
||||
@@ -994,7 +974,7 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
|
||||
}
|
||||
|
||||
repo := &Repository{
|
||||
OwnerID: u.Id,
|
||||
OwnerID: u.ID,
|
||||
Owner: u,
|
||||
Name: opts.Name,
|
||||
LowerName: strings.ToLower(opts.Name),
|
||||
@@ -1038,11 +1018,14 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error
|
||||
return repo, sess.Commit()
|
||||
}
|
||||
|
||||
func countRepositories(showPrivate bool) int64 {
|
||||
sess := x.NewSession()
|
||||
func countRepositories(userID int64, private bool) int64 {
|
||||
sess := x.Where("id > 0")
|
||||
|
||||
if !showPrivate {
|
||||
sess.Where("is_private=?", false)
|
||||
if userID > 0 {
|
||||
sess.And("owner_id = ?", userID)
|
||||
}
|
||||
if !private {
|
||||
sess.And("is_private=?", false)
|
||||
}
|
||||
|
||||
count, err := sess.Count(new(Repository))
|
||||
@@ -1053,13 +1036,17 @@ func countRepositories(showPrivate bool) int64 {
|
||||
}
|
||||
|
||||
// CountRepositories returns number of repositories.
|
||||
func CountRepositories() int64 {
|
||||
return countRepositories(true)
|
||||
// Argument private only takes effect when it is false,
|
||||
// set it true to count all repositories.
|
||||
func CountRepositories(private bool) int64 {
|
||||
return countRepositories(-1, private)
|
||||
}
|
||||
|
||||
// CountPublicRepositories returns number of public repositories.
|
||||
func CountPublicRepositories() int64 {
|
||||
return countRepositories(false)
|
||||
// CountUserRepositories returns number of repositories user owns.
|
||||
// Argument private only takes effect when it is false,
|
||||
// set it true to count all repositories.
|
||||
func CountUserRepositories(userID int64, private bool) int64 {
|
||||
return countRepositories(userID, private)
|
||||
}
|
||||
|
||||
func Repositories(page, pageSize int) (_ []*Repository, err error) {
|
||||
@@ -1113,7 +1100,7 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
|
||||
|
||||
// Note: we have to set value here to make sure recalculate accesses is based on
|
||||
// new owner.
|
||||
repo.OwnerID = newOwner.Id
|
||||
repo.OwnerID = newOwner.ID
|
||||
repo.Owner = newOwner
|
||||
|
||||
// Update repository.
|
||||
@@ -1130,10 +1117,10 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
|
||||
// Dummy object.
|
||||
collaboration := &Collaboration{RepoID: repo.ID}
|
||||
for _, c := range collaborators {
|
||||
collaboration.UserID = c.Id
|
||||
if c.Id == newOwner.Id || newOwner.IsOrgMember(c.Id) {
|
||||
collaboration.UserID = c.ID
|
||||
if c.ID == newOwner.ID || newOwner.IsOrgMember(c.ID) {
|
||||
if _, err = sess.Delete(collaboration); err != nil {
|
||||
return fmt.Errorf("remove collaborator '%d': %v", c.Id, err)
|
||||
return fmt.Errorf("remove collaborator '%d': %v", c.ID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1174,19 +1161,20 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
|
||||
}
|
||||
|
||||
// Update repository count.
|
||||
if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", newOwner.Id); err != nil {
|
||||
if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos+1 WHERE id=?", newOwner.ID); err != nil {
|
||||
return fmt.Errorf("increase new owner repository count: %v", err)
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", owner.Id); err != nil {
|
||||
} else if _, err = sess.Exec("UPDATE `user` SET num_repos=num_repos-1 WHERE id=?", owner.ID); err != nil {
|
||||
return fmt.Errorf("decrease old owner repository count: %v", err)
|
||||
}
|
||||
|
||||
if err = watchRepo(sess, newOwner.Id, repo.ID, true); err != nil {
|
||||
if err = watchRepo(sess, newOwner.ID, repo.ID, true); err != nil {
|
||||
return fmt.Errorf("watchRepo: %v", err)
|
||||
} else if err = transferRepoAction(sess, u, owner, newOwner, repo); err != nil {
|
||||
return fmt.Errorf("transferRepoAction: %v", err)
|
||||
}
|
||||
|
||||
// Rename remote repository to new path and delete local copy.
|
||||
os.MkdirAll(UserPath(newOwner.Name), os.ModePerm)
|
||||
if err = os.Rename(RepoPath(owner.Name, repo.Name), RepoPath(newOwner.Name, repo.Name)); err != nil {
|
||||
return fmt.Errorf("rename repository directory: %v", err)
|
||||
}
|
||||
@@ -1208,7 +1196,7 @@ func TransferOwnership(u *User, newOwnerName string, repo *Repository) error {
|
||||
func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error) {
|
||||
oldRepoName = strings.ToLower(oldRepoName)
|
||||
newRepoName = strings.ToLower(newRepoName)
|
||||
if err = IsUsableName(newRepoName); err != nil {
|
||||
if err = IsUsableRepoName(newRepoName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1219,7 +1207,7 @@ func ChangeRepositoryName(u *User, oldRepoName, newRepoName string) (err error)
|
||||
return ErrRepoAlreadyExist{u.Name, newRepoName}
|
||||
}
|
||||
|
||||
repo, err := GetRepositoryByName(u.Id, oldRepoName)
|
||||
repo, err := GetRepositoryByName(u.ID, oldRepoName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetRepositoryByName: %v", err)
|
||||
}
|
||||
@@ -1433,7 +1421,7 @@ func GetRepositoryByRef(ref string) (*Repository, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return GetRepositoryByName(user.Id, repoName)
|
||||
return GetRepositoryByName(user.ID, repoName)
|
||||
}
|
||||
|
||||
// GetRepositoryByName returns the repository by given name under user if exists.
|
||||
@@ -1467,16 +1455,26 @@ func GetRepositoryByID(id int64) (*Repository, error) {
|
||||
return getRepositoryByID(x, id)
|
||||
}
|
||||
|
||||
// GetRepositories returns a list of repositories of given user.
|
||||
func GetRepositories(uid int64, private bool) ([]*Repository, error) {
|
||||
repos := make([]*Repository, 0, 10)
|
||||
sess := x.Desc("updated_unix")
|
||||
|
||||
// GetUserRepositories returns a list of repositories of given user.
|
||||
func GetUserRepositories(userID int64, private bool, page, pageSize int) ([]*Repository, error) {
|
||||
sess := x.Where("owner_id = ?", userID).Desc("updated_unix")
|
||||
if !private {
|
||||
sess.Where("is_private=?", false)
|
||||
sess.And("is_private=?", false)
|
||||
}
|
||||
|
||||
return repos, sess.Find(&repos, &Repository{OwnerID: uid})
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
sess.Limit(pageSize, (page-1)*pageSize)
|
||||
|
||||
repos := make([]*Repository, 0, pageSize)
|
||||
return repos, sess.Find(&repos)
|
||||
}
|
||||
|
||||
// GetUserRepositories returns a list of mirror repositories of given user.
|
||||
func GetUserMirrorRepositories(userID int64) ([]*Repository, error) {
|
||||
repos := make([]*Repository, 0, 10)
|
||||
return repos, x.Where("owner_id = ?", userID).And("is_mirror = ?", true).Find(&repos)
|
||||
}
|
||||
|
||||
// GetRecentUpdatedRepositories returns the list of repositories that are recently updated.
|
||||
@@ -1486,7 +1484,7 @@ func GetRecentUpdatedRepositories(page, pageSize int) (repos []*Repository, err
|
||||
}
|
||||
|
||||
func getRepositoryCount(e Engine, u *User) (int64, error) {
|
||||
return x.Count(&Repository{OwnerID: u.Id})
|
||||
return x.Count(&Repository{OwnerID: u.ID})
|
||||
}
|
||||
|
||||
// GetRepositoryCount returns the total number of repositories of user.
|
||||
@@ -1670,12 +1668,8 @@ func MirrorUpdate() {
|
||||
log.Trace("Doing: MirrorUpdate")
|
||||
|
||||
mirrors := make([]*Mirror, 0, 10)
|
||||
if err := x.Iterate(new(Mirror), func(idx int, bean interface{}) error {
|
||||
if err := x.Where("next_update_unix<=?", time.Now().Unix()).Iterate(new(Mirror), func(idx int, bean interface{}) error {
|
||||
m := bean.(*Mirror)
|
||||
if m.NextUpdate.After(time.Now()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if m.Repo == nil {
|
||||
log.Error(4, "Disconnected mirror repository found: %d", m.ID)
|
||||
return nil
|
||||
@@ -1872,6 +1866,74 @@ func CheckRepoStats() {
|
||||
// ***** END: Repository.NumForks *****
|
||||
}
|
||||
|
||||
type RepositoryList []*Repository
|
||||
|
||||
func (repos RepositoryList) loadAttributes(e Engine) error {
|
||||
if len(repos) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load owners.
|
||||
set := make(map[int64]*User)
|
||||
for i := range repos {
|
||||
set[repos[i].OwnerID] = nil
|
||||
}
|
||||
userIDs := make([]int64, 0, len(set))
|
||||
for userID := range set {
|
||||
userIDs = append(userIDs, userID)
|
||||
}
|
||||
users := make([]*User, 0, len(userIDs))
|
||||
if err := e.Where("id > 0").In("id", userIDs).Find(&users); err != nil {
|
||||
return fmt.Errorf("find users: %v", err)
|
||||
}
|
||||
for i := range users {
|
||||
set[users[i].ID] = users[i]
|
||||
}
|
||||
for i := range repos {
|
||||
repos[i].Owner = set[repos[i].OwnerID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repos RepositoryList) LoadAttributes() error {
|
||||
return repos.loadAttributes(x)
|
||||
}
|
||||
|
||||
type MirrorRepositoryList []*Repository
|
||||
|
||||
func (repos MirrorRepositoryList) loadAttributes(e Engine) error {
|
||||
if len(repos) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Load mirrors.
|
||||
repoIDs := make([]int64, 0, len(repos))
|
||||
for i := range repos {
|
||||
if !repos[i].IsMirror {
|
||||
continue
|
||||
}
|
||||
|
||||
repoIDs = append(repoIDs, repos[i].ID)
|
||||
}
|
||||
mirrors := make([]*Mirror, 0, len(repoIDs))
|
||||
if err := e.Where("id > 0").In("repo_id", repoIDs).Find(&mirrors); err != nil {
|
||||
return fmt.Errorf("find mirrors: %v", err)
|
||||
}
|
||||
|
||||
set := make(map[int64]*Mirror)
|
||||
for i := range mirrors {
|
||||
set[mirrors[i].RepoID] = mirrors[i]
|
||||
}
|
||||
for i := range repos {
|
||||
repos[i].Mirror = set[repos[i].ID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (repos MirrorRepositoryList) LoadAttributes() error {
|
||||
return repos.loadAttributes(x)
|
||||
}
|
||||
|
||||
// __ __ __ .__
|
||||
// / \ / \_____ _/ |_ ____ | |__
|
||||
// \ \/\/ /\__ \\ __\/ ___\| | \
|
||||
@@ -1886,40 +1948,40 @@ type Watch struct {
|
||||
RepoID int64 `xorm:"UNIQUE(watch)"`
|
||||
}
|
||||
|
||||
func isWatching(e Engine, uid, repoId int64) bool {
|
||||
has, _ := e.Get(&Watch{0, uid, repoId})
|
||||
func isWatching(e Engine, userID, repoID int64) bool {
|
||||
has, _ := e.Get(&Watch{0, userID, repoID})
|
||||
return has
|
||||
}
|
||||
|
||||
// IsWatching checks if user has watched given repository.
|
||||
func IsWatching(uid, repoId int64) bool {
|
||||
return isWatching(x, uid, repoId)
|
||||
func IsWatching(userID, repoID int64) bool {
|
||||
return isWatching(x, userID, repoID)
|
||||
}
|
||||
|
||||
func watchRepo(e Engine, uid, repoId int64, watch bool) (err error) {
|
||||
func watchRepo(e Engine, userID, repoID int64, watch bool) (err error) {
|
||||
if watch {
|
||||
if isWatching(e, uid, repoId) {
|
||||
if isWatching(e, userID, repoID) {
|
||||
return nil
|
||||
}
|
||||
if _, err = e.Insert(&Watch{RepoID: repoId, UserID: uid}); err != nil {
|
||||
if _, err = e.Insert(&Watch{RepoID: repoID, UserID: userID}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoId)
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches + 1 WHERE id = ?", repoID)
|
||||
} else {
|
||||
if !isWatching(e, uid, repoId) {
|
||||
if !isWatching(e, userID, repoID) {
|
||||
return nil
|
||||
}
|
||||
if _, err = e.Delete(&Watch{0, uid, repoId}); err != nil {
|
||||
if _, err = e.Delete(&Watch{0, userID, repoID}); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches=num_watches-1 WHERE id=?", repoId)
|
||||
_, err = e.Exec("UPDATE `repository` SET num_watches = num_watches - 1 WHERE id = ?", repoID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Watch or unwatch repository.
|
||||
func WatchRepo(uid, repoId int64, watch bool) (err error) {
|
||||
return watchRepo(x, uid, repoId, watch)
|
||||
func WatchRepo(userID, repoID int64, watch bool) (err error) {
|
||||
return watchRepo(x, userID, repoID, watch)
|
||||
}
|
||||
|
||||
func getWatchers(e Engine, repoID int64) ([]*Watch, error) {
|
||||
@@ -1990,34 +2052,34 @@ type Star struct {
|
||||
}
|
||||
|
||||
// Star or unstar repository.
|
||||
func StarRepo(uid, repoId int64, star bool) (err error) {
|
||||
func StarRepo(userID, repoID int64, star bool) (err error) {
|
||||
if star {
|
||||
if IsStaring(uid, repoId) {
|
||||
if IsStaring(userID, repoID) {
|
||||
return nil
|
||||
}
|
||||
if _, err = x.Insert(&Star{UID: uid, RepoID: repoId}); err != nil {
|
||||
if _, err = x.Insert(&Star{UID: userID, RepoID: repoID}); err != nil {
|
||||
return err
|
||||
} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoId); err != nil {
|
||||
} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = x.Exec("UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", uid)
|
||||
_, err = x.Exec("UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", userID)
|
||||
} else {
|
||||
if !IsStaring(uid, repoId) {
|
||||
if !IsStaring(userID, repoID) {
|
||||
return nil
|
||||
}
|
||||
if _, err = x.Delete(&Star{0, uid, repoId}); err != nil {
|
||||
if _, err = x.Delete(&Star{0, userID, repoID}); err != nil {
|
||||
return err
|
||||
} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoId); err != nil {
|
||||
} else if _, err = x.Exec("UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = x.Exec("UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", uid)
|
||||
_, err = x.Exec("UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", userID)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// IsStaring checks if user has starred given repository.
|
||||
func IsStaring(uid, repoId int64) bool {
|
||||
has, _ := x.Get(&Star{0, uid, repoId})
|
||||
func IsStaring(userID, repoID int64) bool {
|
||||
has, _ := x.Get(&Star{0, userID, repoID})
|
||||
return has
|
||||
}
|
||||
|
||||
@@ -2048,7 +2110,7 @@ func HasForkedRepo(ownerID, repoID int64) (*Repository, bool) {
|
||||
|
||||
func ForkRepository(u *User, oldRepo *Repository, name, desc string) (_ *Repository, err error) {
|
||||
repo := &Repository{
|
||||
OwnerID: u.Id,
|
||||
OwnerID: u.ID,
|
||||
Owner: u,
|
||||
Name: name,
|
||||
LowerName: strings.ToLower(name),
|
||||
|
||||
@@ -33,7 +33,7 @@ func (c *Collaboration) ModeI18nKey() string {
|
||||
func (repo *Repository) AddCollaborator(u *User) error {
|
||||
collaboration := &Collaboration{
|
||||
RepoID: repo.ID,
|
||||
UserID: u.Id,
|
||||
UserID: u.ID,
|
||||
}
|
||||
|
||||
has, err := x.Get(collaboration)
|
||||
|
||||
@@ -5,12 +5,10 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
@@ -24,17 +22,17 @@ import (
|
||||
"github.com/go-xorm/xorm"
|
||||
"golang.org/x/crypto/ssh"
|
||||
|
||||
"github.com/gogits/gogs/modules/base"
|
||||
"github.com/gogits/gogs/modules/log"
|
||||
"github.com/gogits/gogs/modules/process"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
// "### autogenerated by gitgos, DO NOT EDIT\n"
|
||||
_TPL_PUBLICK_KEY = `command="%s serv key-%d --config='%s'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
|
||||
)
|
||||
|
||||
var sshOpLocker = sync.Mutex{}
|
||||
var sshOpLocker sync.Mutex
|
||||
|
||||
type KeyType int
|
||||
|
||||
@@ -43,7 +41,7 @@ const (
|
||||
KEY_TYPE_DEPLOY
|
||||
)
|
||||
|
||||
// PublicKey represents a SSH or deploy key.
|
||||
// PublicKey represents a user or deploy SSH public key.
|
||||
type PublicKey struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
@@ -62,11 +60,11 @@ type PublicKey struct {
|
||||
}
|
||||
|
||||
func (k *PublicKey) BeforeInsert() {
|
||||
k.CreatedUnix = time.Now().UTC().Unix()
|
||||
k.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (k *PublicKey) BeforeUpdate() {
|
||||
k.UpdatedUnix = time.Now().UTC().Unix()
|
||||
k.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (k *PublicKey) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -80,45 +78,44 @@ func (k *PublicKey) AfterSet(colName string, _ xorm.Cell) {
|
||||
}
|
||||
}
|
||||
|
||||
// OmitEmail returns content of public key but without e-mail address.
|
||||
// OmitEmail returns content of public key without email address.
|
||||
func (k *PublicKey) OmitEmail() string {
|
||||
return strings.Join(strings.Split(k.Content, " ")[:2], " ")
|
||||
}
|
||||
|
||||
// GetAuthorizedString generates and returns formatted public key string for authorized_keys file.
|
||||
func (key *PublicKey) GetAuthorizedString() string {
|
||||
// AuthorizedString returns formatted public key string for authorized_keys file.
|
||||
func (key *PublicKey) AuthorizedString() string {
|
||||
return fmt.Sprintf(_TPL_PUBLICK_KEY, setting.AppPath, key.ID, setting.CustomConf, key.Content)
|
||||
}
|
||||
|
||||
func extractTypeFromBase64Key(key string) (string, error) {
|
||||
b, err := base64.StdEncoding.DecodeString(key)
|
||||
if err != nil || len(b) < 4 {
|
||||
return "", fmt.Errorf("Invalid key format: %v", err)
|
||||
return "", fmt.Errorf("invalid key format: %v", err)
|
||||
}
|
||||
|
||||
keyLength := int(binary.BigEndian.Uint32(b))
|
||||
if len(b) < 4+keyLength {
|
||||
return "", fmt.Errorf("Invalid key format: not enough length")
|
||||
return "", fmt.Errorf("invalid key format: not enough length %d", keyLength)
|
||||
}
|
||||
|
||||
return string(b[4 : 4+keyLength]), nil
|
||||
}
|
||||
|
||||
// parseKeyString parses any key string in OpenSSH or SSH2 format to clean OpenSSH string (RFC4253)
|
||||
// parseKeyString parses any key string in OpenSSH or SSH2 format to clean OpenSSH string (RFC4253).
|
||||
func parseKeyString(content string) (string, error) {
|
||||
// Transform all legal line endings to a single "\n"
|
||||
s := strings.Replace(strings.Replace(strings.TrimSpace(content), "\r\n", "\n", -1), "\r", "\n", -1)
|
||||
|
||||
lines := strings.Split(s, "\n")
|
||||
// Transform all legal line endings to a single "\n".
|
||||
content = strings.NewReplacer("\r\n", "\n", "\r", "\n").Replace(content)
|
||||
lines := strings.Split(content, "\n")
|
||||
|
||||
var keyType, keyContent, keyComment string
|
||||
|
||||
if len(lines) == 1 {
|
||||
// Parse openssh format
|
||||
// Parse OpenSSH format.
|
||||
parts := strings.SplitN(lines[0], " ", 3)
|
||||
switch len(parts) {
|
||||
case 0:
|
||||
return "", errors.New("Empty key")
|
||||
return "", errors.New("empty key")
|
||||
case 1:
|
||||
keyContent = parts[0]
|
||||
case 2:
|
||||
@@ -130,17 +127,15 @@ func parseKeyString(content string) (string, error) {
|
||||
keyComment = parts[2]
|
||||
}
|
||||
|
||||
// If keyType is not given, extract it from content. If given, validate it
|
||||
// If keyType is not given, extract it from content. If given, validate it.
|
||||
t, err := extractTypeFromBase64Key(keyContent)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
|
||||
}
|
||||
if len(keyType) == 0 {
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err == nil {
|
||||
keyType = t
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err != nil || keyType != t {
|
||||
return "", err
|
||||
}
|
||||
keyType = t
|
||||
} else if keyType != t {
|
||||
return "", fmt.Errorf("key type and content does not match: %s - %s", keyType, t)
|
||||
}
|
||||
} else {
|
||||
// Parse SSH2 file format.
|
||||
@@ -158,11 +153,11 @@ func parseKeyString(content string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if t, err := extractTypeFromBase64Key(keyContent); err == nil {
|
||||
keyType = t
|
||||
} else {
|
||||
return "", err
|
||||
t, err := extractTypeFromBase64Key(keyContent)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("extractTypeFromBase64Key: %v", err)
|
||||
}
|
||||
keyType = t
|
||||
}
|
||||
return keyType + " " + keyContent + " " + keyComment, nil
|
||||
}
|
||||
@@ -177,7 +172,7 @@ func writeTmpKeyFile(content string) (string, error) {
|
||||
defer tmpFile.Close()
|
||||
|
||||
if _, err = tmpFile.WriteString(content); err != nil {
|
||||
return "", fmt.Errorf("tmpFile.WriteString: %v", err)
|
||||
return "", fmt.Errorf("WriteString: %v", err)
|
||||
}
|
||||
return tmpFile.Name(), nil
|
||||
}
|
||||
@@ -197,7 +192,7 @@ func SSHKeyGenParsePublicKey(key string) (string, int, error) {
|
||||
|
||||
stdout, stderr, err := process.Exec("SSHKeyGenParsePublicKey", setting.SSH.KeygenPath, "-lf", tmpName)
|
||||
if err != nil {
|
||||
return "", 0, fmt.Errorf("Fail to parse public key: %s - %s", err, stderr)
|
||||
return "", 0, fmt.Errorf("fail to parse public key: %s - %s", err, stderr)
|
||||
}
|
||||
if strings.Contains(stdout, "is not a public key file") {
|
||||
return "", 0, ErrKeyUnableVerify{stdout}
|
||||
@@ -205,7 +200,7 @@ func SSHKeyGenParsePublicKey(key string) (string, int, error) {
|
||||
|
||||
fields := strings.Split(stdout, " ")
|
||||
if len(fields) < 4 {
|
||||
return "", 0, fmt.Errorf("Invalid public key line: %s", stdout)
|
||||
return "", 0, fmt.Errorf("invalid public key line: %s", stdout)
|
||||
}
|
||||
|
||||
keyType := strings.Trim(fields[len(fields)-1], "()\r\n")
|
||||
@@ -230,7 +225,7 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
|
||||
if strings.Contains(err.Error(), "ssh: unknown key algorithm") {
|
||||
return "", 0, ErrKeyUnableVerify{err.Error()}
|
||||
}
|
||||
return "", 0, fmt.Errorf("ssh.ParsePublicKey: %v", err)
|
||||
return "", 0, fmt.Errorf("ParsePublicKey: %v", err)
|
||||
}
|
||||
|
||||
// The ssh library can parse the key, so next we find out what key exactly we have.
|
||||
@@ -262,15 +257,14 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
|
||||
return "ecdsa", 384, nil
|
||||
case ssh.KeyAlgoECDSA521:
|
||||
return "ecdsa", 521, nil
|
||||
case "ssh-ed25519": // TODO replace with ssh constant when available
|
||||
case "ssh-ed25519": // TODO: replace with ssh constant when available
|
||||
return "ed25519", 256, nil
|
||||
}
|
||||
return "", 0, fmt.Errorf("Unsupported key length detection for type: %s", pkey.Type())
|
||||
return "", 0, fmt.Errorf("unsupported key length detection for type: %s", pkey.Type())
|
||||
}
|
||||
|
||||
// CheckPublicKeyString checks if the given public key string is recognized by SSH.
|
||||
//
|
||||
// The function returns the actual public key line on success.
|
||||
// It returns the actual public key line on success.
|
||||
func CheckPublicKeyString(content string) (_ string, err error) {
|
||||
if setting.SSH.Disabled {
|
||||
return "", errors.New("SSH is disabled")
|
||||
@@ -290,16 +284,19 @@ func CheckPublicKeyString(content string) (_ string, err error) {
|
||||
content = strings.TrimSpace(content)
|
||||
|
||||
var (
|
||||
fnName string
|
||||
keyType string
|
||||
length int
|
||||
)
|
||||
if setting.SSH.StartBuiltinServer {
|
||||
fnName = "SSHNativeParsePublicKey"
|
||||
keyType, length, err = SSHNativeParsePublicKey(content)
|
||||
} else {
|
||||
fnName = "SSHKeyGenParsePublicKey"
|
||||
keyType, length, err = SSHKeyGenParsePublicKey(content)
|
||||
}
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("ParsePublicKey: %v", err)
|
||||
return "", fmt.Errorf("%s: %v", fnName, err)
|
||||
}
|
||||
log.Trace("Key info [native: %v]: %s-%d", setting.SSH.StartBuiltinServer, keyType, length)
|
||||
|
||||
@@ -309,13 +306,13 @@ func CheckPublicKeyString(content string) (_ string, err error) {
|
||||
if minLen, found := setting.SSH.MinimumKeySizes[keyType]; found && length >= minLen {
|
||||
return content, nil
|
||||
} else if found && length < minLen {
|
||||
return "", fmt.Errorf("Key length is not enough: got %d, needs %d", length, minLen)
|
||||
return "", fmt.Errorf("key length is not enough: got %d, needs %d", length, minLen)
|
||||
}
|
||||
return "", fmt.Errorf("Key type is not allowed: %s", keyType)
|
||||
return "", fmt.Errorf("key type is not allowed: %s", keyType)
|
||||
}
|
||||
|
||||
// saveAuthorizedKeyFile writes SSH key content to authorized_keys file.
|
||||
func saveAuthorizedKeyFile(keys ...*PublicKey) error {
|
||||
// appendAuthorizedKeysToFile appends new SSH keys' content to authorized_keys file.
|
||||
func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
@@ -326,13 +323,13 @@ func saveAuthorizedKeyFile(keys ...*PublicKey) error {
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME: following command does not support in Windows.
|
||||
// Note: chmod command does not support in Windows.
|
||||
if !setting.IsWindows {
|
||||
fi, err := f.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// .ssh directory should have mode 700, and authorized_keys file should have mode 600.
|
||||
if fi.Mode().Perm() > 0600 {
|
||||
log.Error(4, "authorized_keys file has unusual permission flags: %s - setting to -rw-------", fi.Mode().Perm().String())
|
||||
@@ -343,7 +340,7 @@ func saveAuthorizedKeyFile(keys ...*PublicKey) error {
|
||||
}
|
||||
|
||||
for _, key := range keys {
|
||||
if _, err = f.WriteString(key.GetAuthorizedString()); err != nil {
|
||||
if _, err = f.WriteString(key.AuthorizedString()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -390,7 +387,7 @@ func addKey(e Engine, key *PublicKey) (err error) {
|
||||
if setting.SSH.StartBuiltinServer {
|
||||
return nil
|
||||
}
|
||||
return saveAuthorizedKeyFile(key)
|
||||
return appendAuthorizedKeysToFile(key)
|
||||
}
|
||||
|
||||
// AddPublicKey adds new public key to database and authorized_keys file.
|
||||
@@ -401,7 +398,7 @@ func AddPublicKey(ownerID int64, name, content string) (*PublicKey, error) {
|
||||
}
|
||||
|
||||
// Key name of same user cannot be duplicated.
|
||||
has, err := x.Where("owner_id=? AND name=?", ownerID, name).Get(new(PublicKey))
|
||||
has, err := x.Where("owner_id = ? AND name = ?", ownerID, name).Get(new(PublicKey))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if has {
|
||||
@@ -456,62 +453,7 @@ func SearchPublicKeyByContent(content string) (*PublicKey, error) {
|
||||
// ListPublicKeys returns a list of public keys belongs to given user.
|
||||
func ListPublicKeys(uid int64) ([]*PublicKey, error) {
|
||||
keys := make([]*PublicKey, 0, 5)
|
||||
return keys, x.Where("owner_id=?", uid).Find(&keys)
|
||||
}
|
||||
|
||||
// rewriteAuthorizedKeys finds and deletes corresponding line in authorized_keys file.
|
||||
func rewriteAuthorizedKeys(key *PublicKey, p, tmpP string) error {
|
||||
fr, err := os.Open(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fr.Close()
|
||||
|
||||
fw, err := os.OpenFile(tmpP, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fw.Close()
|
||||
|
||||
isFound := false
|
||||
keyword := fmt.Sprintf("key-%d", key.ID)
|
||||
buf := bufio.NewReader(fr)
|
||||
for {
|
||||
line, errRead := buf.ReadString('\n')
|
||||
line = strings.TrimSpace(line)
|
||||
|
||||
if errRead != nil {
|
||||
if errRead != io.EOF {
|
||||
return errRead
|
||||
}
|
||||
|
||||
// Reached end of file, if nothing to read then break,
|
||||
// otherwise handle the last line.
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Found the line and copy rest of file.
|
||||
if !isFound && strings.Contains(line, keyword) && strings.Contains(line, key.Content) {
|
||||
isFound = true
|
||||
continue
|
||||
}
|
||||
// Still finding the line, copy the line that currently read.
|
||||
if _, err = fw.WriteString(line + "\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if errRead == io.EOF {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isFound {
|
||||
log.Warn("SSH key %d not found in authorized_keys file for deletion", key.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
return keys, x.Where("owner_id = ?", uid).Find(&keys)
|
||||
}
|
||||
|
||||
// UpdatePublicKey updates given public key.
|
||||
@@ -520,35 +462,14 @@ func UpdatePublicKey(key *PublicKey) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func deletePublicKey(e *xorm.Session, keyID int64) error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
|
||||
key := &PublicKey{ID: keyID}
|
||||
has, err := e.Get(key)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
// deletePublicKeys does the actual key deletion but does not update authorized_keys file.
|
||||
func deletePublicKeys(e *xorm.Session, keyIDs ...int64) error {
|
||||
if len(keyIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if _, err = e.Id(key.ID).Delete(new(PublicKey)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Don't need to rewrite this file if builtin SSH server is enabled.
|
||||
if setting.SSH.StartBuiltinServer {
|
||||
return nil
|
||||
}
|
||||
|
||||
fpath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
|
||||
tmpPath := fpath + ".tmp"
|
||||
if err = rewriteAuthorizedKeys(key, fpath, tmpPath); err != nil {
|
||||
return err
|
||||
} else if err = os.Remove(fpath); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpPath, fpath)
|
||||
_, err := e.In("id", strings.Join(base.Int64sToStrings(keyIDs), ",")).Delete(new(PublicKey))
|
||||
return err
|
||||
}
|
||||
|
||||
// DeletePublicKey deletes SSH key information both in database and authorized_keys file.
|
||||
@@ -562,8 +483,8 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
}
|
||||
|
||||
// Check if user has access to delete this key.
|
||||
if !doer.IsAdmin && doer.Id != key.OwnerID {
|
||||
return ErrKeyAccessDenied{doer.Id, key.ID, "public"}
|
||||
if !doer.IsAdmin && doer.ID != key.OwnerID {
|
||||
return ErrKeyAccessDenied{doer.ID, key.ID, "public"}
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
@@ -572,14 +493,20 @@ func DeletePublicKey(doer *User, id int64) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = deletePublicKey(sess, id); err != nil {
|
||||
if err = deletePublicKeys(sess, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
// RewriteAllPublicKeys removes any authorized key and rewrite all keys from database again.
|
||||
// Note: x.Iterate does not get latest data after insert/delete, so we have to call this function
|
||||
// outsite any session scope independently.
|
||||
func RewriteAllPublicKeys() error {
|
||||
sshOpLocker.Lock()
|
||||
defer sshOpLocker.Unlock()
|
||||
@@ -593,7 +520,7 @@ func RewriteAllPublicKeys() error {
|
||||
defer os.Remove(tmpPath)
|
||||
|
||||
err = x.Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
_, err = f.WriteString((bean.(*PublicKey)).GetAuthorizedString())
|
||||
_, err = f.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||
return err
|
||||
})
|
||||
f.Close()
|
||||
@@ -638,11 +565,11 @@ type DeployKey struct {
|
||||
}
|
||||
|
||||
func (k *DeployKey) BeforeInsert() {
|
||||
k.CreatedUnix = time.Now().UTC().Unix()
|
||||
k.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (k *DeployKey) BeforeUpdate() {
|
||||
k.UpdatedUnix = time.Now().UTC().Unix()
|
||||
k.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (k *DeployKey) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -668,14 +595,14 @@ func (k *DeployKey) GetContent() error {
|
||||
|
||||
func checkDeployKey(e Engine, keyID, repoID int64, name string) error {
|
||||
// Note: We want error detail, not just true or false here.
|
||||
has, err := e.Where("key_id=? AND repo_id=?", keyID, repoID).Get(new(DeployKey))
|
||||
has, err := e.Where("key_id = ? AND repo_id = ?", keyID, repoID).Get(new(DeployKey))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
return ErrDeployKeyAlreadyExist{keyID, repoID}
|
||||
}
|
||||
|
||||
has, err = e.Where("repo_id=? AND name=?", repoID, name).Get(new(DeployKey))
|
||||
has, err = e.Where("repo_id = ? AND name = ?", repoID, name).Get(new(DeployKey))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
@@ -703,7 +630,7 @@ func addDeployKey(e *xorm.Session, keyID, repoID int64, name, fingerprint string
|
||||
|
||||
// HasDeployKey returns true if public key is a deploy key of given repository.
|
||||
func HasDeployKey(keyID, repoID int64) bool {
|
||||
has, _ := x.Where("key_id=? AND repo_id=?", keyID, repoID).Get(new(DeployKey))
|
||||
has, _ := x.Where("key_id = ? AND repo_id = ?", keyID, repoID).Get(new(DeployKey))
|
||||
return has
|
||||
}
|
||||
|
||||
@@ -797,7 +724,7 @@ func DeleteDeployKey(doer *User, id int64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("HasAccess: %v", err)
|
||||
} else if !yes {
|
||||
return ErrKeyAccessDenied{doer.Id, key.ID, "deploy"}
|
||||
return ErrKeyAccessDenied{doer.ID, key.ID, "deploy"}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -808,15 +735,15 @@ func DeleteDeployKey(doer *User, id int64) error {
|
||||
}
|
||||
|
||||
if _, err = sess.Id(key.ID).Delete(new(DeployKey)); err != nil {
|
||||
return fmt.Errorf("delete deploy key[%d]: %v", key.ID, err)
|
||||
return fmt.Errorf("delete deploy key [%d]: %v", key.ID, err)
|
||||
}
|
||||
|
||||
// Check if this is the last reference to same key content.
|
||||
has, err := sess.Where("key_id=?", key.KeyID).Get(new(DeployKey))
|
||||
has, err := sess.Where("key_id = ?", key.KeyID).Get(new(DeployKey))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
if err = deletePublicKey(sess, key.KeyID); err != nil {
|
||||
if err = deletePublicKeys(sess, key.KeyID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -827,5 +754,5 @@ func DeleteDeployKey(doer *User, id int64) error {
|
||||
// ListDeployKeys returns all deploy keys by given repository ID.
|
||||
func ListDeployKeys(repoID int64) ([]*DeployKey, error) {
|
||||
keys := make([]*DeployKey, 0, 5)
|
||||
return keys, x.Where("repo_id=?", repoID).Find(&keys)
|
||||
return keys, x.Where("repo_id = ?", repoID).Find(&keys)
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ type AccessToken struct {
|
||||
}
|
||||
|
||||
func (t *AccessToken) BeforeInsert() {
|
||||
t.CreatedUnix = time.Now().UTC().Unix()
|
||||
t.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (t *AccessToken) BeforeUpdate() {
|
||||
t.UpdatedUnix = time.Now().UTC().Unix()
|
||||
t.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (t *AccessToken) AfterSet(colName string, _ xorm.Cell) {
|
||||
|
||||
@@ -108,7 +108,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
return fmt.Errorf("GetUserByName: %v", err)
|
||||
}
|
||||
|
||||
repo, err := GetRepositoryByName(repoUser.Id, opts.RepoName)
|
||||
repo, err := GetRepositoryByName(repoUser.ID, opts.RepoName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetRepositoryByName: %v", err)
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
}
|
||||
|
||||
commit := &PushCommits{}
|
||||
if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, actEmail,
|
||||
if err = CommitRepoAction(opts.PusherID, repoUser.ID, opts.PusherName, actEmail,
|
||||
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, commit, opts.OldCommitID, opts.NewCommitID); err != nil {
|
||||
return fmt.Errorf("CommitRepoAction (tag): %v", err)
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func PushUpdate(opts PushUpdateOptions) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
if err = CommitRepoAction(opts.PusherID, repoUser.Id, opts.PusherName, repoUser.Email,
|
||||
if err = CommitRepoAction(opts.PusherID, repoUser.ID, opts.PusherName, repoUser.Email,
|
||||
repo.ID, opts.RepoUserName, opts.RepoName, opts.RefName, ListToPushCommits(l),
|
||||
opts.OldCommitID, opts.NewCommitID); err != nil {
|
||||
return fmt.Errorf("CommitRepoAction (branch): %v", err)
|
||||
|
||||
167
models/user.go
167
models/user.go
@@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/xorm"
|
||||
@@ -51,7 +52,7 @@ var (
|
||||
|
||||
// User represents the object of individual and member of organization.
|
||||
type User struct {
|
||||
Id int64
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
LowerName string `xorm:"UNIQUE NOT NULL"`
|
||||
Name string `xorm:"UNIQUE NOT NULL"`
|
||||
FullName string
|
||||
@@ -107,7 +108,7 @@ type User struct {
|
||||
}
|
||||
|
||||
func (u *User) BeforeInsert() {
|
||||
u.CreatedUnix = time.Now().UTC().Unix()
|
||||
u.CreatedUnix = time.Now().Unix()
|
||||
u.UpdatedUnix = u.CreatedUnix
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ func (u *User) BeforeUpdate() {
|
||||
if u.MaxRepoCreation < -1 {
|
||||
u.MaxRepoCreation = -1
|
||||
}
|
||||
u.UpdatedUnix = time.Now().UTC().Unix()
|
||||
u.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (u *User) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -136,7 +137,7 @@ func (u *User) IsLocal() bool {
|
||||
|
||||
// HasForkedRepo checks if user has already forked a repository with given ID.
|
||||
func (u *User) HasForkedRepo(repoID int64) bool {
|
||||
_, has := HasForkedRepo(u.Id, repoID)
|
||||
_, has := HasForkedRepo(u.ID, repoID)
|
||||
return has
|
||||
}
|
||||
|
||||
@@ -183,7 +184,7 @@ func (u *User) HomeLink() string {
|
||||
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
|
||||
func (u *User) GenerateEmailActivateCode(email string) string {
|
||||
code := base.CreateTimeLimitCode(
|
||||
com.ToStr(u.Id)+email+u.LowerName+u.Passwd+u.Rands,
|
||||
com.ToStr(u.ID)+email+u.LowerName+u.Passwd+u.Rands,
|
||||
setting.Service.ActiveCodeLives, nil)
|
||||
|
||||
// Add tail hex username
|
||||
@@ -198,7 +199,7 @@ func (u *User) GenerateActivateCode() string {
|
||||
|
||||
// CustomAvatarPath returns user custom avatar file path.
|
||||
func (u *User) CustomAvatarPath() string {
|
||||
return filepath.Join(setting.AvatarUploadPath, com.ToStr(u.Id))
|
||||
return filepath.Join(setting.AvatarUploadPath, com.ToStr(u.ID))
|
||||
}
|
||||
|
||||
// GenerateRandomAvatar generates a random avatar for user.
|
||||
@@ -225,13 +226,13 @@ func (u *User) GenerateRandomAvatar() error {
|
||||
return fmt.Errorf("Encode: %v", err)
|
||||
}
|
||||
|
||||
log.Info("New random avatar created: %d", u.Id)
|
||||
log.Info("New random avatar created: %d", u.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *User) RelAvatarLink() string {
|
||||
defaultImgUrl := "/img/avatar_default.png"
|
||||
if u.Id == -1 {
|
||||
if u.ID == -1 {
|
||||
return defaultImgUrl
|
||||
}
|
||||
|
||||
@@ -240,7 +241,7 @@ func (u *User) RelAvatarLink() string {
|
||||
if !com.IsExist(u.CustomAvatarPath()) {
|
||||
return defaultImgUrl
|
||||
}
|
||||
return "/avatars/" + com.ToStr(u.Id)
|
||||
return "/avatars/" + com.ToStr(u.ID)
|
||||
case setting.DisableGravatar, setting.OfflineMode:
|
||||
if !com.IsExist(u.CustomAvatarPath()) {
|
||||
if err := u.GenerateRandomAvatar(); err != nil {
|
||||
@@ -248,7 +249,7 @@ func (u *User) RelAvatarLink() string {
|
||||
}
|
||||
}
|
||||
|
||||
return "/avatars/" + com.ToStr(u.Id)
|
||||
return "/avatars/" + com.ToStr(u.ID)
|
||||
}
|
||||
return setting.GravatarSource + u.Avatar
|
||||
}
|
||||
@@ -265,7 +266,7 @@ func (u *User) AvatarLink() string {
|
||||
// User.GetFollwoers returns range of user's followers.
|
||||
func (u *User) GetFollowers(page int) ([]*User, error) {
|
||||
users := make([]*User, 0, ItemsPerPage)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.follow_id=?", u.Id)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.follow_id=?", u.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "follow", `"user".id=follow.user_id`)
|
||||
} else {
|
||||
@@ -275,13 +276,13 @@ func (u *User) GetFollowers(page int) ([]*User, error) {
|
||||
}
|
||||
|
||||
func (u *User) IsFollowing(followID int64) bool {
|
||||
return IsFollowing(u.Id, followID)
|
||||
return IsFollowing(u.ID, followID)
|
||||
}
|
||||
|
||||
// GetFollowing returns range of user's following.
|
||||
func (u *User) GetFollowing(page int) ([]*User, error) {
|
||||
users := make([]*User, 0, ItemsPerPage)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.user_id=?", u.Id)
|
||||
sess := x.Limit(ItemsPerPage, (page-1)*ItemsPerPage).Where("follow.user_id=?", u.ID)
|
||||
if setting.UsePostgreSQL {
|
||||
sess = sess.Join("LEFT", "follow", `"user".id=follow.follow_id`)
|
||||
} else {
|
||||
@@ -349,7 +350,7 @@ func (u *User) UploadAvatar(data []byte) error {
|
||||
|
||||
// DeleteAvatar deletes the user's custom avatar.
|
||||
func (u *User) DeleteAvatar() error {
|
||||
log.Trace("DeleteAvatar[%d]: %s", u.Id, u.CustomAvatarPath())
|
||||
log.Trace("DeleteAvatar[%d]: %s", u.ID, u.CustomAvatarPath())
|
||||
os.Remove(u.CustomAvatarPath())
|
||||
|
||||
u.UseCustomAvatar = false
|
||||
@@ -384,16 +385,16 @@ func (u *User) IsOrganization() bool {
|
||||
|
||||
// IsUserOrgOwner returns true if user is in the owner team of given organization.
|
||||
func (u *User) IsUserOrgOwner(orgId int64) bool {
|
||||
return IsOrganizationOwner(orgId, u.Id)
|
||||
return IsOrganizationOwner(orgId, u.ID)
|
||||
}
|
||||
|
||||
// IsPublicMember returns true if user public his/her membership in give organization.
|
||||
func (u *User) IsPublicMember(orgId int64) bool {
|
||||
return IsPublicMembership(orgId, u.Id)
|
||||
return IsPublicMembership(orgId, u.ID)
|
||||
}
|
||||
|
||||
func (u *User) getOrganizationCount(e Engine) (int64, error) {
|
||||
return e.Where("uid=?", u.Id).Count(new(OrgUser))
|
||||
return e.Where("uid=?", u.ID).Count(new(OrgUser))
|
||||
}
|
||||
|
||||
// GetOrganizationCount returns count of membership of organization of user.
|
||||
@@ -401,21 +402,26 @@ func (u *User) GetOrganizationCount() (int64, error) {
|
||||
return u.getOrganizationCount(x)
|
||||
}
|
||||
|
||||
// GetRepositories returns all repositories that user owns, including private repositories.
|
||||
func (u *User) GetRepositories() (err error) {
|
||||
u.Repos, err = GetRepositories(u.Id, true)
|
||||
// GetRepositories returns repositories that user owns, including private repositories.
|
||||
func (u *User) GetRepositories(page, pageSize int) (err error) {
|
||||
u.Repos, err = GetUserRepositories(u.ID, true, page, pageSize)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetRepositories returns mirror repositories that user owns, including private repositories.
|
||||
func (u *User) GetMirrorRepositories() ([]*Repository, error) {
|
||||
return GetUserMirrorRepositories(u.ID)
|
||||
}
|
||||
|
||||
// GetOwnedOrganizations returns all organizations that user owns.
|
||||
func (u *User) GetOwnedOrganizations() (err error) {
|
||||
u.OwnedOrgs, err = GetOwnedOrgsByUserID(u.Id)
|
||||
u.OwnedOrgs, err = GetOwnedOrgsByUserID(u.ID)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetOrganizations returns all organizations that user belongs to.
|
||||
func (u *User) GetOrganizations(all bool) error {
|
||||
ous, err := GetOrgUsersByUserID(u.Id, all)
|
||||
ous, err := GetOrgUsersByUserID(u.ID, all)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -462,15 +468,49 @@ func GetUserSalt() string {
|
||||
// NewFakeUser creates and returns a fake user for someone has deleted his/her account.
|
||||
func NewFakeUser() *User {
|
||||
return &User{
|
||||
Id: -1,
|
||||
ID: -1,
|
||||
Name: "Someone",
|
||||
LowerName: "someone",
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
reversedUsernames = []string{"debug", "raw", "install", "api", "avatar", "user", "org", "help", "stars", "issues", "pulls", "commits", "repo", "template", "admin", "new", ".", ".."}
|
||||
reversedUserPatterns = []string{"*.keys"}
|
||||
)
|
||||
|
||||
// isUsableName checks if name is reserved or pattern of name is not allowed
|
||||
// based on given reversed names and patterns.
|
||||
// Names are exact match, patterns can be prefix or suffix match with placeholder '*'.
|
||||
func isUsableName(names, patterns []string, name string) error {
|
||||
name = strings.TrimSpace(strings.ToLower(name))
|
||||
if utf8.RuneCountInString(name) == 0 {
|
||||
return ErrNameEmpty
|
||||
}
|
||||
|
||||
for i := range names {
|
||||
if name == names[i] {
|
||||
return ErrNameReserved{name}
|
||||
}
|
||||
}
|
||||
|
||||
for _, pat := range patterns {
|
||||
if pat[0] == '*' && strings.HasSuffix(name, pat[1:]) ||
|
||||
(pat[len(pat)-1] == '*' && strings.HasPrefix(name, pat[:len(pat)-1])) {
|
||||
return ErrNamePatternNotAllowed{pat}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsUsableUsername(name string) error {
|
||||
return isUsableName(reversedUsernames, reversedUserPatterns, name)
|
||||
}
|
||||
|
||||
// CreateUser creates record of a new user.
|
||||
func CreateUser(u *User) (err error) {
|
||||
if err = IsUsableName(u.Name); err != nil {
|
||||
if err = IsUsableUsername(u.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -553,7 +593,7 @@ func VerifyUserActiveCode(code string) (user *User) {
|
||||
if user = getVerifyUser(code); user != nil {
|
||||
// time limit code
|
||||
prefix := code[:base.TimeLimitCodeLength]
|
||||
data := com.ToStr(user.Id) + user.Email + user.LowerName + user.Passwd + user.Rands
|
||||
data := com.ToStr(user.ID) + user.Email + user.LowerName + user.Passwd + user.Rands
|
||||
|
||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||
return user
|
||||
@@ -569,7 +609,7 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress {
|
||||
if user := getVerifyUser(code); user != nil {
|
||||
// time limit code
|
||||
prefix := code[:base.TimeLimitCodeLength]
|
||||
data := com.ToStr(user.Id) + email + user.LowerName + user.Passwd + user.Rands
|
||||
data := com.ToStr(user.ID) + email + user.LowerName + user.Passwd + user.Rands
|
||||
|
||||
if base.VerifyTimeLimitCode(data, minutes, prefix) {
|
||||
emailAddress := &EmailAddress{Email: email}
|
||||
@@ -583,7 +623,7 @@ func VerifyActiveEmailCode(code, email string) *EmailAddress {
|
||||
|
||||
// ChangeUserName changes all corresponding setting from old user name to new one.
|
||||
func ChangeUserName(u *User, newUserName string) (err error) {
|
||||
if err = IsUsableName(newUserName); err != nil {
|
||||
if err = IsUsableUsername(newUserName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -599,7 +639,7 @@ func ChangeUserName(u *User, newUserName string) (err error) {
|
||||
}
|
||||
|
||||
// Delete all local copies of repository wiki that user owns.
|
||||
if err = x.Where("owner_id=?", u.Id).Iterate(new(Repository), func(idx int, bean interface{}) error {
|
||||
if err = x.Where("owner_id=?", u.ID).Iterate(new(Repository), func(idx int, bean interface{}) error {
|
||||
repo := bean.(*Repository)
|
||||
RemoveAllWithNotice("Delete repository wiki local copy", repo.LocalWikiPath())
|
||||
return nil
|
||||
@@ -614,7 +654,7 @@ func updateUser(e Engine, u *User) error {
|
||||
// Organization does not need email
|
||||
if !u.IsOrganization() {
|
||||
u.Email = strings.ToLower(u.Email)
|
||||
has, err := e.Where("id!=?", u.Id).And("type=?", u.Type).And("email=?", u.Email).Get(new(User))
|
||||
has, err := e.Where("id!=?", u.ID).And("type=?", u.Type).And("email=?", u.Email).Get(new(User))
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
@@ -633,7 +673,7 @@ func updateUser(e Engine, u *User) error {
|
||||
u.Description = base.TruncateString(u.Description, 255)
|
||||
|
||||
u.FullName = markdown.Sanitizer.Sanitize(u.FullName)
|
||||
_, err := e.Id(u.Id).AllCols().Update(u)
|
||||
_, err := e.Id(u.ID).AllCols().Update(u)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -662,7 +702,7 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetRepositoryCount: %v", err)
|
||||
} else if count > 0 {
|
||||
return ErrUserOwnRepos{UID: u.Id}
|
||||
return ErrUserOwnRepos{UID: u.ID}
|
||||
}
|
||||
|
||||
// Check membership of organization.
|
||||
@@ -670,12 +710,12 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("GetOrganizationCount: %v", err)
|
||||
} else if count > 0 {
|
||||
return ErrUserHasOrgs{UID: u.Id}
|
||||
return ErrUserHasOrgs{UID: u.ID}
|
||||
}
|
||||
|
||||
// ***** START: Watch *****
|
||||
watches := make([]*Watch, 0, 10)
|
||||
if err = e.Find(&watches, &Watch{UserID: u.Id}); err != nil {
|
||||
if err = e.Find(&watches, &Watch{UserID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all watches: %v", err)
|
||||
}
|
||||
for i := range watches {
|
||||
@@ -687,7 +727,7 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
|
||||
// ***** START: Star *****
|
||||
stars := make([]*Star, 0, 10)
|
||||
if err = e.Find(&stars, &Star{UID: u.Id}); err != nil {
|
||||
if err = e.Find(&stars, &Star{UID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all stars: %v", err)
|
||||
}
|
||||
for i := range stars {
|
||||
@@ -699,7 +739,7 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
|
||||
// ***** START: Follow *****
|
||||
followers := make([]*Follow, 0, 10)
|
||||
if err = e.Find(&followers, &Follow{UserID: u.Id}); err != nil {
|
||||
if err = e.Find(&followers, &Follow{UserID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all followers: %v", err)
|
||||
}
|
||||
for i := range followers {
|
||||
@@ -710,37 +750,40 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
// ***** END: Follow *****
|
||||
|
||||
if err = deleteBeans(e,
|
||||
&AccessToken{UID: u.Id},
|
||||
&Collaboration{UserID: u.Id},
|
||||
&Access{UserID: u.Id},
|
||||
&Watch{UserID: u.Id},
|
||||
&Star{UID: u.Id},
|
||||
&Follow{FollowID: u.Id},
|
||||
&Action{UserID: u.Id},
|
||||
&IssueUser{UID: u.Id},
|
||||
&EmailAddress{UID: u.Id},
|
||||
&AccessToken{UID: u.ID},
|
||||
&Collaboration{UserID: u.ID},
|
||||
&Access{UserID: u.ID},
|
||||
&Watch{UserID: u.ID},
|
||||
&Star{UID: u.ID},
|
||||
&Follow{FollowID: u.ID},
|
||||
&Action{UserID: u.ID},
|
||||
&IssueUser{UID: u.ID},
|
||||
&EmailAddress{UID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %v", err)
|
||||
}
|
||||
|
||||
// ***** START: PublicKey *****
|
||||
keys := make([]*PublicKey, 0, 10)
|
||||
if err = e.Find(&keys, &PublicKey{OwnerID: u.Id}); err != nil {
|
||||
if err = e.Find(&keys, &PublicKey{OwnerID: u.ID}); err != nil {
|
||||
return fmt.Errorf("get all public keys: %v", err)
|
||||
}
|
||||
for _, key := range keys {
|
||||
if err = deletePublicKey(e, key.ID); err != nil {
|
||||
return fmt.Errorf("deletePublicKey: %v", err)
|
||||
}
|
||||
|
||||
keyIDs := make([]int64, len(keys))
|
||||
for i := range keys {
|
||||
keyIDs[i] = keys[i].ID
|
||||
}
|
||||
if err = deletePublicKeys(e, keyIDs...); err != nil {
|
||||
return fmt.Errorf("deletePublicKeys: %v", err)
|
||||
}
|
||||
// ***** END: PublicKey *****
|
||||
|
||||
// Clear assignee.
|
||||
if _, err = e.Exec("UPDATE `issue` SET assignee_id=0 WHERE assignee_id=?", u.Id); err != nil {
|
||||
if _, err = e.Exec("UPDATE `issue` SET assignee_id=0 WHERE assignee_id=?", u.ID); err != nil {
|
||||
return fmt.Errorf("clear assignee: %v", err)
|
||||
}
|
||||
|
||||
if _, err = e.Id(u.Id).Delete(new(User)); err != nil {
|
||||
if _, err = e.Id(u.ID).Delete(new(User)); err != nil {
|
||||
return fmt.Errorf("Delete: %v", err)
|
||||
}
|
||||
|
||||
@@ -748,7 +791,6 @@ func deleteUser(e *xorm.Session, u *User) error {
|
||||
// Note: There are something just cannot be roll back,
|
||||
// so just keep error logs of those operations.
|
||||
|
||||
RewriteAllPublicKeys()
|
||||
os.RemoveAll(UserPath(u.Name))
|
||||
os.Remove(u.CustomAvatarPath())
|
||||
|
||||
@@ -769,15 +811,20 @@ func DeleteUser(u *User) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
if err = sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return RewriteAllPublicKeys()
|
||||
}
|
||||
|
||||
// DeleteInactivateUsers deletes all inactivate users and email addresses.
|
||||
func DeleteInactivateUsers() (err error) {
|
||||
users := make([]*User, 0, 10)
|
||||
if err = x.Where("is_active=?", false).Find(&users); err != nil {
|
||||
if err = x.Where("is_active = ?", false).Find(&users); err != nil {
|
||||
return fmt.Errorf("get all inactive users: %v", err)
|
||||
}
|
||||
// FIXME: should only update authorized_keys file once after all deletions.
|
||||
for _, u := range users {
|
||||
if err = DeleteUser(u); err != nil {
|
||||
// Ignore users that were set inactive by admin.
|
||||
@@ -788,7 +835,7 @@ func DeleteInactivateUsers() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
_, err = x.Where("is_activated=?", false).Delete(new(EmailAddress))
|
||||
_, err = x.Where("is_activated = ?", false).Delete(new(EmailAddress))
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -826,7 +873,7 @@ func GetUserByID(id int64) (*User, error) {
|
||||
|
||||
// GetAssigneeByID returns the user with write access of repository by given ID.
|
||||
func GetAssigneeByID(repo *Repository, userID int64) (*User, error) {
|
||||
has, err := HasAccess(&User{Id: userID}, repo, ACCESS_MODE_WRITE)
|
||||
has, err := HasAccess(&User{ID: userID}, repo, ACCESS_MODE_WRITE)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@@ -871,7 +918,7 @@ func GetUserIDsByNames(names []string) []int64 {
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
ids = append(ids, u.Id)
|
||||
ids = append(ids, u.ID)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
@@ -953,7 +1000,7 @@ type SearchUserOptions struct {
|
||||
Type UserType
|
||||
OrderBy string
|
||||
Page int
|
||||
PageSize int // Can be smaller than or equal to setting.ExplorePagingNum
|
||||
PageSize int // Can be smaller than or equal to setting.UI.ExplorePagingNum
|
||||
}
|
||||
|
||||
// SearchUserByName takes keyword and part of user name to search,
|
||||
@@ -964,8 +1011,8 @@ func SearchUserByName(opts *SearchUserOptions) (users []*User, _ int64, _ error)
|
||||
}
|
||||
opts.Keyword = strings.ToLower(opts.Keyword)
|
||||
|
||||
if opts.PageSize <= 0 || opts.PageSize > setting.ExplorePagingNum {
|
||||
opts.PageSize = setting.ExplorePagingNum
|
||||
if opts.PageSize <= 0 || opts.PageSize > setting.UI.ExplorePagingNum {
|
||||
opts.PageSize = setting.UI.ExplorePagingNum
|
||||
}
|
||||
if opts.Page <= 0 {
|
||||
opts.Page = 1
|
||||
|
||||
@@ -160,7 +160,7 @@ func MakeEmailPrimary(email *EmailAddress) error {
|
||||
return ErrEmailNotActivated
|
||||
}
|
||||
|
||||
user := &User{Id: email.UID}
|
||||
user := &User{ID: email.UID}
|
||||
has, err = x.Get(user)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -182,7 +182,7 @@ func MakeEmailPrimary(email *EmailAddress) error {
|
||||
}
|
||||
|
||||
if !has {
|
||||
formerPrimaryEmail.UID = user.Id
|
||||
formerPrimaryEmail.UID = user.ID
|
||||
formerPrimaryEmail.IsActivated = user.IsActive
|
||||
if _, err = sess.Insert(formerPrimaryEmail); err != nil {
|
||||
return err
|
||||
@@ -190,7 +190,7 @@ func MakeEmailPrimary(email *EmailAddress) error {
|
||||
}
|
||||
|
||||
user.Email = email.Email
|
||||
if _, err = sess.Id(user.Id).AllCols().Update(user); err != nil {
|
||||
if _, err = sess.Id(user.ID).AllCols().Update(user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -102,12 +102,12 @@ type Webhook struct {
|
||||
}
|
||||
|
||||
func (w *Webhook) BeforeInsert() {
|
||||
w.CreatedUnix = time.Now().UTC().Unix()
|
||||
w.CreatedUnix = time.Now().Unix()
|
||||
w.UpdatedUnix = w.CreatedUnix
|
||||
}
|
||||
|
||||
func (w *Webhook) BeforeUpdate() {
|
||||
w.UpdatedUnix = time.Now().UTC().Unix()
|
||||
w.UpdatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (w *Webhook) AfterSet(colName string, _ xorm.Cell) {
|
||||
@@ -239,7 +239,7 @@ func deleteWebhook(bean *Webhook) (err error) {
|
||||
}
|
||||
|
||||
// DeleteWebhookByRepoID deletes webhook of repository by given ID.
|
||||
func DeleteWebhookByRepoID(repoID, id int64) (error) {
|
||||
func DeleteWebhookByRepoID(repoID, id int64) error {
|
||||
return deleteWebhook(&Webhook{
|
||||
ID: id,
|
||||
RepoID: repoID,
|
||||
@@ -247,7 +247,7 @@ func DeleteWebhookByRepoID(repoID, id int64) (error) {
|
||||
}
|
||||
|
||||
// DeleteWebhookByOrgID deletes webhook of organization by given ID.
|
||||
func DeleteWebhookByOrgID(orgID, id int64) (error) {
|
||||
func DeleteWebhookByOrgID(orgID, id int64) error {
|
||||
return deleteWebhook(&Webhook{
|
||||
ID: id,
|
||||
OrgID: orgID,
|
||||
@@ -573,7 +573,7 @@ func (t *HookTask) deliver() {
|
||||
}
|
||||
|
||||
defer func() {
|
||||
t.Delivered = time.Now().UTC().UnixNano()
|
||||
t.Delivered = time.Now().UnixNano()
|
||||
if t.IsSucceed {
|
||||
log.Trace("Hook delivered: %s", t.UUID)
|
||||
} else {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -105,6 +105,19 @@ func (ctx *Context) Handle(status int, title string, err error) {
|
||||
ctx.HTML(status, base.TplName(fmt.Sprintf("status/%d", status)))
|
||||
}
|
||||
|
||||
// HandleError use error check function to determine if server should
|
||||
// response as client input error or server internal error.
|
||||
// It responses with given status code for client error,
|
||||
// or error context description for logging purpose of server error.
|
||||
func (ctx *Context) HandleError(title string, errck func(error) bool, err error, status int) {
|
||||
if errck(err) {
|
||||
ctx.Error(status, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Handle(500, title, err)
|
||||
}
|
||||
|
||||
func (ctx *Context) HandleText(status int, title string) {
|
||||
if (status/100 == 4) || (status/100 == 5) {
|
||||
log.Error(4, "%s", title)
|
||||
@@ -156,7 +169,7 @@ func Contexter() macaron.Handler {
|
||||
ctx.IsSigned = true
|
||||
ctx.Data["IsSigned"] = ctx.IsSigned
|
||||
ctx.Data["SignedUser"] = ctx.User
|
||||
ctx.Data["SignedUserID"] = ctx.User.Id
|
||||
ctx.Data["SignedUserID"] = ctx.User.ID
|
||||
ctx.Data["SignedUserName"] = ctx.User.Name
|
||||
ctx.Data["IsAdmin"] = ctx.User.IsAdmin
|
||||
} else {
|
||||
|
||||
@@ -72,13 +72,13 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||
ctx.Org.IsTeamMember = true
|
||||
ctx.Org.IsTeamAdmin = true
|
||||
} else if ctx.IsSigned {
|
||||
ctx.Org.IsOwner = org.IsOwnedBy(ctx.User.Id)
|
||||
ctx.Org.IsOwner = org.IsOwnedBy(ctx.User.ID)
|
||||
if ctx.Org.IsOwner {
|
||||
ctx.Org.IsMember = true
|
||||
ctx.Org.IsTeamMember = true
|
||||
ctx.Org.IsTeamAdmin = true
|
||||
} else {
|
||||
if org.IsOrgMember(ctx.User.Id) {
|
||||
if org.IsOrgMember(ctx.User.ID) {
|
||||
ctx.Org.IsMember = true
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,8 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if err := org.GetUserTeams(ctx.User.Id); err != nil {
|
||||
org.Teams, err = org.GetUserTeams(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.Handle(500, "GetUserTeams", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func RepoAssignment(args ...bool) macaron.Handler {
|
||||
ctx.Repo.Owner = owner
|
||||
|
||||
// Get repository.
|
||||
repo, err := models.GetRepositoryByName(owner.Id, repoName)
|
||||
repo, err := models.GetRepositoryByName(owner.ID, repoName)
|
||||
if err != nil {
|
||||
if models.IsErrRepoNotExist(err) {
|
||||
ctx.Handle(404, "GetRepositoryByName", err)
|
||||
@@ -198,8 +198,8 @@ func RepoAssignment(args ...bool) macaron.Handler {
|
||||
ctx.Data["WikiCloneLink"] = repo.WikiCloneLink()
|
||||
|
||||
if ctx.IsSigned {
|
||||
ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.ID)
|
||||
ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.ID)
|
||||
ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.ID, repo.ID)
|
||||
ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.ID, repo.ID)
|
||||
}
|
||||
|
||||
// repo is bare and display enable
|
||||
|
||||
@@ -75,7 +75,7 @@ func IsReadmeFile(name string) bool {
|
||||
|
||||
var (
|
||||
// MentionPattern matches string that mentions someone, e.g. @Unknwon
|
||||
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z_\.]+`)
|
||||
MentionPattern = regexp.MustCompile(`(\s|^)@[0-9a-zA-Z-_\.]+`)
|
||||
|
||||
// CommitPattern matches link to certain commit with or without trailing hash,
|
||||
// e.g. https://try.gogs.io/gogs/gogs/commit/d8a994ef243349f321568f9e36d5c3f444b99cae#diff-2
|
||||
|
||||
@@ -115,15 +115,23 @@ var (
|
||||
ScriptType string
|
||||
|
||||
// UI settings
|
||||
ExplorePagingNum int
|
||||
IssuePagingNum int
|
||||
FeedMaxCommitNum int
|
||||
AdminUserPagingNum int
|
||||
AdminRepoPagingNum int
|
||||
AdminNoticePagingNum int
|
||||
AdminOrgPagingNum int
|
||||
ThemeColorMetaTag string
|
||||
MaxDisplayFileSize int64
|
||||
UI struct {
|
||||
ExplorePagingNum int
|
||||
IssuePagingNum int
|
||||
FeedMaxCommitNum int
|
||||
ThemeColorMetaTag string
|
||||
MaxDisplayFileSize int64
|
||||
|
||||
Admin struct {
|
||||
UserPagingNum int
|
||||
RepoPagingNum int
|
||||
NoticePagingNum int
|
||||
OrgPagingNum int
|
||||
} `ini:"ui.admin"`
|
||||
User struct {
|
||||
RepoPagingNum int
|
||||
} `ini:"ui.user"`
|
||||
}
|
||||
|
||||
// Markdown sttings
|
||||
Markdown struct {
|
||||
@@ -437,20 +445,6 @@ func NewContext() {
|
||||
log.Fatal(4, "Fail to map Repository settings: %v", err)
|
||||
}
|
||||
|
||||
// UI settings.
|
||||
sec = Cfg.Section("ui")
|
||||
ExplorePagingNum = sec.Key("EXPLORE_PAGING_NUM").MustInt(20)
|
||||
IssuePagingNum = sec.Key("ISSUE_PAGING_NUM").MustInt(10)
|
||||
FeedMaxCommitNum = sec.Key("FEED_MAX_COMMIT_NUM").MustInt(5)
|
||||
MaxDisplayFileSize = sec.Key("MAX_DISPLAY_FILE_SIZE").MustInt64(8388608)
|
||||
|
||||
sec = Cfg.Section("ui.admin")
|
||||
AdminUserPagingNum = sec.Key("USER_PAGING_NUM").MustInt(50)
|
||||
AdminRepoPagingNum = sec.Key("REPO_PAGING_NUM").MustInt(50)
|
||||
AdminNoticePagingNum = sec.Key("NOTICE_PAGING_NUM").MustInt(50)
|
||||
AdminOrgPagingNum = sec.Key("ORG_PAGING_NUM").MustInt(50)
|
||||
ThemeColorMetaTag = sec.Key("THEME_COLOR_META_TAG").MustString("#ff5343")
|
||||
|
||||
sec = Cfg.Section("picture")
|
||||
AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(path.Join(AppDataPath, "avatars"))
|
||||
forcePathSeparator(AvatarUploadPath)
|
||||
@@ -470,7 +464,9 @@ func NewContext() {
|
||||
DisableGravatar = true
|
||||
}
|
||||
|
||||
if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil {
|
||||
if err = Cfg.Section("ui").MapTo(&UI); err != nil {
|
||||
log.Fatal(4, "Fail to map UI settings: %v", err)
|
||||
} else if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil {
|
||||
log.Fatal(4, "Fail to map Markdown settings: %v", err)
|
||||
} else if err = Cfg.Section("cron").MapTo(&Cron); err != nil {
|
||||
log.Fatal(4, "Fail to map Cron settings: %v", err)
|
||||
|
||||
@@ -102,7 +102,7 @@ func NewFuncMap() []template.FuncMap {
|
||||
},
|
||||
"RenderCommitMessage": RenderCommitMessage,
|
||||
"ThemeColorMetaTag": func() string {
|
||||
return setting.ThemeColorMetaTag
|
||||
return setting.UI.ThemeColorMetaTag
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -1248,10 +1248,15 @@ footer .ui.language .menu {
|
||||
.repository.file.list #repo-files-table tbody .octicon {
|
||||
margin-left: 3px;
|
||||
margin-right: 5px;
|
||||
color: #777;
|
||||
}
|
||||
.repository.file.list #repo-files-table tbody .octicon.octicon-mail-reply {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.repository.file.list #repo-files-table tbody .octicon.octicon-file-directory,
|
||||
.repository.file.list #repo-files-table tbody .octicon.octicon-file-submodule {
|
||||
color: #1e70bf;
|
||||
}
|
||||
.repository.file.list #repo-files-table td {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
@@ -1452,7 +1457,10 @@ footer .ui.language .menu {
|
||||
.repository.view.issue .comment-list .comment .actions .item {
|
||||
float: left;
|
||||
}
|
||||
.repository.view.issue .comment-list .comment .actions a.item {
|
||||
.repository.view.issue .comment-list .comment .actions .item.tag {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.repository.view.issue .comment-list .comment .actions .item.action {
|
||||
margin-top: 6px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
@@ -1556,20 +1564,24 @@ footer .ui.language .menu {
|
||||
.repository.view.issue .comment-list .event .octicon {
|
||||
width: 30px;
|
||||
float: left;
|
||||
margin-left: -36px;
|
||||
text-align: center;
|
||||
}
|
||||
.repository.view.issue .comment-list .event .octicon.octicon-circle-slash {
|
||||
margin-top: 5px;
|
||||
margin-left: -34.5px;
|
||||
font-size: 20px;
|
||||
color: #bd2c00;
|
||||
}
|
||||
.repository.view.issue .comment-list .event .octicon.octicon-primitive-dot {
|
||||
margin-left: -28.5px;
|
||||
margin-right: -1px;
|
||||
font-size: 30px;
|
||||
color: #6cc644;
|
||||
}
|
||||
.repository.view.issue .comment-list .event .octicon.octicon-bookmark {
|
||||
margin-top: 3px;
|
||||
margin-left: -31px;
|
||||
margin-right: -1px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.repository.view.issue .comment-list .event .detail {
|
||||
@@ -1968,6 +1980,9 @@ footer .ui.language .menu {
|
||||
.repository.new.release .target {
|
||||
min-width: 500px;
|
||||
}
|
||||
.repository.new.release .target #tag-name {
|
||||
margin-top: -4px;
|
||||
}
|
||||
.repository.new.release .target .at {
|
||||
margin-left: -5px;
|
||||
margin-right: 5px;
|
||||
@@ -2560,9 +2575,10 @@ footer .ui.language .menu {
|
||||
border-radius: 3px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.feeds .list .header {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
.feeds .list .header .ui.label {
|
||||
margin-top: -4px;
|
||||
padding: 4px 5px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.feeds .list .header .plus.icon {
|
||||
margin-top: 5px;
|
||||
|
||||
@@ -250,6 +250,22 @@ function initRepository() {
|
||||
$prompt_span.hide();
|
||||
}
|
||||
});
|
||||
|
||||
// Enable or select internal/external wiki system and issue tracker.
|
||||
$('.enable-system').change(function () {
|
||||
if (this.checked) {
|
||||
$($(this).data('target')).removeClass('disabled');
|
||||
} else {
|
||||
$($(this).data('target')).addClass('disabled');
|
||||
}
|
||||
});
|
||||
$('.enable-system-radio').change(function () {
|
||||
if (this.value == 'false') {
|
||||
$($(this).data('target')).addClass('disabled');
|
||||
} else if (this.value == 'true') {
|
||||
$($(this).data('target')).removeClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Labels
|
||||
@@ -342,7 +358,7 @@ function initRepository() {
|
||||
|
||||
// Edit issue or comment content
|
||||
$('.edit-content').click(function () {
|
||||
var $segment = $(this).parent().parent().next();
|
||||
var $segment = $(this).parent().parent().parent().next();
|
||||
var $edit_content_zone = $segment.find('.edit-content-zone');
|
||||
var $render_content = $segment.find('.render-content');
|
||||
var $raw_content = $segment.find('.raw-content');
|
||||
@@ -404,6 +420,19 @@ function initRepository() {
|
||||
return false;
|
||||
});
|
||||
|
||||
// Delete comment
|
||||
$('.delete-comment').click(function () {
|
||||
var $this = $(this);
|
||||
if (confirm($this.data('locale'))) {
|
||||
$.post($this.data('url'), {
|
||||
"_csrf": csrf
|
||||
}).success(function () {
|
||||
$('#' + $this.data('comment-id')).remove();
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Change status
|
||||
var $status_btn = $('#status-button');
|
||||
$('#content').keyup(function () {
|
||||
@@ -458,11 +487,11 @@ function initRepository() {
|
||||
}
|
||||
}
|
||||
|
||||
function initRepositoryCollaboration(){
|
||||
function initRepositoryCollaboration() {
|
||||
console.log('initRepositoryCollaboration');
|
||||
|
||||
// Change collaborator access mode
|
||||
$('.access-mode.menu .item').click(function(){
|
||||
$('.access-mode.menu .item').click(function () {
|
||||
var $menu = $(this).parent();
|
||||
$.post($menu.data('url'), {
|
||||
"_csrf": csrf,
|
||||
@@ -958,11 +987,11 @@ $(document).ready(function () {
|
||||
$('.show-modal.button').click(function () {
|
||||
$($(this).data('modal')).modal('show');
|
||||
});
|
||||
$('.delete-post.button').click(function(){
|
||||
$('.delete-post.button').click(function () {
|
||||
var $this = $(this);
|
||||
$.post($this.data('request-url'),{
|
||||
$.post($this.data('request-url'), {
|
||||
"_csrf": csrf
|
||||
}).done(function(){
|
||||
}).done(function () {
|
||||
window.location.href = $this.data('done-url');
|
||||
});
|
||||
});
|
||||
@@ -1116,7 +1145,7 @@ $(window).load(function () {
|
||||
}
|
||||
});
|
||||
|
||||
$(function() {
|
||||
if ($('.user.signin').length >0) return;
|
||||
$('form').areYouSure();
|
||||
$(function () {
|
||||
if ($('.user.signin').length > 0) return;
|
||||
$('form').areYouSure();
|
||||
});
|
||||
|
||||
@@ -92,8 +92,11 @@
|
||||
|
||||
.list {
|
||||
.header {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
.ui.label {
|
||||
margin-top: -4px;
|
||||
padding: 4px 5px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.plus.icon {
|
||||
margin-top: 5px;
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
}
|
||||
.item {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
.label.color {
|
||||
padding: 0 8px;
|
||||
margin-right: 5px;
|
||||
@@ -180,9 +180,13 @@
|
||||
.octicon {
|
||||
margin-left: 3px;
|
||||
margin-right: 5px;
|
||||
color: #777;
|
||||
&.octicon-mail-reply {
|
||||
margin-right: 10px;
|
||||
}
|
||||
&.octicon-file-directory, &.octicon-file-submodule {
|
||||
color: #1e70bf;
|
||||
}
|
||||
}
|
||||
}
|
||||
td {
|
||||
@@ -393,10 +397,13 @@
|
||||
.actions {
|
||||
.item {
|
||||
float: left;
|
||||
}
|
||||
a.item {
|
||||
margin-top: 6px;
|
||||
margin-left: 10px;
|
||||
&.tag {
|
||||
margin-right: 5px;
|
||||
}
|
||||
&.action {
|
||||
margin-top: 6px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content {
|
||||
@@ -483,19 +490,23 @@
|
||||
.octicon {
|
||||
width: 30px;
|
||||
float: left;
|
||||
margin-left: -36px;
|
||||
text-align: center;
|
||||
&.octicon-circle-slash {
|
||||
margin-top: 5px;
|
||||
margin-left: -34.5px;
|
||||
font-size: 20px;
|
||||
color: #bd2c00;
|
||||
}
|
||||
&.octicon-primitive-dot {
|
||||
margin-left: -28.5px;
|
||||
margin-right: -1px;
|
||||
font-size: 30px;
|
||||
color: #6cc644;
|
||||
}
|
||||
&.octicon-bookmark {
|
||||
margin-top: 3px;
|
||||
margin-left: -31px;
|
||||
margin-right: -1px;
|
||||
font-size: 25px;
|
||||
}
|
||||
}
|
||||
@@ -954,6 +965,10 @@
|
||||
.target {
|
||||
min-width: 500px;
|
||||
|
||||
#tag-name {
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.at {
|
||||
margin-left: -5px;
|
||||
margin-right: 5px;
|
||||
|
||||
8
public/plugins/codemirror-5.17.0/.gitattributes
vendored
Normal file
8
public/plugins/codemirror-5.17.0/.gitattributes
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
*.txt text
|
||||
*.js text
|
||||
*.html text
|
||||
*.md text
|
||||
*.json text
|
||||
*.yml text
|
||||
*.css text
|
||||
*.svg text
|
||||
8
public/plugins/codemirror-5.17.0/.gitignore
vendored
Normal file
8
public/plugins/codemirror-5.17.0/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
/node_modules
|
||||
/npm-debug.log
|
||||
/test*.html
|
||||
.tern-*
|
||||
*~
|
||||
*.swp
|
||||
.idea
|
||||
*.iml
|
||||
10
public/plugins/codemirror-5.17.0/.npmignore
Normal file
10
public/plugins/codemirror-5.17.0/.npmignore
Normal file
@@ -0,0 +1,10 @@
|
||||
/node_modules
|
||||
/demo
|
||||
/doc
|
||||
/test
|
||||
/test*.html
|
||||
/index.html
|
||||
/mode/*/*test.js
|
||||
/mode/*/*.html
|
||||
/mode/index.html
|
||||
.*
|
||||
4
public/plugins/codemirror-5.17.0/.travis.yml
Normal file
4
public/plugins/codemirror-5.17.0/.travis.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- stable
|
||||
sudo: false
|
||||
64
public/plugins/codemirror-5.17.0/addon/mode/loadmode.js
Normal file
64
public/plugins/codemirror-5.17.0/addon/mode/loadmode.js
Normal file
@@ -0,0 +1,64 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"), "cjs");
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); });
|
||||
else // Plain browser env
|
||||
mod(CodeMirror, "plain");
|
||||
})(function(CodeMirror, env) {
|
||||
if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js";
|
||||
|
||||
var loading = {};
|
||||
function splitCallback(cont, n) {
|
||||
var countDown = n;
|
||||
return function() { if (--countDown == 0) cont(); };
|
||||
}
|
||||
function ensureDeps(mode, cont) {
|
||||
var deps = CodeMirror.modes[mode].dependencies;
|
||||
if (!deps) return cont();
|
||||
var missing = [];
|
||||
for (var i = 0; i < deps.length; ++i) {
|
||||
if (!CodeMirror.modes.hasOwnProperty(deps[i]))
|
||||
missing.push(deps[i]);
|
||||
}
|
||||
if (!missing.length) return cont();
|
||||
var split = splitCallback(cont, missing.length);
|
||||
for (var i = 0; i < missing.length; ++i)
|
||||
CodeMirror.requireMode(missing[i], split);
|
||||
}
|
||||
|
||||
CodeMirror.requireMode = function(mode, cont) {
|
||||
if (typeof mode != "string") mode = mode.name;
|
||||
if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont);
|
||||
if (loading.hasOwnProperty(mode)) return loading[mode].push(cont);
|
||||
|
||||
var file = CodeMirror.modeURL.replace(/%N/g, mode);
|
||||
if (env == "plain") {
|
||||
var script = document.createElement("script");
|
||||
script.src = file;
|
||||
var others = document.getElementsByTagName("script")[0];
|
||||
var list = loading[mode] = [cont];
|
||||
CodeMirror.on(script, "load", function() {
|
||||
ensureDeps(mode, function() {
|
||||
for (var i = 0; i < list.length; ++i) list[i]();
|
||||
});
|
||||
});
|
||||
others.parentNode.insertBefore(script, others);
|
||||
} else if (env == "cjs") {
|
||||
require(file);
|
||||
cont();
|
||||
} else if (env == "amd") {
|
||||
requirejs([file], cont);
|
||||
}
|
||||
};
|
||||
|
||||
CodeMirror.autoLoadMode = function(instance, mode) {
|
||||
if (!CodeMirror.modes.hasOwnProperty(mode))
|
||||
CodeMirror.requireMode(mode, function() {
|
||||
instance.setOption("mode", instance.getOption("mode"));
|
||||
});
|
||||
};
|
||||
});
|
||||
123
public/plugins/codemirror-5.17.0/addon/mode/multiplex.js
Normal file
123
public/plugins/codemirror-5.17.0/addon/mode/multiplex.js
Normal file
@@ -0,0 +1,123 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.multiplexingMode = function(outer /*, others */) {
|
||||
// Others should be {open, close, mode [, delimStyle] [, innerStyle]} objects
|
||||
var others = Array.prototype.slice.call(arguments, 1);
|
||||
|
||||
function indexOf(string, pattern, from, returnEnd) {
|
||||
if (typeof pattern == "string") {
|
||||
var found = string.indexOf(pattern, from);
|
||||
return returnEnd && found > -1 ? found + pattern.length : found;
|
||||
}
|
||||
var m = pattern.exec(from ? string.slice(from) : string);
|
||||
return m ? m.index + from + (returnEnd ? m[0].length : 0) : -1;
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
outer: CodeMirror.startState(outer),
|
||||
innerActive: null,
|
||||
inner: null
|
||||
};
|
||||
},
|
||||
|
||||
copyState: function(state) {
|
||||
return {
|
||||
outer: CodeMirror.copyState(outer, state.outer),
|
||||
innerActive: state.innerActive,
|
||||
inner: state.innerActive && CodeMirror.copyState(state.innerActive.mode, state.inner)
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (!state.innerActive) {
|
||||
var cutOff = Infinity, oldContent = stream.string;
|
||||
for (var i = 0; i < others.length; ++i) {
|
||||
var other = others[i];
|
||||
var found = indexOf(oldContent, other.open, stream.pos);
|
||||
if (found == stream.pos) {
|
||||
if (!other.parseDelimiters) stream.match(other.open);
|
||||
state.innerActive = other;
|
||||
state.inner = CodeMirror.startState(other.mode, outer.indent ? outer.indent(state.outer, "") : 0);
|
||||
return other.delimStyle && (other.delimStyle + " " + other.delimStyle + "-open");
|
||||
} else if (found != -1 && found < cutOff) {
|
||||
cutOff = found;
|
||||
}
|
||||
}
|
||||
if (cutOff != Infinity) stream.string = oldContent.slice(0, cutOff);
|
||||
var outerToken = outer.token(stream, state.outer);
|
||||
if (cutOff != Infinity) stream.string = oldContent;
|
||||
return outerToken;
|
||||
} else {
|
||||
var curInner = state.innerActive, oldContent = stream.string;
|
||||
if (!curInner.close && stream.sol()) {
|
||||
state.innerActive = state.inner = null;
|
||||
return this.token(stream, state);
|
||||
}
|
||||
var found = curInner.close ? indexOf(oldContent, curInner.close, stream.pos, curInner.parseDelimiters) : -1;
|
||||
if (found == stream.pos && !curInner.parseDelimiters) {
|
||||
stream.match(curInner.close);
|
||||
state.innerActive = state.inner = null;
|
||||
return curInner.delimStyle && (curInner.delimStyle + " " + curInner.delimStyle + "-close");
|
||||
}
|
||||
if (found > -1) stream.string = oldContent.slice(0, found);
|
||||
var innerToken = curInner.mode.token(stream, state.inner);
|
||||
if (found > -1) stream.string = oldContent;
|
||||
|
||||
if (found == stream.pos && curInner.parseDelimiters)
|
||||
state.innerActive = state.inner = null;
|
||||
|
||||
if (curInner.innerStyle) {
|
||||
if (innerToken) innerToken = innerToken + " " + curInner.innerStyle;
|
||||
else innerToken = curInner.innerStyle;
|
||||
}
|
||||
|
||||
return innerToken;
|
||||
}
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
||||
if (!mode.indent) return CodeMirror.Pass;
|
||||
return mode.indent(state.innerActive ? state.inner : state.outer, textAfter);
|
||||
},
|
||||
|
||||
blankLine: function(state) {
|
||||
var mode = state.innerActive ? state.innerActive.mode : outer;
|
||||
if (mode.blankLine) {
|
||||
mode.blankLine(state.innerActive ? state.inner : state.outer);
|
||||
}
|
||||
if (!state.innerActive) {
|
||||
for (var i = 0; i < others.length; ++i) {
|
||||
var other = others[i];
|
||||
if (other.open === "\n") {
|
||||
state.innerActive = other;
|
||||
state.inner = CodeMirror.startState(other.mode, mode.indent ? mode.indent(state.outer, "") : 0);
|
||||
}
|
||||
}
|
||||
} else if (state.innerActive.close === "\n") {
|
||||
state.innerActive = state.inner = null;
|
||||
}
|
||||
},
|
||||
|
||||
electricChars: outer.electricChars,
|
||||
|
||||
innerMode: function(state) {
|
||||
return state.inner ? {state: state.inner, mode: state.innerActive.mode} : {state: state.outer, mode: outer};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
CodeMirror.defineMode("markdown_with_stex", function(){
|
||||
var inner = CodeMirror.getMode({}, "stex");
|
||||
var outer = CodeMirror.getMode({}, "markdown");
|
||||
|
||||
var innerOptions = {
|
||||
open: '$',
|
||||
close: '$',
|
||||
mode: inner,
|
||||
delimStyle: 'delim',
|
||||
innerStyle: 'inner'
|
||||
};
|
||||
|
||||
return CodeMirror.multiplexingMode(outer, innerOptions);
|
||||
});
|
||||
|
||||
var mode = CodeMirror.getMode({}, "markdown_with_stex");
|
||||
|
||||
function MT(name) {
|
||||
test.mode(
|
||||
name,
|
||||
mode,
|
||||
Array.prototype.slice.call(arguments, 1),
|
||||
'multiplexing');
|
||||
}
|
||||
|
||||
MT(
|
||||
"stexInsideMarkdown",
|
||||
"[strong **Equation:**] [delim&delim-open $][inner&tag \\pi][delim&delim-close $]");
|
||||
})();
|
||||
85
public/plugins/codemirror-5.17.0/addon/mode/overlay.js
Normal file
85
public/plugins/codemirror-5.17.0/addon/mode/overlay.js
Normal file
@@ -0,0 +1,85 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Utility function that allows modes to be combined. The mode given
|
||||
// as the base argument takes care of most of the normal mode
|
||||
// functionality, but a second (typically simple) mode is used, which
|
||||
// can override the style of text. Both modes get to parse all of the
|
||||
// text, but when both assign a non-null style to a piece of code, the
|
||||
// overlay wins, unless the combine argument was true and not overridden,
|
||||
// or state.overlay.combineTokens was true, in which case the styles are
|
||||
// combined.
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.overlayMode = function(base, overlay, combine) {
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
base: CodeMirror.startState(base),
|
||||
overlay: CodeMirror.startState(overlay),
|
||||
basePos: 0, baseCur: null,
|
||||
overlayPos: 0, overlayCur: null,
|
||||
streamSeen: null
|
||||
};
|
||||
},
|
||||
copyState: function(state) {
|
||||
return {
|
||||
base: CodeMirror.copyState(base, state.base),
|
||||
overlay: CodeMirror.copyState(overlay, state.overlay),
|
||||
basePos: state.basePos, baseCur: null,
|
||||
overlayPos: state.overlayPos, overlayCur: null
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream != state.streamSeen ||
|
||||
Math.min(state.basePos, state.overlayPos) < stream.start) {
|
||||
state.streamSeen = stream;
|
||||
state.basePos = state.overlayPos = stream.start;
|
||||
}
|
||||
|
||||
if (stream.start == state.basePos) {
|
||||
state.baseCur = base.token(stream, state.base);
|
||||
state.basePos = stream.pos;
|
||||
}
|
||||
if (stream.start == state.overlayPos) {
|
||||
stream.pos = stream.start;
|
||||
state.overlayCur = overlay.token(stream, state.overlay);
|
||||
state.overlayPos = stream.pos;
|
||||
}
|
||||
stream.pos = Math.min(state.basePos, state.overlayPos);
|
||||
|
||||
// state.overlay.combineTokens always takes precedence over combine,
|
||||
// unless set to null
|
||||
if (state.overlayCur == null) return state.baseCur;
|
||||
else if (state.baseCur != null &&
|
||||
state.overlay.combineTokens ||
|
||||
combine && state.overlay.combineTokens == null)
|
||||
return state.baseCur + " " + state.overlayCur;
|
||||
else return state.overlayCur;
|
||||
},
|
||||
|
||||
indent: base.indent && function(state, textAfter) {
|
||||
return base.indent(state.base, textAfter);
|
||||
},
|
||||
electricChars: base.electricChars,
|
||||
|
||||
innerMode: function(state) { return {state: state.base, mode: base}; },
|
||||
|
||||
blankLine: function(state) {
|
||||
if (base.blankLine) base.blankLine(state.base);
|
||||
if (overlay.blankLine) overlay.blankLine(state.overlay);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
});
|
||||
213
public/plugins/codemirror-5.17.0/addon/mode/simple.js
Normal file
213
public/plugins/codemirror-5.17.0/addon/mode/simple.js
Normal file
@@ -0,0 +1,213 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineSimpleMode = function(name, states) {
|
||||
CodeMirror.defineMode(name, function(config) {
|
||||
return CodeMirror.simpleMode(config, states);
|
||||
});
|
||||
};
|
||||
|
||||
CodeMirror.simpleMode = function(config, states) {
|
||||
ensureState(states, "start");
|
||||
var states_ = {}, meta = states.meta || {}, hasIndentation = false;
|
||||
for (var state in states) if (state != meta && states.hasOwnProperty(state)) {
|
||||
var list = states_[state] = [], orig = states[state];
|
||||
for (var i = 0; i < orig.length; i++) {
|
||||
var data = orig[i];
|
||||
list.push(new Rule(data, states));
|
||||
if (data.indent || data.dedent) hasIndentation = true;
|
||||
}
|
||||
}
|
||||
var mode = {
|
||||
startState: function() {
|
||||
return {state: "start", pending: null,
|
||||
local: null, localState: null,
|
||||
indent: hasIndentation ? [] : null};
|
||||
},
|
||||
copyState: function(state) {
|
||||
var s = {state: state.state, pending: state.pending,
|
||||
local: state.local, localState: null,
|
||||
indent: state.indent && state.indent.slice(0)};
|
||||
if (state.localState)
|
||||
s.localState = CodeMirror.copyState(state.local.mode, state.localState);
|
||||
if (state.stack)
|
||||
s.stack = state.stack.slice(0);
|
||||
for (var pers = state.persistentStates; pers; pers = pers.next)
|
||||
s.persistentStates = {mode: pers.mode,
|
||||
spec: pers.spec,
|
||||
state: pers.state == state.localState ? s.localState : CodeMirror.copyState(pers.mode, pers.state),
|
||||
next: s.persistentStates};
|
||||
return s;
|
||||
},
|
||||
token: tokenFunction(states_, config),
|
||||
innerMode: function(state) { return state.local && {mode: state.local.mode, state: state.localState}; },
|
||||
indent: indentFunction(states_, meta)
|
||||
};
|
||||
if (meta) for (var prop in meta) if (meta.hasOwnProperty(prop))
|
||||
mode[prop] = meta[prop];
|
||||
return mode;
|
||||
};
|
||||
|
||||
function ensureState(states, name) {
|
||||
if (!states.hasOwnProperty(name))
|
||||
throw new Error("Undefined state " + name + " in simple mode");
|
||||
}
|
||||
|
||||
function toRegex(val, caret) {
|
||||
if (!val) return /(?:)/;
|
||||
var flags = "";
|
||||
if (val instanceof RegExp) {
|
||||
if (val.ignoreCase) flags = "i";
|
||||
val = val.source;
|
||||
} else {
|
||||
val = String(val);
|
||||
}
|
||||
return new RegExp((caret === false ? "" : "^") + "(?:" + val + ")", flags);
|
||||
}
|
||||
|
||||
function asToken(val) {
|
||||
if (!val) return null;
|
||||
if (typeof val == "string") return val.replace(/\./g, " ");
|
||||
var result = [];
|
||||
for (var i = 0; i < val.length; i++)
|
||||
result.push(val[i] && val[i].replace(/\./g, " "));
|
||||
return result;
|
||||
}
|
||||
|
||||
function Rule(data, states) {
|
||||
if (data.next || data.push) ensureState(states, data.next || data.push);
|
||||
this.regex = toRegex(data.regex);
|
||||
this.token = asToken(data.token);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
function tokenFunction(states, config) {
|
||||
return function(stream, state) {
|
||||
if (state.pending) {
|
||||
var pend = state.pending.shift();
|
||||
if (state.pending.length == 0) state.pending = null;
|
||||
stream.pos += pend.text.length;
|
||||
return pend.token;
|
||||
}
|
||||
|
||||
if (state.local) {
|
||||
if (state.local.end && stream.match(state.local.end)) {
|
||||
var tok = state.local.endToken || null;
|
||||
state.local = state.localState = null;
|
||||
return tok;
|
||||
} else {
|
||||
var tok = state.local.mode.token(stream, state.localState), m;
|
||||
if (state.local.endScan && (m = state.local.endScan.exec(stream.current())))
|
||||
stream.pos = stream.start + m.index;
|
||||
return tok;
|
||||
}
|
||||
}
|
||||
|
||||
var curState = states[state.state];
|
||||
for (var i = 0; i < curState.length; i++) {
|
||||
var rule = curState[i];
|
||||
var matches = (!rule.data.sol || stream.sol()) && stream.match(rule.regex);
|
||||
if (matches) {
|
||||
if (rule.data.next) {
|
||||
state.state = rule.data.next;
|
||||
} else if (rule.data.push) {
|
||||
(state.stack || (state.stack = [])).push(state.state);
|
||||
state.state = rule.data.push;
|
||||
} else if (rule.data.pop && state.stack && state.stack.length) {
|
||||
state.state = state.stack.pop();
|
||||
}
|
||||
|
||||
if (rule.data.mode)
|
||||
enterLocalMode(config, state, rule.data.mode, rule.token);
|
||||
if (rule.data.indent)
|
||||
state.indent.push(stream.indentation() + config.indentUnit);
|
||||
if (rule.data.dedent)
|
||||
state.indent.pop();
|
||||
if (matches.length > 2) {
|
||||
state.pending = [];
|
||||
for (var j = 2; j < matches.length; j++)
|
||||
if (matches[j])
|
||||
state.pending.push({text: matches[j], token: rule.token[j - 1]});
|
||||
stream.backUp(matches[0].length - (matches[1] ? matches[1].length : 0));
|
||||
return rule.token[0];
|
||||
} else if (rule.token && rule.token.join) {
|
||||
return rule.token[0];
|
||||
} else {
|
||||
return rule.token;
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.next();
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
function cmp(a, b) {
|
||||
if (a === b) return true;
|
||||
if (!a || typeof a != "object" || !b || typeof b != "object") return false;
|
||||
var props = 0;
|
||||
for (var prop in a) if (a.hasOwnProperty(prop)) {
|
||||
if (!b.hasOwnProperty(prop) || !cmp(a[prop], b[prop])) return false;
|
||||
props++;
|
||||
}
|
||||
for (var prop in b) if (b.hasOwnProperty(prop)) props--;
|
||||
return props == 0;
|
||||
}
|
||||
|
||||
function enterLocalMode(config, state, spec, token) {
|
||||
var pers;
|
||||
if (spec.persistent) for (var p = state.persistentStates; p && !pers; p = p.next)
|
||||
if (spec.spec ? cmp(spec.spec, p.spec) : spec.mode == p.mode) pers = p;
|
||||
var mode = pers ? pers.mode : spec.mode || CodeMirror.getMode(config, spec.spec);
|
||||
var lState = pers ? pers.state : CodeMirror.startState(mode);
|
||||
if (spec.persistent && !pers)
|
||||
state.persistentStates = {mode: mode, spec: spec.spec, state: lState, next: state.persistentStates};
|
||||
|
||||
state.localState = lState;
|
||||
state.local = {mode: mode,
|
||||
end: spec.end && toRegex(spec.end),
|
||||
endScan: spec.end && spec.forceEnd !== false && toRegex(spec.end, false),
|
||||
endToken: token && token.join ? token[token.length - 1] : token};
|
||||
}
|
||||
|
||||
function indexOf(val, arr) {
|
||||
for (var i = 0; i < arr.length; i++) if (arr[i] === val) return true;
|
||||
}
|
||||
|
||||
function indentFunction(states, meta) {
|
||||
return function(state, textAfter, line) {
|
||||
if (state.local && state.local.mode.indent)
|
||||
return state.local.mode.indent(state.localState, textAfter, line);
|
||||
if (state.indent == null || state.local || meta.dontIndentStates && indexOf(state.state, meta.dontIndentStates) > -1)
|
||||
return CodeMirror.Pass;
|
||||
|
||||
var pos = state.indent.length - 1, rules = states[state.state];
|
||||
scan: for (;;) {
|
||||
for (var i = 0; i < rules.length; i++) {
|
||||
var rule = rules[i];
|
||||
if (rule.data.dedent && rule.data.dedentIfLineStart !== false) {
|
||||
var m = rule.regex.exec(textAfter);
|
||||
if (m && m[0]) {
|
||||
pos--;
|
||||
if (rule.next || rule.push) rules = states[rule.next || rule.push];
|
||||
textAfter = textAfter.slice(m[0].length);
|
||||
continue scan;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return pos < 0 ? 0 : state.indent[pos];
|
||||
};
|
||||
}
|
||||
});
|
||||
174
public/plugins/codemirror-5.17.0/mode/apl/apl.js
Normal file
174
public/plugins/codemirror-5.17.0/mode/apl/apl.js
Normal file
@@ -0,0 +1,174 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("apl", function() {
|
||||
var builtInOps = {
|
||||
".": "innerProduct",
|
||||
"\\": "scan",
|
||||
"/": "reduce",
|
||||
"⌿": "reduce1Axis",
|
||||
"⍀": "scan1Axis",
|
||||
"¨": "each",
|
||||
"⍣": "power"
|
||||
};
|
||||
var builtInFuncs = {
|
||||
"+": ["conjugate", "add"],
|
||||
"−": ["negate", "subtract"],
|
||||
"×": ["signOf", "multiply"],
|
||||
"÷": ["reciprocal", "divide"],
|
||||
"⌈": ["ceiling", "greaterOf"],
|
||||
"⌊": ["floor", "lesserOf"],
|
||||
"∣": ["absolute", "residue"],
|
||||
"⍳": ["indexGenerate", "indexOf"],
|
||||
"?": ["roll", "deal"],
|
||||
"⋆": ["exponentiate", "toThePowerOf"],
|
||||
"⍟": ["naturalLog", "logToTheBase"],
|
||||
"○": ["piTimes", "circularFuncs"],
|
||||
"!": ["factorial", "binomial"],
|
||||
"⌹": ["matrixInverse", "matrixDivide"],
|
||||
"<": [null, "lessThan"],
|
||||
"≤": [null, "lessThanOrEqual"],
|
||||
"=": [null, "equals"],
|
||||
">": [null, "greaterThan"],
|
||||
"≥": [null, "greaterThanOrEqual"],
|
||||
"≠": [null, "notEqual"],
|
||||
"≡": ["depth", "match"],
|
||||
"≢": [null, "notMatch"],
|
||||
"∈": ["enlist", "membership"],
|
||||
"⍷": [null, "find"],
|
||||
"∪": ["unique", "union"],
|
||||
"∩": [null, "intersection"],
|
||||
"∼": ["not", "without"],
|
||||
"∨": [null, "or"],
|
||||
"∧": [null, "and"],
|
||||
"⍱": [null, "nor"],
|
||||
"⍲": [null, "nand"],
|
||||
"⍴": ["shapeOf", "reshape"],
|
||||
",": ["ravel", "catenate"],
|
||||
"⍪": [null, "firstAxisCatenate"],
|
||||
"⌽": ["reverse", "rotate"],
|
||||
"⊖": ["axis1Reverse", "axis1Rotate"],
|
||||
"⍉": ["transpose", null],
|
||||
"↑": ["first", "take"],
|
||||
"↓": [null, "drop"],
|
||||
"⊂": ["enclose", "partitionWithAxis"],
|
||||
"⊃": ["diclose", "pick"],
|
||||
"⌷": [null, "index"],
|
||||
"⍋": ["gradeUp", null],
|
||||
"⍒": ["gradeDown", null],
|
||||
"⊤": ["encode", null],
|
||||
"⊥": ["decode", null],
|
||||
"⍕": ["format", "formatByExample"],
|
||||
"⍎": ["execute", null],
|
||||
"⊣": ["stop", "left"],
|
||||
"⊢": ["pass", "right"]
|
||||
};
|
||||
|
||||
var isOperator = /[\.\/⌿⍀¨⍣]/;
|
||||
var isNiladic = /⍬/;
|
||||
var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/;
|
||||
var isArrow = /←/;
|
||||
var isComment = /[⍝#].*$/;
|
||||
|
||||
var stringEater = function(type) {
|
||||
var prev;
|
||||
prev = false;
|
||||
return function(c) {
|
||||
prev = c;
|
||||
if (c === type) {
|
||||
return prev === "\\";
|
||||
}
|
||||
return true;
|
||||
};
|
||||
};
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
prev: false,
|
||||
func: false,
|
||||
op: false,
|
||||
string: false,
|
||||
escape: false
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
var ch, funcName;
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
ch = stream.next();
|
||||
if (ch === '"' || ch === "'") {
|
||||
stream.eatWhile(stringEater(ch));
|
||||
stream.next();
|
||||
state.prev = true;
|
||||
return "string";
|
||||
}
|
||||
if (/[\[{\(]/.test(ch)) {
|
||||
state.prev = false;
|
||||
return null;
|
||||
}
|
||||
if (/[\]}\)]/.test(ch)) {
|
||||
state.prev = true;
|
||||
return null;
|
||||
}
|
||||
if (isNiladic.test(ch)) {
|
||||
state.prev = false;
|
||||
return "niladic";
|
||||
}
|
||||
if (/[¯\d]/.test(ch)) {
|
||||
if (state.func) {
|
||||
state.func = false;
|
||||
state.prev = false;
|
||||
} else {
|
||||
state.prev = true;
|
||||
}
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (isOperator.test(ch)) {
|
||||
return "operator apl-" + builtInOps[ch];
|
||||
}
|
||||
if (isArrow.test(ch)) {
|
||||
return "apl-arrow";
|
||||
}
|
||||
if (isFunction.test(ch)) {
|
||||
funcName = "apl-";
|
||||
if (builtInFuncs[ch] != null) {
|
||||
if (state.prev) {
|
||||
funcName += builtInFuncs[ch][1];
|
||||
} else {
|
||||
funcName += builtInFuncs[ch][0];
|
||||
}
|
||||
}
|
||||
state.func = true;
|
||||
state.prev = false;
|
||||
return "function " + funcName;
|
||||
}
|
||||
if (isComment.test(ch)) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
if (ch === "∘" && stream.peek() === ".") {
|
||||
stream.next();
|
||||
return "function jot-dot";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
state.prev = true;
|
||||
return "keyword";
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/apl", "apl");
|
||||
|
||||
});
|
||||
72
public/plugins/codemirror-5.17.0/mode/apl/index.html
Normal file
72
public/plugins/codemirror-5.17.0/mode/apl/index.html
Normal file
@@ -0,0 +1,72 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: APL mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="./apl.js"></script>
|
||||
<style>
|
||||
.CodeMirror { border: 2px inset #dee; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">APL</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>APL mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
⍝ Conway's game of life
|
||||
|
||||
⍝ This example was inspired by the impressive demo at
|
||||
⍝ http://www.youtube.com/watch?v=a9xAKttWgP4
|
||||
|
||||
⍝ Create a matrix:
|
||||
⍝ 0 1 1
|
||||
⍝ 1 1 0
|
||||
⍝ 0 1 0
|
||||
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 2 3 4 7 ⍝ Original creature from demo
|
||||
creature ← (3 3 ⍴ ⍳ 9) ∈ 1 3 6 7 8 ⍝ Glider
|
||||
|
||||
⍝ Place the creature on a larger board, near the centre
|
||||
board ← ¯1 ⊖ ¯2 ⌽ 5 7 ↑ creature
|
||||
|
||||
⍝ A function to move from one generation to the next
|
||||
life ← {∨/ 1 ⍵ ∧ 3 4 = ⊂+/ +⌿ 1 0 ¯1 ∘.⊖ 1 0 ¯1 ⌽¨ ⊂⍵}
|
||||
|
||||
⍝ Compute n-th generation and format it as a
|
||||
⍝ character matrix
|
||||
gen ← {' #'[(life ⍣ ⍵) board]}
|
||||
|
||||
⍝ Show first three generations
|
||||
(gen 1) (gen 2) (gen 3)
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/apl"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Simple mode that tries to handle APL as well as it can.</p>
|
||||
<p>It attempts to label functions/operators based upon
|
||||
monadic/dyadic usage (but this is far from fully fleshed out).
|
||||
This means there are meaningful classnames so hover states can
|
||||
have popups etc.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/apl</code> (APL code)</p>
|
||||
</article>
|
||||
@@ -0,0 +1,73 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function errorIfNotEmpty(stream) {
|
||||
var nonWS = stream.match(/^\s*\S/);
|
||||
stream.skipToEnd();
|
||||
return nonWS ? "error" : null;
|
||||
}
|
||||
|
||||
CodeMirror.defineMode("asciiarmor", function() {
|
||||
return {
|
||||
token: function(stream, state) {
|
||||
var m;
|
||||
if (state.state == "top") {
|
||||
if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) {
|
||||
state.state = "headers";
|
||||
state.type = m[1];
|
||||
return "tag";
|
||||
}
|
||||
return errorIfNotEmpty(stream);
|
||||
} else if (state.state == "headers") {
|
||||
if (stream.sol() && stream.match(/^\w+:/)) {
|
||||
state.state = "header";
|
||||
return "atom";
|
||||
} else {
|
||||
var result = errorIfNotEmpty(stream);
|
||||
if (result) state.state = "body";
|
||||
return result;
|
||||
}
|
||||
} else if (state.state == "header") {
|
||||
stream.skipToEnd();
|
||||
state.state = "headers";
|
||||
return "string";
|
||||
} else if (state.state == "body") {
|
||||
if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) {
|
||||
if (m[1] != state.type) return "error";
|
||||
state.state = "end";
|
||||
return "tag";
|
||||
} else {
|
||||
if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) {
|
||||
return null;
|
||||
} else {
|
||||
stream.next();
|
||||
return "error";
|
||||
}
|
||||
}
|
||||
} else if (state.state == "end") {
|
||||
return errorIfNotEmpty(stream);
|
||||
}
|
||||
},
|
||||
blankLine: function(state) {
|
||||
if (state.state == "headers") state.state = "body";
|
||||
},
|
||||
startState: function() {
|
||||
return {state: "top", type: null};
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("application/pgp", "asciiarmor");
|
||||
CodeMirror.defineMIME("application/pgp-keys", "asciiarmor");
|
||||
CodeMirror.defineMIME("application/pgp-signature", "asciiarmor");
|
||||
});
|
||||
46
public/plugins/codemirror-5.17.0/mode/asciiarmor/index.html
Normal file
46
public/plugins/codemirror-5.17.0/mode/asciiarmor/index.html
Normal file
@@ -0,0 +1,46 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: ASCII Armor (PGP) mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asciiarmor.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">ASCII Armor</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>ASCII Armor (PGP) mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
-----BEGIN PGP MESSAGE-----
|
||||
Version: OpenPrivacy 0.99
|
||||
|
||||
yDgBO22WxBHv7O8X7O/jygAEzol56iUKiXmV+XmpCtmpqQUKiQrFqclFqUDBovzS
|
||||
vBSFjNSiVHsuAA==
|
||||
=njUN
|
||||
-----END PGP MESSAGE-----
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types
|
||||
defined:</strong> <code>application/pgp</code>, <code>application/pgp-keys</code>, <code>application/pgp-signature</code></p>
|
||||
|
||||
</article>
|
||||
204
public/plugins/codemirror-5.17.0/mode/asn.1/asn.1.js
Normal file
204
public/plugins/codemirror-5.17.0/mode/asn.1/asn.1.js
Normal file
@@ -0,0 +1,204 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("asn.1", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
keywords = parserConfig.keywords || {},
|
||||
cmipVerbs = parserConfig.cmipVerbs || {},
|
||||
compareTypes = parserConfig.compareTypes || {},
|
||||
status = parserConfig.status || {},
|
||||
tags = parserConfig.tags || {},
|
||||
storage = parserConfig.storage || {},
|
||||
modifier = parserConfig.modifier || {},
|
||||
accessTypes = parserConfig.accessTypes|| {},
|
||||
multiLineStrings = parserConfig.multiLineStrings,
|
||||
indentStatements = parserConfig.indentStatements !== false;
|
||||
var isOperatorChar = /[\|\^]/;
|
||||
var curPunc;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (/[\[\]\(\){}:=,;]/.test(ch)) {
|
||||
curPunc = ch;
|
||||
return "punctuation";
|
||||
}
|
||||
if (ch == "-"){
|
||||
if (stream.eat("-")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (/\d/.test(ch)) {
|
||||
stream.eatWhile(/[\w\.]/);
|
||||
return "number";
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
stream.eatWhile(isOperatorChar);
|
||||
return "operator";
|
||||
}
|
||||
|
||||
stream.eatWhile(/[\w\-]/);
|
||||
var cur = stream.current();
|
||||
if (keywords.propertyIsEnumerable(cur)) return "keyword";
|
||||
if (cmipVerbs.propertyIsEnumerable(cur)) return "variable cmipVerbs";
|
||||
if (compareTypes.propertyIsEnumerable(cur)) return "atom compareTypes";
|
||||
if (status.propertyIsEnumerable(cur)) return "comment status";
|
||||
if (tags.propertyIsEnumerable(cur)) return "variable-3 tags";
|
||||
if (storage.propertyIsEnumerable(cur)) return "builtin storage";
|
||||
if (modifier.propertyIsEnumerable(cur)) return "string-2 modifier";
|
||||
if (accessTypes.propertyIsEnumerable(cur)) return "atom accessTypes";
|
||||
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped){
|
||||
var afterNext = stream.peek();
|
||||
//look if the character if the quote is like the B in '10100010'B
|
||||
if (afterNext){
|
||||
afterNext = afterNext.toLowerCase();
|
||||
if(afterNext == "b" || afterNext == "h" || afterNext == "o")
|
||||
stream.next();
|
||||
}
|
||||
end = true; break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function Context(indented, column, type, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type == "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
//Interface
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", false),
|
||||
indented: 0,
|
||||
startOfLine: true
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) return null;
|
||||
curPunc = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if ((curPunc == ";" || curPunc == ":" || curPunc == ",")
|
||||
&& ctx.type == "statement"){
|
||||
popContext(state);
|
||||
}
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (indentStatements && (((ctx.type == "}" || ctx.type == "top")
|
||||
&& curPunc != ';') || (ctx.type == "statement"
|
||||
&& curPunc == "newstatement")))
|
||||
pushContext(state, stream.column(), "statement");
|
||||
|
||||
state.startOfLine = false;
|
||||
return style;
|
||||
},
|
||||
|
||||
electricChars: "{}",
|
||||
lineComment: "--",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
CodeMirror.defineMIME("text/x-ttcn-asn", {
|
||||
name: "asn.1",
|
||||
keywords: words("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION" +
|
||||
" REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED" +
|
||||
" WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN" +
|
||||
" IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS" +
|
||||
" MINACCESS MAXACCESS REVISION STATUS DESCRIPTION" +
|
||||
" SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName" +
|
||||
" ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY" +
|
||||
" IMPLIED EXPORTS"),
|
||||
cmipVerbs: words("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"),
|
||||
compareTypes: words("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY" +
|
||||
" MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY" +
|
||||
" OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL" +
|
||||
" SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL" +
|
||||
" TEXTUAL-CONVENTION"),
|
||||
status: words("current deprecated mandatory obsolete"),
|
||||
tags: words("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS" +
|
||||
" UNIVERSAL"),
|
||||
storage: words("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING" +
|
||||
" UTCTime InterfaceIndex IANAifType CMIP-Attribute" +
|
||||
" REAL PACKAGE PACKAGES IpAddress PhysAddress" +
|
||||
" NetworkAddress BITS BMPString TimeStamp TimeTicks" +
|
||||
" TruthValue RowStatus DisplayString GeneralString" +
|
||||
" GraphicString IA5String NumericString" +
|
||||
" PrintableString SnmpAdminAtring TeletexString" +
|
||||
" UTF8String VideotexString VisibleString StringStore" +
|
||||
" ISO646String T61String UniversalString Unsigned32" +
|
||||
" Integer32 Gauge Gauge32 Counter Counter32 Counter64"),
|
||||
modifier: words("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS" +
|
||||
" GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS" +
|
||||
" DEFINED"),
|
||||
accessTypes: words("not-accessible accessible-for-notify read-only" +
|
||||
" read-create read-write"),
|
||||
multiLineStrings: true
|
||||
});
|
||||
});
|
||||
77
public/plugins/codemirror-5.17.0/mode/asn.1/index.html
Normal file
77
public/plugins/codemirror-5.17.0/mode/asn.1/index.html
Normal file
@@ -0,0 +1,77 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: ASN.1 mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asn.1.js"></script>
|
||||
<style type="text/css">
|
||||
.CodeMirror {
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1>
|
||||
<img id=logo src="../../doc/logo.png">
|
||||
</a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One">ASN.1</a>
|
||||
</ul>
|
||||
</div>
|
||||
<article>
|
||||
<h2>ASN.1 example</h2>
|
||||
<div>
|
||||
<textarea id="ttcn-asn-code">
|
||||
--
|
||||
-- Sample ASN.1 Code
|
||||
--
|
||||
MyModule DEFINITIONS ::=
|
||||
BEGIN
|
||||
|
||||
MyTypes ::= SEQUENCE {
|
||||
myObjectId OBJECT IDENTIFIER,
|
||||
mySeqOf SEQUENCE OF MyInt,
|
||||
myBitString BIT STRING {
|
||||
muxToken(0),
|
||||
modemToken(1)
|
||||
}
|
||||
}
|
||||
|
||||
MyInt ::= INTEGER (0..65535)
|
||||
|
||||
END
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var ttcnEditor = CodeMirror.fromTextArea(document.getElementById("ttcn-asn-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-ttcn-asn"
|
||||
});
|
||||
ttcnEditor.setSize(400, 400);
|
||||
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
|
||||
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
|
||||
</script>
|
||||
<br/>
|
||||
<p><strong>Language:</strong> Abstract Syntax Notation One
|
||||
(<a href="http://www.itu.int/en/ITU-T/asn1/Pages/introduction.aspx">ASN.1</a>)
|
||||
</p>
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-ttcn-asn</code></p>
|
||||
|
||||
<br/>
|
||||
<p>The development of this mode has been sponsored by <a href="http://www.ericsson.com/">Ericsson
|
||||
</a>.</p>
|
||||
<p>Coded by Asmelash Tsegay Gebretsadkan </p>
|
||||
</article>
|
||||
|
||||
196
public/plugins/codemirror-5.17.0/mode/asterisk/asterisk.js
Normal file
196
public/plugins/codemirror-5.17.0/mode/asterisk/asterisk.js
Normal file
@@ -0,0 +1,196 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/*
|
||||
* =====================================================================================
|
||||
*
|
||||
* Filename: mode/asterisk/asterisk.js
|
||||
*
|
||||
* Description: CodeMirror mode for Asterisk dialplan
|
||||
*
|
||||
* Created: 05/17/2012 09:20:25 PM
|
||||
* Revision: none
|
||||
*
|
||||
* Author: Stas Kobzar (stas@modulis.ca),
|
||||
* Company: Modulis.ca Inc.
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("asterisk", function() {
|
||||
var atoms = ["exten", "same", "include","ignorepat","switch"],
|
||||
dpcmd = ["#include","#exec"],
|
||||
apps = [
|
||||
"addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi",
|
||||
"alarmreceiver","amd","answer","authenticate","background","backgrounddetect",
|
||||
"bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent",
|
||||
"changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge",
|
||||
"congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge",
|
||||
"dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility",
|
||||
"datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa",
|
||||
"dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy",
|
||||
"externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif",
|
||||
"goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete",
|
||||
"ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus",
|
||||
"jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme",
|
||||
"meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete",
|
||||
"minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode",
|
||||
"mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish",
|
||||
"originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce",
|
||||
"parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones",
|
||||
"privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten",
|
||||
"readfile","receivefax","receivefax","receivefax","record","removequeuemember",
|
||||
"resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun",
|
||||
"saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax",
|
||||
"sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags",
|
||||
"setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel",
|
||||
"slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground",
|
||||
"speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound",
|
||||
"speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor",
|
||||
"stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec",
|
||||
"trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate",
|
||||
"vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring",
|
||||
"waitforsilence","waitmusiconhold","waituntil","while","zapateller"
|
||||
];
|
||||
|
||||
function basicToken(stream,state){
|
||||
var cur = '';
|
||||
var ch = stream.next();
|
||||
// comment
|
||||
if(ch == ";") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
// context
|
||||
if(ch == '[') {
|
||||
stream.skipTo(']');
|
||||
stream.eat(']');
|
||||
return "header";
|
||||
}
|
||||
// string
|
||||
if(ch == '"') {
|
||||
stream.skipTo('"');
|
||||
return "string";
|
||||
}
|
||||
if(ch == "'") {
|
||||
stream.skipTo("'");
|
||||
return "string-2";
|
||||
}
|
||||
// dialplan commands
|
||||
if(ch == '#') {
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current();
|
||||
if(dpcmd.indexOf(cur) !== -1) {
|
||||
stream.skipToEnd();
|
||||
return "strong";
|
||||
}
|
||||
}
|
||||
// application args
|
||||
if(ch == '$'){
|
||||
var ch1 = stream.peek();
|
||||
if(ch1 == '{'){
|
||||
stream.skipTo('}');
|
||||
stream.eat('}');
|
||||
return "variable-3";
|
||||
}
|
||||
}
|
||||
// extension
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current();
|
||||
if(atoms.indexOf(cur) !== -1) {
|
||||
state.extenStart = true;
|
||||
switch(cur) {
|
||||
case 'same': state.extenSame = true; break;
|
||||
case 'include':
|
||||
case 'switch':
|
||||
case 'ignorepat':
|
||||
state.extenInclude = true;break;
|
||||
default:break;
|
||||
}
|
||||
return "atom";
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
extenStart: false,
|
||||
extenSame: false,
|
||||
extenInclude: false,
|
||||
extenExten: false,
|
||||
extenPriority: false,
|
||||
extenApplication: false
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
|
||||
var cur = '';
|
||||
if(stream.eatSpace()) return null;
|
||||
// extension started
|
||||
if(state.extenStart){
|
||||
stream.eatWhile(/[^\s]/);
|
||||
cur = stream.current();
|
||||
if(/^=>?$/.test(cur)){
|
||||
state.extenExten = true;
|
||||
state.extenStart = false;
|
||||
return "strong";
|
||||
} else {
|
||||
state.extenStart = false;
|
||||
stream.skipToEnd();
|
||||
return "error";
|
||||
}
|
||||
} else if(state.extenExten) {
|
||||
// set exten and priority
|
||||
state.extenExten = false;
|
||||
state.extenPriority = true;
|
||||
stream.eatWhile(/[^,]/);
|
||||
if(state.extenInclude) {
|
||||
stream.skipToEnd();
|
||||
state.extenPriority = false;
|
||||
state.extenInclude = false;
|
||||
}
|
||||
if(state.extenSame) {
|
||||
state.extenPriority = false;
|
||||
state.extenSame = false;
|
||||
state.extenApplication = true;
|
||||
}
|
||||
return "tag";
|
||||
} else if(state.extenPriority) {
|
||||
state.extenPriority = false;
|
||||
state.extenApplication = true;
|
||||
stream.next(); // get comma
|
||||
if(state.extenSame) return null;
|
||||
stream.eatWhile(/[^,]/);
|
||||
return "number";
|
||||
} else if(state.extenApplication) {
|
||||
stream.eatWhile(/,/);
|
||||
cur = stream.current();
|
||||
if(cur === ',') return null;
|
||||
stream.eatWhile(/\w/);
|
||||
cur = stream.current().toLowerCase();
|
||||
state.extenApplication = false;
|
||||
if(apps.indexOf(cur) !== -1){
|
||||
return "def strong";
|
||||
}
|
||||
} else{
|
||||
return basicToken(stream,state);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-asterisk", "asterisk");
|
||||
|
||||
});
|
||||
154
public/plugins/codemirror-5.17.0/mode/asterisk/index.html
Normal file
154
public/plugins/codemirror-5.17.0/mode/asterisk/index.html
Normal file
@@ -0,0 +1,154 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Asterisk dialplan mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="asterisk.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border: 1px solid #999;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Asterisk dialplan</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Asterisk dialplan mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
; extensions.conf - the Asterisk dial plan
|
||||
;
|
||||
|
||||
[general]
|
||||
;
|
||||
; If static is set to no, or omitted, then the pbx_config will rewrite
|
||||
; this file when extensions are modified. Remember that all comments
|
||||
; made in the file will be lost when that happens.
|
||||
static=yes
|
||||
|
||||
#include "/etc/asterisk/additional_general.conf
|
||||
|
||||
[iaxprovider]
|
||||
switch => IAX2/user:[key]@myserver/mycontext
|
||||
|
||||
[dynamic]
|
||||
#exec /usr/bin/dynamic-peers.pl
|
||||
|
||||
[trunkint]
|
||||
;
|
||||
; International long distance through trunk
|
||||
;
|
||||
exten => _9011.,1,Macro(dundi-e164,${EXTEN:4})
|
||||
exten => _9011.,n,Dial(${GLOBAL(TRUNK)}/${FILTER(0-9,${EXTEN:${GLOBAL(TRUNKMSD)}})})
|
||||
|
||||
[local]
|
||||
;
|
||||
; Master context for local, toll-free, and iaxtel calls only
|
||||
;
|
||||
ignorepat => 9
|
||||
include => default
|
||||
|
||||
[demo]
|
||||
include => stdexten
|
||||
;
|
||||
; We start with what to do when a call first comes in.
|
||||
;
|
||||
exten => s,1,Wait(1) ; Wait a second, just for fun
|
||||
same => n,Answer ; Answer the line
|
||||
same => n,Set(TIMEOUT(digit)=5) ; Set Digit Timeout to 5 seconds
|
||||
same => n,Set(TIMEOUT(response)=10) ; Set Response Timeout to 10 seconds
|
||||
same => n(restart),BackGround(demo-congrats) ; Play a congratulatory message
|
||||
same => n(instruct),BackGround(demo-instruct) ; Play some instructions
|
||||
same => n,WaitExten ; Wait for an extension to be dialed.
|
||||
|
||||
exten => 2,1,BackGround(demo-moreinfo) ; Give some more information.
|
||||
exten => 2,n,Goto(s,instruct)
|
||||
|
||||
exten => 3,1,Set(LANGUAGE()=fr) ; Set language to french
|
||||
exten => 3,n,Goto(s,restart) ; Start with the congratulations
|
||||
|
||||
exten => 1000,1,Goto(default,s,1)
|
||||
;
|
||||
; We also create an example user, 1234, who is on the console and has
|
||||
; voicemail, etc.
|
||||
;
|
||||
exten => 1234,1,Playback(transfer,skip) ; "Please hold while..."
|
||||
; (but skip if channel is not up)
|
||||
exten => 1234,n,Gosub(${EXTEN},stdexten(${GLOBAL(CONSOLE)}))
|
||||
exten => 1234,n,Goto(default,s,1) ; exited Voicemail
|
||||
|
||||
exten => 1235,1,Voicemail(1234,u) ; Right to voicemail
|
||||
|
||||
exten => 1236,1,Dial(Console/dsp) ; Ring forever
|
||||
exten => 1236,n,Voicemail(1234,b) ; Unless busy
|
||||
|
||||
;
|
||||
; # for when they're done with the demo
|
||||
;
|
||||
exten => #,1,Playback(demo-thanks) ; "Thanks for trying the demo"
|
||||
exten => #,n,Hangup ; Hang them up.
|
||||
|
||||
;
|
||||
; A timeout and "invalid extension rule"
|
||||
;
|
||||
exten => t,1,Goto(#,1) ; If they take too long, give up
|
||||
exten => i,1,Playback(invalid) ; "That's not valid, try again"
|
||||
|
||||
;
|
||||
; Create an extension, 500, for dialing the
|
||||
; Asterisk demo.
|
||||
;
|
||||
exten => 500,1,Playback(demo-abouttotry); Let them know what's going on
|
||||
exten => 500,n,Dial(IAX2/guest@pbx.digium.com/s@default) ; Call the Asterisk demo
|
||||
exten => 500,n,Playback(demo-nogo) ; Couldn't connect to the demo site
|
||||
exten => 500,n,Goto(s,6) ; Return to the start over message.
|
||||
|
||||
;
|
||||
; Create an extension, 600, for evaluating echo latency.
|
||||
;
|
||||
exten => 600,1,Playback(demo-echotest) ; Let them know what's going on
|
||||
exten => 600,n,Echo ; Do the echo test
|
||||
exten => 600,n,Playback(demo-echodone) ; Let them know it's over
|
||||
exten => 600,n,Goto(s,6) ; Start over
|
||||
|
||||
;
|
||||
; You can use the Macro Page to intercom a individual user
|
||||
exten => 76245,1,Macro(page,SIP/Grandstream1)
|
||||
; or if your peernames are the same as extensions
|
||||
exten => _7XXX,1,Macro(page,SIP/${EXTEN})
|
||||
;
|
||||
;
|
||||
; System Wide Page at extension 7999
|
||||
;
|
||||
exten => 7999,1,Set(TIMEOUT(absolute)=60)
|
||||
exten => 7999,2,Page(Local/Grandstream1@page&Local/Xlite1@page&Local/1234@page/n,d)
|
||||
|
||||
; Give voicemail at extension 8500
|
||||
;
|
||||
exten => 8500,1,VoicemailMain
|
||||
exten => 8500,n,Goto(s,6)
|
||||
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-asterisk",
|
||||
matchBrackets: true,
|
||||
lineNumber: true
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-asterisk</code>.</p>
|
||||
|
||||
</article>
|
||||
85
public/plugins/codemirror-5.17.0/mode/brainfuck/brainfuck.js
Normal file
85
public/plugins/codemirror-5.17.0/mode/brainfuck/brainfuck.js
Normal file
@@ -0,0 +1,85 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
// Brainfuck mode created by Michael Kaminsky https://github.com/mkaminsky11
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object")
|
||||
mod(require("../../lib/codemirror"))
|
||||
else if (typeof define == "function" && define.amd)
|
||||
define(["../../lib/codemirror"], mod)
|
||||
else
|
||||
mod(CodeMirror)
|
||||
})(function(CodeMirror) {
|
||||
"use strict"
|
||||
var reserve = "><+-.,[]".split("");
|
||||
/*
|
||||
comments can be either:
|
||||
placed behind lines
|
||||
|
||||
+++ this is a comment
|
||||
|
||||
where reserved characters cannot be used
|
||||
or in a loop
|
||||
[
|
||||
this is ok to use [ ] and stuff
|
||||
]
|
||||
or preceded by #
|
||||
*/
|
||||
CodeMirror.defineMode("brainfuck", function() {
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
commentLine: false,
|
||||
left: 0,
|
||||
right: 0,
|
||||
commentLoop: false
|
||||
}
|
||||
},
|
||||
token: function(stream, state) {
|
||||
if (stream.eatSpace()) return null
|
||||
if(stream.sol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
var ch = stream.next().toString();
|
||||
if(reserve.indexOf(ch) !== -1){
|
||||
if(state.commentLine === true){
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
if(ch === "]" || ch === "["){
|
||||
if(ch === "["){
|
||||
state.left++;
|
||||
}
|
||||
else{
|
||||
state.right++;
|
||||
}
|
||||
return "bracket";
|
||||
}
|
||||
else if(ch === "+" || ch === "-"){
|
||||
return "keyword";
|
||||
}
|
||||
else if(ch === "<" || ch === ">"){
|
||||
return "atom";
|
||||
}
|
||||
else if(ch === "." || ch === ","){
|
||||
return "def";
|
||||
}
|
||||
}
|
||||
else{
|
||||
state.commentLine = true;
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
if(stream.eol()){
|
||||
state.commentLine = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
CodeMirror.defineMIME("text/x-brainfuck","brainfuck")
|
||||
});
|
||||
85
public/plugins/codemirror-5.17.0/mode/brainfuck/index.html
Normal file
85
public/plugins/codemirror-5.17.0/mode/brainfuck/index.html
Normal file
@@ -0,0 +1,85 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Brainfuck mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="./brainfuck.js"></script>
|
||||
<style>
|
||||
.CodeMirror { border: 2px inset #dee; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#"></a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Brainfuck mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
[ This program prints "Hello World!" and a newline to the screen, its
|
||||
length is 106 active command characters [it is not the shortest.]
|
||||
|
||||
This loop is a "comment loop", it's a simple way of adding a comment
|
||||
to a BF program such that you don't have to worry about any command
|
||||
characters. Any ".", ",", "+", "-", "<" and ">" characters are simply
|
||||
ignored, the "[" and "]" characters just have to be balanced.
|
||||
]
|
||||
+++++ +++ Set Cell #0 to 8
|
||||
[
|
||||
>++++ Add 4 to Cell #1; this will always set Cell #1 to 4
|
||||
[ as the cell will be cleared by the loop
|
||||
>++ Add 2 to Cell #2
|
||||
>+++ Add 3 to Cell #3
|
||||
>+++ Add 3 to Cell #4
|
||||
>+ Add 1 to Cell #5
|
||||
<<<<- Decrement the loop counter in Cell #1
|
||||
] Loop till Cell #1 is zero; number of iterations is 4
|
||||
>+ Add 1 to Cell #2
|
||||
>+ Add 1 to Cell #3
|
||||
>- Subtract 1 from Cell #4
|
||||
>>+ Add 1 to Cell #6
|
||||
[<] Move back to the first zero cell you find; this will
|
||||
be Cell #1 which was cleared by the previous loop
|
||||
<- Decrement the loop Counter in Cell #0
|
||||
] Loop till Cell #0 is zero; number of iterations is 8
|
||||
|
||||
The result of this is:
|
||||
Cell No : 0 1 2 3 4 5 6
|
||||
Contents: 0 0 72 104 88 32 8
|
||||
Pointer : ^
|
||||
|
||||
>>. Cell #2 has value 72 which is 'H'
|
||||
>---. Subtract 3 from Cell #3 to get 101 which is 'e'
|
||||
+++++++..+++. Likewise for 'llo' from Cell #3
|
||||
>>. Cell #5 is 32 for the space
|
||||
<-. Subtract 1 from Cell #4 for 87 to give a 'W'
|
||||
<. Cell #3 was set to 'o' from the end of 'Hello'
|
||||
+++.------.--------. Cell #3 for 'rl' and 'd'
|
||||
>>+. Add 1 to Cell #5 gives us an exclamation point
|
||||
>++. And finally a newline from Cell #6
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-brainfuck"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>A mode for Brainfuck</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-brainfuck</code></p>
|
||||
</article>
|
||||
786
public/plugins/codemirror-5.17.0/mode/clike/clike.js
Normal file
786
public/plugins/codemirror-5.17.0/mode/clike/clike.js
Normal file
@@ -0,0 +1,786 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
function Context(indented, column, type, info, align, prev) {
|
||||
this.indented = indented;
|
||||
this.column = column;
|
||||
this.type = type;
|
||||
this.info = info;
|
||||
this.align = align;
|
||||
this.prev = prev;
|
||||
}
|
||||
function pushContext(state, col, type, info) {
|
||||
var indent = state.indented;
|
||||
if (state.context && state.context.type != "statement" && type != "statement")
|
||||
indent = state.context.indented;
|
||||
return state.context = new Context(indent, col, type, info, null, state.context);
|
||||
}
|
||||
function popContext(state) {
|
||||
var t = state.context.type;
|
||||
if (t == ")" || t == "]" || t == "}")
|
||||
state.indented = state.context.indented;
|
||||
return state.context = state.context.prev;
|
||||
}
|
||||
|
||||
function typeBefore(stream, state, pos) {
|
||||
if (state.prevToken == "variable" || state.prevToken == "variable-3") return true;
|
||||
if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true;
|
||||
if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true;
|
||||
}
|
||||
|
||||
function isTopScope(context) {
|
||||
for (;;) {
|
||||
if (!context || context.type == "top") return true;
|
||||
if (context.type == "}" && context.prev.info != "namespace") return false;
|
||||
context = context.prev;
|
||||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineMode("clike", function(config, parserConfig) {
|
||||
var indentUnit = config.indentUnit,
|
||||
statementIndentUnit = parserConfig.statementIndentUnit || indentUnit,
|
||||
dontAlignCalls = parserConfig.dontAlignCalls,
|
||||
keywords = parserConfig.keywords || {},
|
||||
types = parserConfig.types || {},
|
||||
builtin = parserConfig.builtin || {},
|
||||
blockKeywords = parserConfig.blockKeywords || {},
|
||||
defKeywords = parserConfig.defKeywords || {},
|
||||
atoms = parserConfig.atoms || {},
|
||||
hooks = parserConfig.hooks || {},
|
||||
multiLineStrings = parserConfig.multiLineStrings,
|
||||
indentStatements = parserConfig.indentStatements !== false,
|
||||
indentSwitch = parserConfig.indentSwitch !== false,
|
||||
namespaceSeparator = parserConfig.namespaceSeparator,
|
||||
isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/,
|
||||
numberStart = parserConfig.numberStart || /[\d\.]/,
|
||||
number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i,
|
||||
isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/,
|
||||
endStatement = parserConfig.endStatement || /^[;:,]$/;
|
||||
|
||||
var curPunc, isDefKeyword;
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
var ch = stream.next();
|
||||
if (hooks[ch]) {
|
||||
var result = hooks[ch](stream, state);
|
||||
if (result !== false) return result;
|
||||
}
|
||||
if (ch == '"' || ch == "'") {
|
||||
state.tokenize = tokenString(ch);
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
if (isPunctuationChar.test(ch)) {
|
||||
curPunc = ch;
|
||||
return null;
|
||||
}
|
||||
if (numberStart.test(ch)) {
|
||||
stream.backUp(1)
|
||||
if (stream.match(number)) return "number"
|
||||
stream.next()
|
||||
}
|
||||
if (ch == "/") {
|
||||
if (stream.eat("*")) {
|
||||
state.tokenize = tokenComment;
|
||||
return tokenComment(stream, state);
|
||||
}
|
||||
if (stream.eat("/")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
}
|
||||
if (isOperatorChar.test(ch)) {
|
||||
while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {}
|
||||
return "operator";
|
||||
}
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
if (namespaceSeparator) while (stream.match(namespaceSeparator))
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
|
||||
var cur = stream.current();
|
||||
if (contains(keywords, cur)) {
|
||||
if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
||||
if (contains(defKeywords, cur)) isDefKeyword = true;
|
||||
return "keyword";
|
||||
}
|
||||
if (contains(types, cur)) return "variable-3";
|
||||
if (contains(builtin, cur)) {
|
||||
if (contains(blockKeywords, cur)) curPunc = "newstatement";
|
||||
return "builtin";
|
||||
}
|
||||
if (contains(atoms, cur)) return "atom";
|
||||
return "variable";
|
||||
}
|
||||
|
||||
function tokenString(quote) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == quote && !escaped) {end = true; break;}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
if (end || !(escaped || multiLineStrings))
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
};
|
||||
}
|
||||
|
||||
function tokenComment(stream, state) {
|
||||
var maybeEnd = false, ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "/" && maybeEnd) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
maybeEnd = (ch == "*");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function maybeEOL(stream, state) {
|
||||
if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context))
|
||||
state.typeAtEndOfLine = typeBefore(stream, state, stream.pos)
|
||||
}
|
||||
|
||||
// Interface
|
||||
|
||||
return {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: null,
|
||||
context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false),
|
||||
indented: 0,
|
||||
startOfLine: true,
|
||||
prevToken: null
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var ctx = state.context;
|
||||
if (stream.sol()) {
|
||||
if (ctx.align == null) ctx.align = false;
|
||||
state.indented = stream.indentation();
|
||||
state.startOfLine = true;
|
||||
}
|
||||
if (stream.eatSpace()) { maybeEOL(stream, state); return null; }
|
||||
curPunc = isDefKeyword = null;
|
||||
var style = (state.tokenize || tokenBase)(stream, state);
|
||||
if (style == "comment" || style == "meta") return style;
|
||||
if (ctx.align == null) ctx.align = true;
|
||||
|
||||
if (endStatement.test(curPunc)) while (state.context.type == "statement") popContext(state);
|
||||
else if (curPunc == "{") pushContext(state, stream.column(), "}");
|
||||
else if (curPunc == "[") pushContext(state, stream.column(), "]");
|
||||
else if (curPunc == "(") pushContext(state, stream.column(), ")");
|
||||
else if (curPunc == "}") {
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
if (ctx.type == "}") ctx = popContext(state);
|
||||
while (ctx.type == "statement") ctx = popContext(state);
|
||||
}
|
||||
else if (curPunc == ctx.type) popContext(state);
|
||||
else if (indentStatements &&
|
||||
(((ctx.type == "}" || ctx.type == "top") && curPunc != ";") ||
|
||||
(ctx.type == "statement" && curPunc == "newstatement"))) {
|
||||
pushContext(state, stream.column(), "statement", stream.current());
|
||||
}
|
||||
|
||||
if (style == "variable" &&
|
||||
((state.prevToken == "def" ||
|
||||
(parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) &&
|
||||
isTopScope(state.context) && stream.match(/^\s*\(/, false)))))
|
||||
style = "def";
|
||||
|
||||
if (hooks.token) {
|
||||
var result = hooks.token(stream, state, style);
|
||||
if (result !== undefined) style = result;
|
||||
}
|
||||
|
||||
if (style == "def" && parserConfig.styleDefs === false) style = "variable";
|
||||
|
||||
state.startOfLine = false;
|
||||
state.prevToken = isDefKeyword ? "def" : style || curPunc;
|
||||
maybeEOL(stream, state);
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, textAfter) {
|
||||
if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass;
|
||||
var ctx = state.context, firstChar = textAfter && textAfter.charAt(0);
|
||||
if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev;
|
||||
if (parserConfig.dontIndentStatements)
|
||||
while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info))
|
||||
ctx = ctx.prev
|
||||
if (hooks.indent) {
|
||||
var hook = hooks.indent(state, ctx, textAfter);
|
||||
if (typeof hook == "number") return hook
|
||||
}
|
||||
var closing = firstChar == ctx.type;
|
||||
var switchBlock = ctx.prev && ctx.prev.info == "switch";
|
||||
if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) {
|
||||
while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev
|
||||
return ctx.indented
|
||||
}
|
||||
if (ctx.type == "statement")
|
||||
return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit);
|
||||
if (ctx.align && (!dontAlignCalls || ctx.type != ")"))
|
||||
return ctx.column + (closing ? 0 : 1);
|
||||
if (ctx.type == ")" && !closing)
|
||||
return ctx.indented + statementIndentUnit;
|
||||
|
||||
return ctx.indented + (closing ? 0 : indentUnit) +
|
||||
(!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0);
|
||||
},
|
||||
|
||||
electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/,
|
||||
blockCommentStart: "/*",
|
||||
blockCommentEnd: "*/",
|
||||
lineComment: "//",
|
||||
fold: "brace"
|
||||
};
|
||||
});
|
||||
|
||||
function words(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
function contains(words, word) {
|
||||
if (typeof words === "function") {
|
||||
return words(word);
|
||||
} else {
|
||||
return words.propertyIsEnumerable(word);
|
||||
}
|
||||
}
|
||||
var cKeywords = "auto if break case register continue return default do sizeof " +
|
||||
"static else struct switch extern typedef union for goto while enum const volatile";
|
||||
var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t";
|
||||
|
||||
function cppHook(stream, state) {
|
||||
if (!state.startOfLine) return false
|
||||
for (var ch, next = null; ch = stream.peek();) {
|
||||
if (ch == "\\" && stream.match(/^.$/)) {
|
||||
next = cppHook
|
||||
break
|
||||
} else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) {
|
||||
break
|
||||
}
|
||||
stream.next()
|
||||
}
|
||||
state.tokenize = next
|
||||
return "meta"
|
||||
}
|
||||
|
||||
function pointerHook(_stream, state) {
|
||||
if (state.prevToken == "variable-3") return "variable-3";
|
||||
return false;
|
||||
}
|
||||
|
||||
function cpp14Literal(stream) {
|
||||
stream.eatWhile(/[\w\.']/);
|
||||
return "number";
|
||||
}
|
||||
|
||||
function cpp11StringHook(stream, state) {
|
||||
stream.backUp(1);
|
||||
// Raw strings.
|
||||
if (stream.match(/(R|u8R|uR|UR|LR)/)) {
|
||||
var match = stream.match(/"([^\s\\()]{0,16})\(/);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
state.cpp11RawStringDelim = match[1];
|
||||
state.tokenize = tokenRawString;
|
||||
return tokenRawString(stream, state);
|
||||
}
|
||||
// Unicode strings/chars.
|
||||
if (stream.match(/(u8|u|U|L)/)) {
|
||||
if (stream.match(/["']/, /* eat */ false)) {
|
||||
return "string";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Ignore this hook.
|
||||
stream.next();
|
||||
return false;
|
||||
}
|
||||
|
||||
function cppLooksLikeConstructor(word) {
|
||||
var lastTwo = /(\w+)::(\w+)$/.exec(word);
|
||||
return lastTwo && lastTwo[1] == lastTwo[2];
|
||||
}
|
||||
|
||||
// C#-style strings where "" escapes a quote.
|
||||
function tokenAtString(stream, state) {
|
||||
var next;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == '"' && !stream.eat('"')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
// C++11 raw string literal is <prefix>"<delim>( anything )<delim>", where
|
||||
// <delim> can be a string up to 16 characters long.
|
||||
function tokenRawString(stream, state) {
|
||||
// Escape characters that have special regex meanings.
|
||||
var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&');
|
||||
var match = stream.match(new RegExp(".*?\\)" + delim + '"'));
|
||||
if (match)
|
||||
state.tokenize = null;
|
||||
else
|
||||
stream.skipToEnd();
|
||||
return "string";
|
||||
}
|
||||
|
||||
function def(mimes, mode) {
|
||||
if (typeof mimes == "string") mimes = [mimes];
|
||||
var words = [];
|
||||
function add(obj) {
|
||||
if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop))
|
||||
words.push(prop);
|
||||
}
|
||||
add(mode.keywords);
|
||||
add(mode.types);
|
||||
add(mode.builtin);
|
||||
add(mode.atoms);
|
||||
if (words.length) {
|
||||
mode.helperType = mimes[0];
|
||||
CodeMirror.registerHelper("hintWords", mimes[0], words);
|
||||
}
|
||||
|
||||
for (var i = 0; i < mimes.length; ++i)
|
||||
CodeMirror.defineMIME(mimes[i], mode);
|
||||
}
|
||||
|
||||
def(["text/x-csrc", "text/x-c", "text/x-chdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords),
|
||||
types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " +
|
||||
"int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " +
|
||||
"uint32_t uint64_t"),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
defKeywords: words("struct"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook, "*": pointerHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def(["text/x-c++src", "text/x-c++hdr"], {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " +
|
||||
"static_cast typeid catch operator template typename class friend private " +
|
||||
"this using const_cast inline public throw virtual delete mutable protected " +
|
||||
"alignas alignof constexpr decltype nullptr noexcept thread_local final " +
|
||||
"static_assert override"),
|
||||
types: words(cTypes + " bool wchar_t"),
|
||||
blockKeywords: words("catch class do else finally for if struct switch try while"),
|
||||
defKeywords: words("class namespace struct enum union"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
dontIndentStatements: /^template$/,
|
||||
hooks: {
|
||||
"#": cppHook,
|
||||
"*": pointerHook,
|
||||
"u": cpp11StringHook,
|
||||
"U": cpp11StringHook,
|
||||
"L": cpp11StringHook,
|
||||
"R": cpp11StringHook,
|
||||
"0": cpp14Literal,
|
||||
"1": cpp14Literal,
|
||||
"2": cpp14Literal,
|
||||
"3": cpp14Literal,
|
||||
"4": cpp14Literal,
|
||||
"5": cpp14Literal,
|
||||
"6": cpp14Literal,
|
||||
"7": cpp14Literal,
|
||||
"8": cpp14Literal,
|
||||
"9": cpp14Literal,
|
||||
token: function(stream, state, style) {
|
||||
if (style == "variable" && stream.peek() == "(" &&
|
||||
(state.prevToken == ";" || state.prevToken == null ||
|
||||
state.prevToken == "}") &&
|
||||
cppLooksLikeConstructor(stream.current()))
|
||||
return "def";
|
||||
}
|
||||
},
|
||||
namespaceSeparator: "::",
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-java", {
|
||||
name: "clike",
|
||||
keywords: words("abstract assert break case catch class const continue default " +
|
||||
"do else enum extends final finally float for goto if implements import " +
|
||||
"instanceof interface native new package private protected public " +
|
||||
"return static strictfp super switch synchronized this throw throws transient " +
|
||||
"try volatile while"),
|
||||
types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " +
|
||||
"Integer Long Number Object Short String StringBuffer StringBuilder Void"),
|
||||
blockKeywords: words("catch class do else finally for if switch try while"),
|
||||
defKeywords: words("class interface package enum"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
endStatement: /^[;:]$/,
|
||||
number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
},
|
||||
modeProps: {fold: ["brace", "import"]}
|
||||
});
|
||||
|
||||
def("text/x-csharp", {
|
||||
name: "clike",
|
||||
keywords: words("abstract as async await base break case catch checked class const continue" +
|
||||
" default delegate do else enum event explicit extern finally fixed for" +
|
||||
" foreach goto if implicit in interface internal is lock namespace new" +
|
||||
" operator out override params private protected public readonly ref return sealed" +
|
||||
" sizeof stackalloc static struct switch this throw try typeof unchecked" +
|
||||
" unsafe using virtual void volatile while add alias ascending descending dynamic from get" +
|
||||
" global group into join let orderby partial remove select set value var yield"),
|
||||
types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" +
|
||||
" Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" +
|
||||
" UInt64 bool byte char decimal double short int long object" +
|
||||
" sbyte float string ushort uint ulong"),
|
||||
blockKeywords: words("catch class do else finally for foreach if struct switch try while"),
|
||||
defKeywords: words("class interface namespace struct var"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {
|
||||
"@": function(stream, state) {
|
||||
if (stream.eat('"')) {
|
||||
state.tokenize = tokenAtString;
|
||||
return tokenAtString(stream, state);
|
||||
}
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function tokenTripleString(stream, state) {
|
||||
var escaped = false;
|
||||
while (!stream.eol()) {
|
||||
if (!escaped && stream.match('"""')) {
|
||||
state.tokenize = null;
|
||||
break;
|
||||
}
|
||||
escaped = stream.next() == "\\" && !escaped;
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
def("text/x-scala", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
|
||||
/* scala */
|
||||
"abstract case catch class def do else extends final finally for forSome if " +
|
||||
"implicit import lazy match new null object override package private protected return " +
|
||||
"sealed super this throw trait try type val var while with yield _ : = => <- <: " +
|
||||
"<% >: # @ " +
|
||||
|
||||
/* package scala */
|
||||
"assert assume require print println printf readLine readBoolean readByte readShort " +
|
||||
"readChar readInt readLong readFloat readDouble " +
|
||||
|
||||
":: #:: "
|
||||
),
|
||||
types: words(
|
||||
"AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " +
|
||||
"Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " +
|
||||
"Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " +
|
||||
"Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " +
|
||||
"StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " +
|
||||
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
),
|
||||
multiLineStrings: true,
|
||||
blockKeywords: words("catch class do else finally for forSome if match switch try while"),
|
||||
defKeywords: words("class def object package trait type val var"),
|
||||
atoms: words("true false null"),
|
||||
indentStatements: false,
|
||||
indentSwitch: false,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
if (!stream.match('""')) return false;
|
||||
state.tokenize = tokenTripleString;
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
"'": function(stream) {
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
return "atom";
|
||||
},
|
||||
"=": function(stream, state) {
|
||||
var cx = state.context
|
||||
if (cx.type == "}" && cx.align && stream.eat(">")) {
|
||||
state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev)
|
||||
return "operator"
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
modeProps: {closeBrackets: {triples: '"'}}
|
||||
});
|
||||
|
||||
function tokenKotlinString(tripleString){
|
||||
return function (stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while (!stream.eol()) {
|
||||
if (!tripleString && !escaped && stream.match('"') ) {end = true; break;}
|
||||
if (tripleString && stream.match('"""')) {end = true; break;}
|
||||
next = stream.next();
|
||||
if(!escaped && next == "$" && stream.match('{'))
|
||||
stream.skipTo("}");
|
||||
escaped = !escaped && next == "\\" && !tripleString;
|
||||
}
|
||||
if (end || !tripleString)
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
|
||||
def("text/x-kotlin", {
|
||||
name: "clike",
|
||||
keywords: words(
|
||||
/*keywords*/
|
||||
"package as typealias class interface this super val " +
|
||||
"var fun for is in This throw return " +
|
||||
"break continue object if else while do try when !in !is as? " +
|
||||
|
||||
/*soft keywords*/
|
||||
"file import where by get set abstract enum open inner override private public internal " +
|
||||
"protected catch finally out final vararg reified dynamic companion constructor init " +
|
||||
"sealed field property receiver param sparam lateinit data inline noinline tailrec " +
|
||||
"external annotation crossinline const operator infix"
|
||||
),
|
||||
types: words(
|
||||
/* package java.lang */
|
||||
"Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " +
|
||||
"Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " +
|
||||
"Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " +
|
||||
"StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void"
|
||||
),
|
||||
intendSwitch: false,
|
||||
indentStatements: false,
|
||||
multiLineStrings: true,
|
||||
blockKeywords: words("catch class do else finally for if where try while enum"),
|
||||
defKeywords: words("class val var object package interface fun"),
|
||||
atoms: words("true false null this"),
|
||||
hooks: {
|
||||
'"': function(stream, state) {
|
||||
state.tokenize = tokenKotlinString(stream.match('""'));
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
},
|
||||
modeProps: {closeBrackets: {triples: '"'}}
|
||||
});
|
||||
|
||||
def(["x-shader/x-vertex", "x-shader/x-fragment"], {
|
||||
name: "clike",
|
||||
keywords: words("sampler1D sampler2D sampler3D samplerCube " +
|
||||
"sampler1DShadow sampler2DShadow " +
|
||||
"const attribute uniform varying " +
|
||||
"break continue discard return " +
|
||||
"for while do if else struct " +
|
||||
"in out inout"),
|
||||
types: words("float int bool void " +
|
||||
"vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " +
|
||||
"mat2 mat3 mat4"),
|
||||
blockKeywords: words("for while do if else struct"),
|
||||
builtin: words("radians degrees sin cos tan asin acos atan " +
|
||||
"pow exp log exp2 sqrt inversesqrt " +
|
||||
"abs sign floor ceil fract mod min max clamp mix step smoothstep " +
|
||||
"length distance dot cross normalize ftransform faceforward " +
|
||||
"reflect refract matrixCompMult " +
|
||||
"lessThan lessThanEqual greaterThan greaterThanEqual " +
|
||||
"equal notEqual any all not " +
|
||||
"texture1D texture1DProj texture1DLod texture1DProjLod " +
|
||||
"texture2D texture2DProj texture2DLod texture2DProjLod " +
|
||||
"texture3D texture3DProj texture3DLod texture3DProjLod " +
|
||||
"textureCube textureCubeLod " +
|
||||
"shadow1D shadow2D shadow1DProj shadow2DProj " +
|
||||
"shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " +
|
||||
"dFdx dFdy fwidth " +
|
||||
"noise1 noise2 noise3 noise4"),
|
||||
atoms: words("true false " +
|
||||
"gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " +
|
||||
"gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " +
|
||||
"gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " +
|
||||
"gl_FogCoord gl_PointCoord " +
|
||||
"gl_Position gl_PointSize gl_ClipVertex " +
|
||||
"gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " +
|
||||
"gl_TexCoord gl_FogFragCoord " +
|
||||
"gl_FragCoord gl_FrontFacing " +
|
||||
"gl_FragData gl_FragDepth " +
|
||||
"gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " +
|
||||
"gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " +
|
||||
"gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " +
|
||||
"gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " +
|
||||
"gl_ProjectionMatrixInverseTranspose " +
|
||||
"gl_ModelViewProjectionMatrixInverseTranspose " +
|
||||
"gl_TextureMatrixInverseTranspose " +
|
||||
"gl_NormalScale gl_DepthRange gl_ClipPlane " +
|
||||
"gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " +
|
||||
"gl_FrontLightModelProduct gl_BackLightModelProduct " +
|
||||
"gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " +
|
||||
"gl_FogParameters " +
|
||||
"gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " +
|
||||
"gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " +
|
||||
"gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " +
|
||||
"gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " +
|
||||
"gl_MaxDrawBuffers"),
|
||||
indentSwitch: false,
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-nesc", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "as atomic async call command component components configuration event generic " +
|
||||
"implementation includes interface module new norace nx_struct nx_union post provides " +
|
||||
"signal task uses abstract extends"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case do else for if switch while struct"),
|
||||
atoms: words("null true false"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
def("text/x-objectivec", {
|
||||
name: "clike",
|
||||
keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " +
|
||||
"inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"),
|
||||
types: words(cTypes),
|
||||
atoms: words("YES NO NULL NILL ON OFF true false"),
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$]/);
|
||||
return "keyword";
|
||||
},
|
||||
"#": cppHook,
|
||||
indent: function(_state, ctx, textAfter) {
|
||||
if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented
|
||||
}
|
||||
},
|
||||
modeProps: {fold: "brace"}
|
||||
});
|
||||
|
||||
def("text/x-squirrel", {
|
||||
name: "clike",
|
||||
keywords: words("base break clone continue const default delete enum extends function in class" +
|
||||
" foreach local resume return this throw typeof yield constructor instanceof static"),
|
||||
types: words(cTypes),
|
||||
blockKeywords: words("case catch class else for foreach if switch try while"),
|
||||
defKeywords: words("function local class"),
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null"),
|
||||
hooks: {"#": cppHook},
|
||||
modeProps: {fold: ["brace", "include"]}
|
||||
});
|
||||
|
||||
// Ceylon Strings need to deal with interpolation
|
||||
var stringTokenizer = null;
|
||||
function tokenCeylonString(type) {
|
||||
return function(stream, state) {
|
||||
var escaped = false, next, end = false;
|
||||
while (!stream.eol()) {
|
||||
if (!escaped && stream.match('"') &&
|
||||
(type == "single" || stream.match('""'))) {
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
if (!escaped && stream.match('``')) {
|
||||
stringTokenizer = tokenCeylonString(type);
|
||||
end = true;
|
||||
break;
|
||||
}
|
||||
next = stream.next();
|
||||
escaped = type == "single" && !escaped && next == "\\";
|
||||
}
|
||||
if (end)
|
||||
state.tokenize = null;
|
||||
return "string";
|
||||
}
|
||||
}
|
||||
|
||||
def("text/x-ceylon", {
|
||||
name: "clike",
|
||||
keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" +
|
||||
" exists extends finally for function given if import in interface is let module new" +
|
||||
" nonempty object of out outer package return satisfies super switch then this throw" +
|
||||
" try value void while"),
|
||||
types: function(word) {
|
||||
// In Ceylon all identifiers that start with an uppercase are types
|
||||
var first = word.charAt(0);
|
||||
return (first === first.toUpperCase() && first !== first.toLowerCase());
|
||||
},
|
||||
blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"),
|
||||
defKeywords: words("class dynamic function interface module object package value"),
|
||||
builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" +
|
||||
" native optional sealed see serializable shared suppressWarnings tagged throws variable"),
|
||||
isPunctuationChar: /[\[\]{}\(\),;\:\.`]/,
|
||||
isOperatorChar: /[+\-*&%=<>!?|^~:\/]/,
|
||||
numberStart: /[\d#$]/,
|
||||
number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i,
|
||||
multiLineStrings: true,
|
||||
typeFirstDefinitions: true,
|
||||
atoms: words("true false null larger smaller equal empty finished"),
|
||||
indentSwitch: false,
|
||||
styleDefs: false,
|
||||
hooks: {
|
||||
"@": function(stream) {
|
||||
stream.eatWhile(/[\w\$_]/);
|
||||
return "meta";
|
||||
},
|
||||
'"': function(stream, state) {
|
||||
state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single");
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
'`': function(stream, state) {
|
||||
if (!stringTokenizer || !stream.match('`')) return false;
|
||||
state.tokenize = stringTokenizer;
|
||||
stringTokenizer = null;
|
||||
return state.tokenize(stream, state);
|
||||
},
|
||||
"'": function(stream) {
|
||||
stream.eatWhile(/[\w\$_\xa1-\uffff]/);
|
||||
return "atom";
|
||||
},
|
||||
token: function(_stream, state, style) {
|
||||
if ((style == "variable" || style == "variable-3") &&
|
||||
state.prevToken == ".") {
|
||||
return "variable-2";
|
||||
}
|
||||
}
|
||||
},
|
||||
modeProps: {
|
||||
fold: ["brace", "import"],
|
||||
closeBrackets: {triples: '"'}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
360
public/plugins/codemirror-5.17.0/mode/clike/index.html
Normal file
360
public/plugins/codemirror-5.17.0/mode/clike/index.html
Normal file
@@ -0,0 +1,360 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: C-like mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<link rel="stylesheet" href="../../addon/hint/show-hint.css">
|
||||
<script src="../../addon/hint/show-hint.js"></script>
|
||||
<script src="clike.js"></script>
|
||||
<style>.CodeMirror {border: 2px inset #dee;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">C-like</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>C-like mode</h2>
|
||||
|
||||
<div><textarea id="c-code">
|
||||
/* C demo code */
|
||||
|
||||
#include <zmq.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
|
||||
typedef struct {
|
||||
void* arg_socket;
|
||||
zmq_msg_t* arg_msg;
|
||||
char* arg_string;
|
||||
unsigned long arg_len;
|
||||
int arg_int, arg_command;
|
||||
|
||||
int signal_fd;
|
||||
int pad;
|
||||
void* context;
|
||||
sem_t sem;
|
||||
} acl_zmq_context;
|
||||
|
||||
#define p(X) (context->arg_##X)
|
||||
|
||||
void* zmq_thread(void* context_pointer) {
|
||||
acl_zmq_context* context = (acl_zmq_context*)context_pointer;
|
||||
char ok = 'K', err = 'X';
|
||||
int res;
|
||||
|
||||
while (1) {
|
||||
while ((res = sem_wait(&context->sem)) == EINTR);
|
||||
if (res) {write(context->signal_fd, &err, 1); goto cleanup;}
|
||||
switch(p(command)) {
|
||||
case 0: goto cleanup;
|
||||
case 1: p(socket) = zmq_socket(context->context, p(int)); break;
|
||||
case 2: p(int) = zmq_close(p(socket)); break;
|
||||
case 3: p(int) = zmq_bind(p(socket), p(string)); break;
|
||||
case 4: p(int) = zmq_connect(p(socket), p(string)); break;
|
||||
case 5: p(int) = zmq_getsockopt(p(socket), p(int), (void*)p(string), &p(len)); break;
|
||||
case 6: p(int) = zmq_setsockopt(p(socket), p(int), (void*)p(string), p(len)); break;
|
||||
case 7: p(int) = zmq_send(p(socket), p(msg), p(int)); break;
|
||||
case 8: p(int) = zmq_recv(p(socket), p(msg), p(int)); break;
|
||||
case 9: p(int) = zmq_poll(p(socket), p(int), p(len)); break;
|
||||
}
|
||||
p(command) = errno;
|
||||
write(context->signal_fd, &ok, 1);
|
||||
}
|
||||
cleanup:
|
||||
close(context->signal_fd);
|
||||
free(context_pointer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* zmq_thread_init(void* zmq_context, int signal_fd) {
|
||||
acl_zmq_context* context = malloc(sizeof(acl_zmq_context));
|
||||
pthread_t thread;
|
||||
|
||||
context->context = zmq_context;
|
||||
context->signal_fd = signal_fd;
|
||||
sem_init(&context->sem, 1, 0);
|
||||
pthread_create(&thread, 0, &zmq_thread, context);
|
||||
pthread_detach(thread);
|
||||
return context;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>C++ example</h2>
|
||||
|
||||
<div><textarea id="cpp-code">
|
||||
#include <iostream>
|
||||
#include "mystuff/util.h"
|
||||
|
||||
namespace {
|
||||
enum Enum {
|
||||
VAL1, VAL2, VAL3
|
||||
};
|
||||
|
||||
char32_t unicode_string = U"\U0010FFFF";
|
||||
string raw_string = R"delim(anything
|
||||
you
|
||||
want)delim";
|
||||
|
||||
int Helper(const MyType& param) {
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class ForwardDec;
|
||||
|
||||
template <class T, class V>
|
||||
class Class : public BaseClass {
|
||||
const MyType<T, V> member_;
|
||||
|
||||
public:
|
||||
const MyType<T, V>& Method() const {
|
||||
return member_;
|
||||
}
|
||||
|
||||
void Method2(MyType<T, V>* value);
|
||||
}
|
||||
|
||||
template <class T, class V>
|
||||
void Class::Method2(MyType<T, V>* value) {
|
||||
std::out << 1 >> method();
|
||||
value->Method3(member_);
|
||||
member_ = value;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Objective-C example</h2>
|
||||
|
||||
<div><textarea id="objectivec-code">
|
||||
/*
|
||||
This is a longer comment
|
||||
That spans two lines
|
||||
*/
|
||||
|
||||
#import <Test/Test.h>
|
||||
@implementation YourAppDelegate
|
||||
|
||||
// This is a one-line comment
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
|
||||
char myString[] = "This is a C character array";
|
||||
int test = 5;
|
||||
return YES;
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Java example</h2>
|
||||
|
||||
<div><textarea id="java-code">
|
||||
import com.demo.util.MyType;
|
||||
import com.demo.util.MyInterface;
|
||||
|
||||
public enum Enum {
|
||||
VAL1, VAL2, VAL3
|
||||
}
|
||||
|
||||
public class Class<T, V> implements MyInterface {
|
||||
public static final MyType<T, V> member;
|
||||
|
||||
private class InnerClass {
|
||||
public int zero() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MyType method() {
|
||||
return member;
|
||||
}
|
||||
|
||||
public void method2(MyType<T, V> value) {
|
||||
method();
|
||||
value.method3();
|
||||
member = value;
|
||||
}
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Scala example</h2>
|
||||
|
||||
<div><textarea id="scala-code">
|
||||
object FilterTest extends App {
|
||||
def filter(xs: List[Int], threshold: Int) = {
|
||||
def process(ys: List[Int]): List[Int] =
|
||||
if (ys.isEmpty) ys
|
||||
else if (ys.head < threshold) ys.head :: process(ys.tail)
|
||||
else process(ys.tail)
|
||||
process(xs)
|
||||
}
|
||||
println(filter(List(1, 9, 2, 8, 3, 7, 4), 5))
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Kotlin mode</h2>
|
||||
|
||||
<div><textarea id="kotlin-code">
|
||||
package org.wasabi.http
|
||||
|
||||
import java.util.concurrent.Executors
|
||||
import java.net.InetSocketAddress
|
||||
import org.wasabi.app.AppConfiguration
|
||||
import io.netty.bootstrap.ServerBootstrap
|
||||
import io.netty.channel.nio.NioEventLoopGroup
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel
|
||||
import org.wasabi.app.AppServer
|
||||
|
||||
public class HttpServer(private val appServer: AppServer) {
|
||||
|
||||
val bootstrap: ServerBootstrap
|
||||
val primaryGroup: NioEventLoopGroup
|
||||
val workerGroup: NioEventLoopGroup
|
||||
|
||||
init {
|
||||
// Define worker groups
|
||||
primaryGroup = NioEventLoopGroup()
|
||||
workerGroup = NioEventLoopGroup()
|
||||
|
||||
// Initialize bootstrap of server
|
||||
bootstrap = ServerBootstrap()
|
||||
|
||||
bootstrap.group(primaryGroup, workerGroup)
|
||||
bootstrap.channel(javaClass<NioServerSocketChannel>())
|
||||
bootstrap.childHandler(NettyPipelineInitializer(appServer))
|
||||
}
|
||||
|
||||
public fun start(wait: Boolean = true) {
|
||||
val channel = bootstrap.bind(appServer.configuration.port)?.sync()?.channel()
|
||||
|
||||
if (wait) {
|
||||
channel?.closeFuture()?.sync()
|
||||
}
|
||||
}
|
||||
|
||||
public fun stop() {
|
||||
// Shutdown all event loops
|
||||
primaryGroup.shutdownGracefully()
|
||||
workerGroup.shutdownGracefully()
|
||||
|
||||
// Wait till all threads are terminated
|
||||
primaryGroup.terminationFuture().sync()
|
||||
workerGroup.terminationFuture().sync()
|
||||
}
|
||||
}
|
||||
</textarea></div>
|
||||
|
||||
<h2>Ceylon mode</h2>
|
||||
|
||||
<div><textarea id="ceylon-code">
|
||||
"Produces the [[stream|Iterable]] that results from repeated
|
||||
application of the given [[function|next]] to the given
|
||||
[[first]] element of the stream, until the function first
|
||||
returns [[finished]]. If the given function never returns
|
||||
`finished`, the resulting stream is infinite.
|
||||
|
||||
For example:
|
||||
|
||||
loop(0)(2.plus).takeWhile(10.largerThan)
|
||||
|
||||
produces the stream `{ 0, 2, 4, 6, 8 }`."
|
||||
tagged("Streams")
|
||||
shared {Element+} loop<Element>(
|
||||
"The first element of the resulting stream."
|
||||
Element first)(
|
||||
"The function that produces the next element of the
|
||||
stream, given the current element. The function may
|
||||
return [[finished]] to indicate the end of the
|
||||
stream."
|
||||
Element|Finished next(Element element))
|
||||
=> let (start = first)
|
||||
object satisfies {Element+} {
|
||||
first => start;
|
||||
empty => false;
|
||||
function nextElement(Element element)
|
||||
=> next(element);
|
||||
iterator()
|
||||
=> object satisfies Iterator<Element> {
|
||||
variable Element|Finished current = start;
|
||||
shared actual Element|Finished next() {
|
||||
if (!is Finished result = current) {
|
||||
current = nextElement(result);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
return finished;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
</textarea></div>
|
||||
|
||||
<script>
|
||||
var cEditor = CodeMirror.fromTextArea(document.getElementById("c-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-csrc"
|
||||
});
|
||||
var cppEditor = CodeMirror.fromTextArea(document.getElementById("cpp-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-c++src"
|
||||
});
|
||||
var javaEditor = CodeMirror.fromTextArea(document.getElementById("java-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-java"
|
||||
});
|
||||
var objectivecEditor = CodeMirror.fromTextArea(document.getElementById("objectivec-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-objectivec"
|
||||
});
|
||||
var scalaEditor = CodeMirror.fromTextArea(document.getElementById("scala-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-scala"
|
||||
});
|
||||
var kotlinEditor = CodeMirror.fromTextArea(document.getElementById("kotlin-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-kotlin"
|
||||
});
|
||||
var ceylonEditor = CodeMirror.fromTextArea(document.getElementById("ceylon-code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-ceylon"
|
||||
});
|
||||
var mac = CodeMirror.keyMap.default == CodeMirror.keyMap.macDefault;
|
||||
CodeMirror.keyMap.default[(mac ? "Cmd" : "Ctrl") + "-Space"] = "autocomplete";
|
||||
</script>
|
||||
|
||||
<p>Simple mode that tries to handle C-like languages as well as it
|
||||
can. Takes two configuration parameters: <code>keywords</code>, an
|
||||
object whose property names are the keywords in the language,
|
||||
and <code>useCPP</code>, which determines whether C preprocessor
|
||||
directives are recognized.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-csrc</code>
|
||||
(C), <code>text/x-c++src</code> (C++), <code>text/x-java</code>
|
||||
(Java), <code>text/x-csharp</code> (C#),
|
||||
<code>text/x-objectivec</code> (Objective-C),
|
||||
<code>text/x-scala</code> (Scala), <code>text/x-vertex</code>
|
||||
<code>x-shader/x-fragment</code> (shader programs),
|
||||
<code>text/x-squirrel</code> (Squirrel) and
|
||||
<code>text/x-ceylon</code> (Ceylon)</p>
|
||||
</article>
|
||||
767
public/plugins/codemirror-5.17.0/mode/clike/scala.html
Normal file
767
public/plugins/codemirror-5.17.0/mode/clike/scala.html
Normal file
@@ -0,0 +1,767 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Scala mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../theme/ambiance.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="clike.js"></script>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Scala</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Scala mode</h2>
|
||||
<form>
|
||||
<textarea id="code" name="code">
|
||||
|
||||
/* __ *\
|
||||
** ________ ___ / / ___ Scala API **
|
||||
** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
|
||||
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
|
||||
** /____/\___/_/ |_/____/_/ | | **
|
||||
** |/ **
|
||||
\* */
|
||||
|
||||
package scala.collection
|
||||
|
||||
import generic._
|
||||
import mutable.{ Builder, ListBuffer }
|
||||
import annotation.{tailrec, migration, bridge}
|
||||
import annotation.unchecked.{ uncheckedVariance => uV }
|
||||
import parallel.ParIterable
|
||||
|
||||
/** A template trait for traversable collections of type `Traversable[A]`.
|
||||
*
|
||||
* $traversableInfo
|
||||
* @define mutability
|
||||
* @define traversableInfo
|
||||
* This is a base trait of all kinds of $mutability Scala collections. It
|
||||
* implements the behavior common to all collections, in terms of a method
|
||||
* `foreach` with signature:
|
||||
* {{{
|
||||
* def foreach[U](f: Elem => U): Unit
|
||||
* }}}
|
||||
* Collection classes mixing in this trait provide a concrete
|
||||
* `foreach` method which traverses all the
|
||||
* elements contained in the collection, applying a given function to each.
|
||||
* They also need to provide a method `newBuilder`
|
||||
* which creates a builder for collections of the same kind.
|
||||
*
|
||||
* A traversable class might or might not have two properties: strictness
|
||||
* and orderedness. Neither is represented as a type.
|
||||
*
|
||||
* The instances of a strict collection class have all their elements
|
||||
* computed before they can be used as values. By contrast, instances of
|
||||
* a non-strict collection class may defer computation of some of their
|
||||
* elements until after the instance is available as a value.
|
||||
* A typical example of a non-strict collection class is a
|
||||
* <a href="../immutable/Stream.html" target="ContentFrame">
|
||||
* `scala.collection.immutable.Stream`</a>.
|
||||
* A more general class of examples are `TraversableViews`.
|
||||
*
|
||||
* If a collection is an instance of an ordered collection class, traversing
|
||||
* its elements with `foreach` will always visit elements in the
|
||||
* same order, even for different runs of the program. If the class is not
|
||||
* ordered, `foreach` can visit elements in different orders for
|
||||
* different runs (but it will keep the same order in the same run).'
|
||||
*
|
||||
* A typical example of a collection class which is not ordered is a
|
||||
* `HashMap` of objects. The traversal order for hash maps will
|
||||
* depend on the hash codes of its elements, and these hash codes might
|
||||
* differ from one run to the next. By contrast, a `LinkedHashMap`
|
||||
* is ordered because it's `foreach` method visits elements in the
|
||||
* order they were inserted into the `HashMap`.
|
||||
*
|
||||
* @author Martin Odersky
|
||||
* @version 2.8
|
||||
* @since 2.8
|
||||
* @tparam A the element type of the collection
|
||||
* @tparam Repr the type of the actual collection containing the elements.
|
||||
*
|
||||
* @define Coll Traversable
|
||||
* @define coll traversable collection
|
||||
*/
|
||||
trait TraversableLike[+A, +Repr] extends HasNewBuilder[A, Repr]
|
||||
with FilterMonadic[A, Repr]
|
||||
with TraversableOnce[A]
|
||||
with GenTraversableLike[A, Repr]
|
||||
with Parallelizable[A, ParIterable[A]]
|
||||
{
|
||||
self =>
|
||||
|
||||
import Traversable.breaks._
|
||||
|
||||
/** The type implementing this traversable */
|
||||
protected type Self = Repr
|
||||
|
||||
/** The collection of type $coll underlying this `TraversableLike` object.
|
||||
* By default this is implemented as the `TraversableLike` object itself,
|
||||
* but this can be overridden.
|
||||
*/
|
||||
def repr: Repr = this.asInstanceOf[Repr]
|
||||
|
||||
/** The underlying collection seen as an instance of `$Coll`.
|
||||
* By default this is implemented as the current collection object itself,
|
||||
* but this can be overridden.
|
||||
*/
|
||||
protected[this] def thisCollection: Traversable[A] = this.asInstanceOf[Traversable[A]]
|
||||
|
||||
/** A conversion from collections of type `Repr` to `$Coll` objects.
|
||||
* By default this is implemented as just a cast, but this can be overridden.
|
||||
*/
|
||||
protected[this] def toCollection(repr: Repr): Traversable[A] = repr.asInstanceOf[Traversable[A]]
|
||||
|
||||
/** Creates a new builder for this collection type.
|
||||
*/
|
||||
protected[this] def newBuilder: Builder[A, Repr]
|
||||
|
||||
protected[this] def parCombiner = ParIterable.newCombiner[A]
|
||||
|
||||
/** Applies a function `f` to all elements of this $coll.
|
||||
*
|
||||
* Note: this method underlies the implementation of most other bulk operations.
|
||||
* It's important to implement this method in an efficient way.
|
||||
*
|
||||
*
|
||||
* @param f the function that is applied for its side-effect to every element.
|
||||
* The result of function `f` is discarded.
|
||||
*
|
||||
* @tparam U the type parameter describing the result of function `f`.
|
||||
* This result will always be ignored. Typically `U` is `Unit`,
|
||||
* but this is not necessary.
|
||||
*
|
||||
* @usecase def foreach(f: A => Unit): Unit
|
||||
*/
|
||||
def foreach[U](f: A => U): Unit
|
||||
|
||||
/** Tests whether this $coll is empty.
|
||||
*
|
||||
* @return `true` if the $coll contain no elements, `false` otherwise.
|
||||
*/
|
||||
def isEmpty: Boolean = {
|
||||
var result = true
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
result = false
|
||||
break
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Tests whether this $coll is known to have a finite size.
|
||||
* All strict collections are known to have finite size. For a non-strict collection
|
||||
* such as `Stream`, the predicate returns `true` if all elements have been computed.
|
||||
* It returns `false` if the stream is not yet evaluated to the end.
|
||||
*
|
||||
* Note: many collection methods will not work on collections of infinite sizes.
|
||||
*
|
||||
* @return `true` if this collection is known to have finite size, `false` otherwise.
|
||||
*/
|
||||
def hasDefiniteSize = true
|
||||
|
||||
def ++[B >: A, That](that: GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.seq.size)
|
||||
b ++= thisCollection
|
||||
b ++= that.seq
|
||||
b.result
|
||||
}
|
||||
|
||||
@bridge
|
||||
def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
|
||||
++(that: GenTraversableOnce[B])(bf)
|
||||
|
||||
/** Concatenates this $coll with the elements of a traversable collection.
|
||||
* It differs from ++ in that the right operand determines the type of the
|
||||
* resulting collection rather than the left one.
|
||||
*
|
||||
* @param that the traversable to append.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` which contains all elements
|
||||
* of this $coll followed by all elements of `that`.
|
||||
*
|
||||
* @usecase def ++:[B](that: TraversableOnce[B]): $Coll[B]
|
||||
*
|
||||
* @return a new $coll which contains all elements of this $coll
|
||||
* followed by all elements of `that`.
|
||||
*/
|
||||
def ++:[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
if (that.isInstanceOf[IndexedSeqLike[_, _]]) b.sizeHint(this, that.size)
|
||||
b ++= that
|
||||
b ++= thisCollection
|
||||
b.result
|
||||
}
|
||||
|
||||
/** This overload exists because: for the implementation of ++: we should reuse
|
||||
* that of ++ because many collections override it with more efficient versions.
|
||||
* Since TraversableOnce has no '++' method, we have to implement that directly,
|
||||
* but Traversable and down can use the overload.
|
||||
*/
|
||||
def ++:[B >: A, That](that: Traversable[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
|
||||
(that ++ seq)(breakOut)
|
||||
|
||||
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
b.sizeHint(this)
|
||||
for (x <- this) b += f(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this) b ++= f(x).seq
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects all elements of this $coll which satisfy a predicate.
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return a new $coll consisting of all elements of this $coll that satisfy the given
|
||||
* predicate `p`. The order of the elements is preserved.
|
||||
*/
|
||||
def filter(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
for (x <- this)
|
||||
if (p(x)) b += x
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects all elements of this $coll which do not satisfy a predicate.
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return a new $coll consisting of all elements of this $coll that do not satisfy the given
|
||||
* predicate `p`. The order of the elements is preserved.
|
||||
*/
|
||||
def filterNot(p: A => Boolean): Repr = filter(!p(_))
|
||||
|
||||
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this) if (pf.isDefinedAt(x)) b += pf(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Builds a new collection by applying an option-valued function to all
|
||||
* elements of this $coll on which the function is defined.
|
||||
*
|
||||
* @param f the option-valued function which filters and maps the $coll.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying the option-valued function
|
||||
* `f` to each element and collecting all defined results.
|
||||
* The order of the elements is preserved.
|
||||
*
|
||||
* @usecase def filterMap[B](f: A => Option[B]): $Coll[B]
|
||||
*
|
||||
* @param pf the partial function which filters and maps the $coll.
|
||||
* @return a new $coll resulting from applying the given option-valued function
|
||||
* `f` to each element and collecting all defined results.
|
||||
* The order of the elements is preserved.
|
||||
def filterMap[B, That](f: A => Option[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- this)
|
||||
f(x) match {
|
||||
case Some(y) => b += y
|
||||
case _ =>
|
||||
}
|
||||
b.result
|
||||
}
|
||||
*/
|
||||
|
||||
/** Partitions this $coll in two ${coll}s according to a predicate.
|
||||
*
|
||||
* @param p the predicate on which to partition.
|
||||
* @return a pair of ${coll}s: the first $coll consists of all elements that
|
||||
* satisfy the predicate `p` and the second $coll consists of all elements
|
||||
* that don't. The relative order of the elements in the resulting ${coll}s
|
||||
* is the same as in the original $coll.
|
||||
*/
|
||||
def partition(p: A => Boolean): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
for (x <- this) (if (p(x)) l else r) += x
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
|
||||
val m = mutable.Map.empty[K, Builder[A, Repr]]
|
||||
for (elem <- this) {
|
||||
val key = f(elem)
|
||||
val bldr = m.getOrElseUpdate(key, newBuilder)
|
||||
bldr += elem
|
||||
}
|
||||
val b = immutable.Map.newBuilder[K, Repr]
|
||||
for ((k, v) <- m)
|
||||
b += ((k, v.result))
|
||||
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Tests whether a predicate holds for all elements of this $coll.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return `true` if the given predicate `p` holds for all elements
|
||||
* of this $coll, otherwise `false`.
|
||||
*/
|
||||
def forall(p: A => Boolean): Boolean = {
|
||||
var result = true
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (!p(x)) { result = false; break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Tests whether a predicate holds for some of the elements of this $coll.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return `true` if the given predicate `p` holds for some of the
|
||||
* elements of this $coll, otherwise `false`.
|
||||
*/
|
||||
def exists(p: A => Boolean): Boolean = {
|
||||
var result = false
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (p(x)) { result = true; break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/** Finds the first element of the $coll satisfying a predicate, if any.
|
||||
*
|
||||
* $mayNotTerminateInf
|
||||
* $orderDependent
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return an option value containing the first element in the $coll
|
||||
* that satisfies `p`, or `None` if none exists.
|
||||
*/
|
||||
def find(p: A => Boolean): Option[A] = {
|
||||
var result: Option[A] = None
|
||||
breakable {
|
||||
for (x <- this)
|
||||
if (p(x)) { result = Some(x); break }
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That = scanLeft(z)(op)
|
||||
|
||||
def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
b.sizeHint(this, 1)
|
||||
var acc = z
|
||||
b += acc
|
||||
for (x <- this) { acc = op(acc, x); b += acc }
|
||||
b.result
|
||||
}
|
||||
|
||||
@migration(2, 9,
|
||||
"This scanRight definition has changed in 2.9.\n" +
|
||||
"The previous behavior can be reproduced with scanRight.reverse."
|
||||
)
|
||||
def scanRight[B, That](z: B)(op: (A, B) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
var scanned = List(z)
|
||||
var acc = z
|
||||
for (x <- reversed) {
|
||||
acc = op(x, acc)
|
||||
scanned ::= acc
|
||||
}
|
||||
val b = bf(repr)
|
||||
for (elem <- scanned) b += elem
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Selects the first element of this $coll.
|
||||
* $orderDependent
|
||||
* @return the first element of this $coll.
|
||||
* @throws `NoSuchElementException` if the $coll is empty.
|
||||
*/
|
||||
def head: A = {
|
||||
var result: () => A = () => throw new NoSuchElementException
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
result = () => x
|
||||
break
|
||||
}
|
||||
}
|
||||
result()
|
||||
}
|
||||
|
||||
/** Optionally selects the first element.
|
||||
* $orderDependent
|
||||
* @return the first element of this $coll if it is nonempty, `None` if it is empty.
|
||||
*/
|
||||
def headOption: Option[A] = if (isEmpty) None else Some(head)
|
||||
|
||||
/** Selects all elements except the first.
|
||||
* $orderDependent
|
||||
* @return a $coll consisting of all elements of this $coll
|
||||
* except the first one.
|
||||
* @throws `UnsupportedOperationException` if the $coll is empty.
|
||||
*/
|
||||
override def tail: Repr = {
|
||||
if (isEmpty) throw new UnsupportedOperationException("empty.tail")
|
||||
drop(1)
|
||||
}
|
||||
|
||||
/** Selects the last element.
|
||||
* $orderDependent
|
||||
* @return The last element of this $coll.
|
||||
* @throws NoSuchElementException If the $coll is empty.
|
||||
*/
|
||||
def last: A = {
|
||||
var lst = head
|
||||
for (x <- this)
|
||||
lst = x
|
||||
lst
|
||||
}
|
||||
|
||||
/** Optionally selects the last element.
|
||||
* $orderDependent
|
||||
* @return the last element of this $coll$ if it is nonempty, `None` if it is empty.
|
||||
*/
|
||||
def lastOption: Option[A] = if (isEmpty) None else Some(last)
|
||||
|
||||
/** Selects all elements except the last.
|
||||
* $orderDependent
|
||||
* @return a $coll consisting of all elements of this $coll
|
||||
* except the last one.
|
||||
* @throws `UnsupportedOperationException` if the $coll is empty.
|
||||
*/
|
||||
def init: Repr = {
|
||||
if (isEmpty) throw new UnsupportedOperationException("empty.init")
|
||||
var lst = head
|
||||
var follow = false
|
||||
val b = newBuilder
|
||||
b.sizeHint(this, -1)
|
||||
for (x <- this.seq) {
|
||||
if (follow) b += lst
|
||||
else follow = true
|
||||
lst = x
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def take(n: Int): Repr = slice(0, n)
|
||||
|
||||
def drop(n: Int): Repr =
|
||||
if (n <= 0) {
|
||||
val b = newBuilder
|
||||
b.sizeHint(this)
|
||||
b ++= thisCollection result
|
||||
}
|
||||
else sliceWithKnownDelta(n, Int.MaxValue, -n)
|
||||
|
||||
def slice(from: Int, until: Int): Repr = sliceWithKnownBound(math.max(from, 0), until)
|
||||
|
||||
// Precondition: from >= 0, until > 0, builder already configured for building.
|
||||
private[this] def sliceInternal(from: Int, until: Int, b: Builder[A, Repr]): Repr = {
|
||||
var i = 0
|
||||
breakable {
|
||||
for (x <- this.seq) {
|
||||
if (i >= from) b += x
|
||||
i += 1
|
||||
if (i >= until) break
|
||||
}
|
||||
}
|
||||
b.result
|
||||
}
|
||||
// Precondition: from >= 0
|
||||
private[scala] def sliceWithKnownDelta(from: Int, until: Int, delta: Int): Repr = {
|
||||
val b = newBuilder
|
||||
if (until <= from) b.result
|
||||
else {
|
||||
b.sizeHint(this, delta)
|
||||
sliceInternal(from, until, b)
|
||||
}
|
||||
}
|
||||
// Precondition: from >= 0
|
||||
private[scala] def sliceWithKnownBound(from: Int, until: Int): Repr = {
|
||||
val b = newBuilder
|
||||
if (until <= from) b.result
|
||||
else {
|
||||
b.sizeHintBounded(until - from, this)
|
||||
sliceInternal(from, until, b)
|
||||
}
|
||||
}
|
||||
|
||||
def takeWhile(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
if (!p(x)) break
|
||||
b += x
|
||||
}
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def dropWhile(p: A => Boolean): Repr = {
|
||||
val b = newBuilder
|
||||
var go = false
|
||||
for (x <- this) {
|
||||
if (!p(x)) go = true
|
||||
if (go) b += x
|
||||
}
|
||||
b.result
|
||||
}
|
||||
|
||||
def span(p: A => Boolean): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
var toLeft = true
|
||||
for (x <- this) {
|
||||
toLeft = toLeft && p(x)
|
||||
(if (toLeft) l else r) += x
|
||||
}
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
def splitAt(n: Int): (Repr, Repr) = {
|
||||
val l, r = newBuilder
|
||||
l.sizeHintBounded(n, this)
|
||||
if (n >= 0) r.sizeHint(this, -n)
|
||||
var i = 0
|
||||
for (x <- this) {
|
||||
(if (i < n) l else r) += x
|
||||
i += 1
|
||||
}
|
||||
(l.result, r.result)
|
||||
}
|
||||
|
||||
/** Iterates over the tails of this $coll. The first value will be this
|
||||
* $coll and the final one will be an empty $coll, with the intervening
|
||||
* values the results of successive applications of `tail`.
|
||||
*
|
||||
* @return an iterator over all the tails of this $coll
|
||||
* @example `List(1,2,3).tails = Iterator(List(1,2,3), List(2,3), List(3), Nil)`
|
||||
*/
|
||||
def tails: Iterator[Repr] = iterateUntilEmpty(_.tail)
|
||||
|
||||
/** Iterates over the inits of this $coll. The first value will be this
|
||||
* $coll and the final one will be an empty $coll, with the intervening
|
||||
* values the results of successive applications of `init`.
|
||||
*
|
||||
* @return an iterator over all the inits of this $coll
|
||||
* @example `List(1,2,3).inits = Iterator(List(1,2,3), List(1,2), List(1), Nil)`
|
||||
*/
|
||||
def inits: Iterator[Repr] = iterateUntilEmpty(_.init)
|
||||
|
||||
/** Copies elements of this $coll to an array.
|
||||
* Fills the given array `xs` with at most `len` elements of
|
||||
* this $coll, starting at position `start`.
|
||||
* Copying will stop once either the end of the current $coll is reached,
|
||||
* or the end of the array is reached, or `len` elements have been copied.
|
||||
*
|
||||
* $willNotTerminateInf
|
||||
*
|
||||
* @param xs the array to fill.
|
||||
* @param start the starting index.
|
||||
* @param len the maximal number of elements to copy.
|
||||
* @tparam B the type of the elements of the array.
|
||||
*
|
||||
*
|
||||
* @usecase def copyToArray(xs: Array[A], start: Int, len: Int): Unit
|
||||
*/
|
||||
def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) {
|
||||
var i = start
|
||||
val end = (start + len) min xs.length
|
||||
breakable {
|
||||
for (x <- this) {
|
||||
if (i >= end) break
|
||||
xs(i) = x
|
||||
i += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def toTraversable: Traversable[A] = thisCollection
|
||||
def toIterator: Iterator[A] = toStream.iterator
|
||||
def toStream: Stream[A] = toBuffer.toStream
|
||||
|
||||
/** Converts this $coll to a string.
|
||||
*
|
||||
* @return a string representation of this collection. By default this
|
||||
* string consists of the `stringPrefix` of this $coll,
|
||||
* followed by all elements separated by commas and enclosed in parentheses.
|
||||
*/
|
||||
override def toString = mkString(stringPrefix + "(", ", ", ")")
|
||||
|
||||
/** Defines the prefix of this object's `toString` representation.
|
||||
*
|
||||
* @return a string representation which starts the result of `toString`
|
||||
* applied to this $coll. By default the string prefix is the
|
||||
* simple name of the collection class $coll.
|
||||
*/
|
||||
def stringPrefix : String = {
|
||||
var string = repr.asInstanceOf[AnyRef].getClass.getName
|
||||
val idx1 = string.lastIndexOf('.' : Int)
|
||||
if (idx1 != -1) string = string.substring(idx1 + 1)
|
||||
val idx2 = string.indexOf('$')
|
||||
if (idx2 != -1) string = string.substring(0, idx2)
|
||||
string
|
||||
}
|
||||
|
||||
/** Creates a non-strict view of this $coll.
|
||||
*
|
||||
* @return a non-strict view of this $coll.
|
||||
*/
|
||||
def view = new TraversableView[A, Repr] {
|
||||
protected lazy val underlying = self.repr
|
||||
override def foreach[U](f: A => U) = self foreach f
|
||||
}
|
||||
|
||||
/** Creates a non-strict view of a slice of this $coll.
|
||||
*
|
||||
* Note: the difference between `view` and `slice` is that `view` produces
|
||||
* a view of the current $coll, whereas `slice` produces a new $coll.
|
||||
*
|
||||
* Note: `view(from, to)` is equivalent to `view.slice(from, to)`
|
||||
* $orderDependent
|
||||
*
|
||||
* @param from the index of the first element of the view
|
||||
* @param until the index of the element following the view
|
||||
* @return a non-strict view of a slice of this $coll, starting at index `from`
|
||||
* and extending up to (but not including) index `until`.
|
||||
*/
|
||||
def view(from: Int, until: Int): TraversableView[A, Repr] = view.slice(from, until)
|
||||
|
||||
/** Creates a non-strict filter of this $coll.
|
||||
*
|
||||
* Note: the difference between `c filter p` and `c withFilter p` is that
|
||||
* the former creates a new collection, whereas the latter only
|
||||
* restricts the domain of subsequent `map`, `flatMap`, `foreach`,
|
||||
* and `withFilter` operations.
|
||||
* $orderDependent
|
||||
*
|
||||
* @param p the predicate used to test elements.
|
||||
* @return an object of class `WithFilter`, which supports
|
||||
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
|
||||
* All these operations apply to those elements of this $coll which
|
||||
* satisfy the predicate `p`.
|
||||
*/
|
||||
def withFilter(p: A => Boolean): FilterMonadic[A, Repr] = new WithFilter(p)
|
||||
|
||||
/** A class supporting filtered operations. Instances of this class are
|
||||
* returned by method `withFilter`.
|
||||
*/
|
||||
class WithFilter(p: A => Boolean) extends FilterMonadic[A, Repr] {
|
||||
|
||||
/** Builds a new collection by applying a function to all elements of the
|
||||
* outer $coll containing this `WithFilter` instance that satisfy predicate `p`.
|
||||
*
|
||||
* @param f the function to apply to each element.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying
|
||||
* the given function `f` to each element of the outer $coll
|
||||
* that satisfies predicate `p` and collecting the results.
|
||||
*
|
||||
* @usecase def map[B](f: A => B): $Coll[B]
|
||||
*
|
||||
* @return a new $coll resulting from applying the given function
|
||||
* `f` to each element of the outer $coll that satisfies
|
||||
* predicate `p` and collecting the results.
|
||||
*/
|
||||
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- self)
|
||||
if (p(x)) b += f(x)
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Builds a new collection by applying a function to all elements of the
|
||||
* outer $coll containing this `WithFilter` instance that satisfy
|
||||
* predicate `p` and concatenating the results.
|
||||
*
|
||||
* @param f the function to apply to each element.
|
||||
* @tparam B the element type of the returned collection.
|
||||
* @tparam That $thatinfo
|
||||
* @param bf $bfinfo
|
||||
* @return a new collection of type `That` resulting from applying
|
||||
* the given collection-valued function `f` to each element
|
||||
* of the outer $coll that satisfies predicate `p` and
|
||||
* concatenating the results.
|
||||
*
|
||||
* @usecase def flatMap[B](f: A => TraversableOnce[B]): $Coll[B]
|
||||
*
|
||||
* @return a new $coll resulting from applying the given collection-valued function
|
||||
* `f` to each element of the outer $coll that satisfies predicate `p` and concatenating the results.
|
||||
*/
|
||||
def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
|
||||
val b = bf(repr)
|
||||
for (x <- self)
|
||||
if (p(x)) b ++= f(x).seq
|
||||
b.result
|
||||
}
|
||||
|
||||
/** Applies a function `f` to all elements of the outer $coll containing
|
||||
* this `WithFilter` instance that satisfy predicate `p`.
|
||||
*
|
||||
* @param f the function that is applied for its side-effect to every element.
|
||||
* The result of function `f` is discarded.
|
||||
*
|
||||
* @tparam U the type parameter describing the result of function `f`.
|
||||
* This result will always be ignored. Typically `U` is `Unit`,
|
||||
* but this is not necessary.
|
||||
*
|
||||
* @usecase def foreach(f: A => Unit): Unit
|
||||
*/
|
||||
def foreach[U](f: A => U): Unit =
|
||||
for (x <- self)
|
||||
if (p(x)) f(x)
|
||||
|
||||
/** Further refines the filter for this $coll.
|
||||
*
|
||||
* @param q the predicate used to test elements.
|
||||
* @return an object of class `WithFilter`, which supports
|
||||
* `map`, `flatMap`, `foreach`, and `withFilter` operations.
|
||||
* All these operations apply to those elements of this $coll which
|
||||
* satisfy the predicate `q` in addition to the predicate `p`.
|
||||
*/
|
||||
def withFilter(q: A => Boolean): WithFilter =
|
||||
new WithFilter(x => p(x) && q(x))
|
||||
}
|
||||
|
||||
// A helper for tails and inits.
|
||||
private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
|
||||
val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
|
||||
it ++ Iterator(Nil) map (newBuilder ++= _ result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</textarea>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
theme: "ambiance",
|
||||
mode: "text/x-scala"
|
||||
});
|
||||
</script>
|
||||
</article>
|
||||
55
public/plugins/codemirror-5.17.0/mode/clike/test.js
Normal file
55
public/plugins/codemirror-5.17.0/mode/clike/test.js
Normal file
@@ -0,0 +1,55 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-c");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MT("indent",
|
||||
"[variable-3 void] [def foo]([variable-3 void*] [variable a], [variable-3 int] [variable b]) {",
|
||||
" [variable-3 int] [variable c] [operator =] [variable b] [operator +]",
|
||||
" [number 1];",
|
||||
" [keyword return] [operator *][variable a];",
|
||||
"}");
|
||||
|
||||
MT("indent_switch",
|
||||
"[keyword switch] ([variable x]) {",
|
||||
" [keyword case] [number 10]:",
|
||||
" [keyword return] [number 20];",
|
||||
" [keyword default]:",
|
||||
" [variable printf]([string \"foo %c\"], [variable x]);",
|
||||
"}");
|
||||
|
||||
MT("def",
|
||||
"[variable-3 void] [def foo]() {}",
|
||||
"[keyword struct] [def bar]{}",
|
||||
"[variable-3 int] [variable-3 *][def baz]() {}");
|
||||
|
||||
MT("def_new_line",
|
||||
"::[variable std]::[variable SomeTerribleType][operator <][variable T][operator >]",
|
||||
"[def SomeLongMethodNameThatDoesntFitIntoOneLine]([keyword const] [variable MyType][operator &] [variable param]) {}")
|
||||
|
||||
MT("double_block",
|
||||
"[keyword for] (;;)",
|
||||
" [keyword for] (;;)",
|
||||
" [variable x][operator ++];",
|
||||
"[keyword return];");
|
||||
|
||||
MT("preprocessor",
|
||||
"[meta #define FOO 3]",
|
||||
"[variable-3 int] [variable foo];",
|
||||
"[meta #define BAR\\]",
|
||||
"[meta 4]",
|
||||
"[variable-3 unsigned] [variable-3 int] [variable bar] [operator =] [number 8];",
|
||||
"[meta #include <baz> ][comment // comment]")
|
||||
|
||||
|
||||
var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src");
|
||||
function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MTCPP("cpp14_literal",
|
||||
"[number 10'000];",
|
||||
"[number 0b10'000];",
|
||||
"[number 0x10'000];",
|
||||
"[string '100000'];");
|
||||
})();
|
||||
306
public/plugins/codemirror-5.17.0/mode/clojure/clojure.js
Normal file
306
public/plugins/codemirror-5.17.0/mode/clojure/clojure.js
Normal file
@@ -0,0 +1,306 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Author: Hans Engel
|
||||
* Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun)
|
||||
*/
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("clojure", function (options) {
|
||||
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2",
|
||||
ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable";
|
||||
var INDENT_WORD_SKIP = options.indentUnit || 2;
|
||||
var NORMAL_INDENT_UNIT = options.indentUnit || 2;
|
||||
|
||||
function makeKeywords(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
|
||||
var atoms = makeKeywords("true false nil");
|
||||
|
||||
var keywords = makeKeywords(
|
||||
"defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest " +
|
||||
"slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn " +
|
||||
"do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync " +
|
||||
"doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars " +
|
||||
"binding gen-class gen-and-load-class gen-and-save-class handler-case handle");
|
||||
|
||||
var builtins = makeKeywords(
|
||||
"* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* " +
|
||||
"*compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* " +
|
||||
"*math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* " +
|
||||
"*source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> " +
|
||||
"->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor " +
|
||||
"aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! " +
|
||||
"alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double " +
|
||||
"aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 " +
|
||||
"bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set " +
|
||||
"bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast " +
|
||||
"byte byte-array bytes case cat cast char char-array char-escape-string char-name-string char? chars chunk chunk-append " +
|
||||
"chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors " +
|
||||
"clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement completing concat cond condp " +
|
||||
"conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? " +
|
||||
"declare dedupe default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol " +
|
||||
"defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc " +
|
||||
"dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last " +
|
||||
"drop-while eduction empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info " +
|
||||
"extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword " +
|
||||
"find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? " +
|
||||
"fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? " +
|
||||
"gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash " +
|
||||
"hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? " +
|
||||
"int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep " +
|
||||
"keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file " +
|
||||
"load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array " +
|
||||
"make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods " +
|
||||
"min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty " +
|
||||
"not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias " +
|
||||
"ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all " +
|
||||
"partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers " +
|
||||
"primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str " +
|
||||
"prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues " +
|
||||
"quot rand rand-int rand-nth random-sample range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern " +
|
||||
"re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history " +
|
||||
"ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods " +
|
||||
"remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest " +
|
||||
"restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? " +
|
||||
"seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts " +
|
||||
"shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? " +
|
||||
"special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol " +
|
||||
"symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transduce " +
|
||||
"transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec " +
|
||||
"unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int " +
|
||||
"unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int "+
|
||||
"unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote " +
|
||||
"unquote-splicing update update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of " +
|
||||
"vector? volatile! volatile? vreset! vswap! when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context " +
|
||||
"with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap " +
|
||||
"*default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! " +
|
||||
"set-agent-send-off-executor! some-> some->>");
|
||||
|
||||
var indentKeys = makeKeywords(
|
||||
// Built-ins
|
||||
"ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto " +
|
||||
"locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type " +
|
||||
"try catch " +
|
||||
|
||||
// Binding forms
|
||||
"let letfn binding loop for doseq dotimes when-let if-let " +
|
||||
|
||||
// Data structures
|
||||
"defstruct struct-map assoc " +
|
||||
|
||||
// clojure.test
|
||||
"testing deftest " +
|
||||
|
||||
// contrib
|
||||
"handler-case handle dotrace deftrace");
|
||||
|
||||
var tests = {
|
||||
digit: /\d/,
|
||||
digit_or_colon: /[\d:]/,
|
||||
hex: /[0-9a-f]/i,
|
||||
sign: /[+-]/,
|
||||
exponent: /e/i,
|
||||
keyword_char: /[^\s\(\[\;\)\]]/,
|
||||
symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/,
|
||||
block_indent: /^(?:def|with)[^\/]+$|\/(?:def|with)/
|
||||
};
|
||||
|
||||
function stateStack(indent, type, prev) { // represents a state stack object
|
||||
this.indent = indent;
|
||||
this.type = type;
|
||||
this.prev = prev;
|
||||
}
|
||||
|
||||
function pushStack(state, indent, type) {
|
||||
state.indentStack = new stateStack(indent, type, state.indentStack);
|
||||
}
|
||||
|
||||
function popStack(state) {
|
||||
state.indentStack = state.indentStack.prev;
|
||||
}
|
||||
|
||||
function isNumber(ch, stream){
|
||||
// hex
|
||||
if ( ch === '0' && stream.eat(/x/i) ) {
|
||||
stream.eatWhile(tests.hex);
|
||||
return true;
|
||||
}
|
||||
|
||||
// leading sign
|
||||
if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
|
||||
stream.eat(tests.sign);
|
||||
ch = stream.next();
|
||||
}
|
||||
|
||||
if ( tests.digit.test(ch) ) {
|
||||
stream.eat(ch);
|
||||
stream.eatWhile(tests.digit);
|
||||
|
||||
if ( '.' == stream.peek() ) {
|
||||
stream.eat('.');
|
||||
stream.eatWhile(tests.digit);
|
||||
} else if ('/' == stream.peek() ) {
|
||||
stream.eat('/');
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
|
||||
if ( stream.eat(tests.exponent) ) {
|
||||
stream.eat(tests.sign);
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Eat character that starts after backslash \
|
||||
function eatCharacter(stream) {
|
||||
var first = stream.next();
|
||||
// Read special literals: backspace, newline, space, return.
|
||||
// Just read all lowercase letters.
|
||||
if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) {
|
||||
return;
|
||||
}
|
||||
// Read unicode character: \u1000 \uA0a1
|
||||
if (first === "u") {
|
||||
stream.match(/[0-9a-z]{4}/i, true);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
indentStack: null,
|
||||
indentation: 0,
|
||||
mode: false
|
||||
};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
if (state.indentStack == null && stream.sol()) {
|
||||
// update indentation, but only if indentStack is empty
|
||||
state.indentation = stream.indentation();
|
||||
}
|
||||
|
||||
// skip spaces
|
||||
if (state.mode != "string" && stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
var returnType = null;
|
||||
|
||||
switch(state.mode){
|
||||
case "string": // multi-line string parsing mode
|
||||
var next, escaped = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == "\"" && !escaped) {
|
||||
|
||||
state.mode = false;
|
||||
break;
|
||||
}
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
returnType = STRING; // continue on in string mode
|
||||
break;
|
||||
default: // default parsing mode
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch == "\"") {
|
||||
state.mode = "string";
|
||||
returnType = STRING;
|
||||
} else if (ch == "\\") {
|
||||
eatCharacter(stream);
|
||||
returnType = CHARACTER;
|
||||
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
|
||||
returnType = ATOM;
|
||||
} else if (ch == ";") { // comment
|
||||
stream.skipToEnd(); // rest of the line is a comment
|
||||
returnType = COMMENT;
|
||||
} else if (isNumber(ch,stream)){
|
||||
returnType = NUMBER;
|
||||
} else if (ch == "(" || ch == "[" || ch == "{" ) {
|
||||
var keyWord = '', indentTemp = stream.column(), letter;
|
||||
/**
|
||||
Either
|
||||
(indent-word ..
|
||||
(non-indent-word ..
|
||||
(;something else, bracket, etc.
|
||||
*/
|
||||
|
||||
if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) {
|
||||
keyWord += letter;
|
||||
}
|
||||
|
||||
if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) ||
|
||||
tests.block_indent.test(keyWord))) { // indent-word
|
||||
pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
|
||||
} else { // non-indent word
|
||||
// we continue eating the spaces
|
||||
stream.eatSpace();
|
||||
if (stream.eol() || stream.peek() == ";") {
|
||||
// nothing significant after
|
||||
// we restart indentation the user defined spaces after
|
||||
pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch);
|
||||
} else {
|
||||
pushStack(state, indentTemp + stream.current().length, ch); // else we match
|
||||
}
|
||||
}
|
||||
stream.backUp(stream.current().length - 1); // undo all the eating
|
||||
|
||||
returnType = BRACKET;
|
||||
} else if (ch == ")" || ch == "]" || ch == "}") {
|
||||
returnType = BRACKET;
|
||||
if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) {
|
||||
popStack(state);
|
||||
}
|
||||
} else if ( ch == ":" ) {
|
||||
stream.eatWhile(tests.symbol);
|
||||
return ATOM;
|
||||
} else {
|
||||
stream.eatWhile(tests.symbol);
|
||||
|
||||
if (keywords && keywords.propertyIsEnumerable(stream.current())) {
|
||||
returnType = KEYWORD;
|
||||
} else if (builtins && builtins.propertyIsEnumerable(stream.current())) {
|
||||
returnType = BUILTIN;
|
||||
} else if (atoms && atoms.propertyIsEnumerable(stream.current())) {
|
||||
returnType = ATOM;
|
||||
} else {
|
||||
returnType = VAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnType;
|
||||
},
|
||||
|
||||
indent: function (state) {
|
||||
if (state.indentStack == null) return state.indentation;
|
||||
return state.indentStack.indent;
|
||||
},
|
||||
|
||||
closeBrackets: {pairs: "()[]{}\"\""},
|
||||
lineComment: ";;"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-clojure", "clojure");
|
||||
CodeMirror.defineMIME("text/x-clojurescript", "clojure");
|
||||
CodeMirror.defineMIME("application/edn", "clojure");
|
||||
|
||||
});
|
||||
91
public/plugins/codemirror-5.17.0/mode/clojure/index.html
Normal file
91
public/plugins/codemirror-5.17.0/mode/clojure/index.html
Normal file
@@ -0,0 +1,91 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Clojure mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="clojure.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Clojure</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Clojure mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
; Conway's Game of Life, based on the work of:
|
||||
;; Laurent Petit https://gist.github.com/1200343
|
||||
;; Christophe Grand http://clj-me.cgrand.net/2011/08/19/conways-game-of-life
|
||||
|
||||
(ns ^{:doc "Conway's Game of Life."}
|
||||
game-of-life)
|
||||
|
||||
;; Core game of life's algorithm functions
|
||||
|
||||
(defn neighbours
|
||||
"Given a cell's coordinates, returns the coordinates of its neighbours."
|
||||
[[x y]]
|
||||
(for [dx [-1 0 1] dy (if (zero? dx) [-1 1] [-1 0 1])]
|
||||
[(+ dx x) (+ dy y)]))
|
||||
|
||||
(defn step
|
||||
"Given a set of living cells, computes the new set of living cells."
|
||||
[cells]
|
||||
(set (for [[cell n] (frequencies (mapcat neighbours cells))
|
||||
:when (or (= n 3) (and (= n 2) (cells cell)))]
|
||||
cell)))
|
||||
|
||||
;; Utility methods for displaying game on a text terminal
|
||||
|
||||
(defn print-board
|
||||
"Prints a board on *out*, representing a step in the game."
|
||||
[board w h]
|
||||
(doseq [x (range (inc w)) y (range (inc h))]
|
||||
(if (= y 0) (print "\n"))
|
||||
(print (if (board [x y]) "[X]" " . "))))
|
||||
|
||||
(defn display-grids
|
||||
"Prints a squence of boards on *out*, representing several steps."
|
||||
[grids w h]
|
||||
(doseq [board grids]
|
||||
(print-board board w h)
|
||||
(print "\n")))
|
||||
|
||||
;; Launches an example board
|
||||
|
||||
(def
|
||||
^{:doc "board represents the initial set of living cells"}
|
||||
board #{[2 1] [2 2] [2 3]})
|
||||
|
||||
(display-grids (take 3 (iterate step board)) 5 5)
|
||||
|
||||
;; Let's play with characters
|
||||
(println \1 \a \# \\
|
||||
\" \( \newline
|
||||
\} \" \space
|
||||
\tab \return \backspace
|
||||
\u1000 \uAaAa \u9F9F)
|
||||
|
||||
;; Let's play with numbers
|
||||
(+ 1 -1 1/2 -1/2 -0.5 0.5)
|
||||
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-clojure</code>.</p>
|
||||
|
||||
</article>
|
||||
97
public/plugins/codemirror-5.17.0/mode/cmake/cmake.js
Normal file
97
public/plugins/codemirror-5.17.0/mode/cmake/cmake.js
Normal file
@@ -0,0 +1,97 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object")
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd)
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("cmake", function () {
|
||||
var variable_regex = /({)?[a-zA-Z0-9_]+(})?/;
|
||||
|
||||
function tokenString(stream, state) {
|
||||
var current, prev, found_var = false;
|
||||
while (!stream.eol() && (current = stream.next()) != state.pending) {
|
||||
if (current === '$' && prev != '\\' && state.pending == '"') {
|
||||
found_var = true;
|
||||
break;
|
||||
}
|
||||
prev = current;
|
||||
}
|
||||
if (found_var) {
|
||||
stream.backUp(1);
|
||||
}
|
||||
if (current == state.pending) {
|
||||
state.continueString = false;
|
||||
} else {
|
||||
state.continueString = true;
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function tokenize(stream, state) {
|
||||
var ch = stream.next();
|
||||
|
||||
// Have we found a variable?
|
||||
if (ch === '$') {
|
||||
if (stream.match(variable_regex)) {
|
||||
return 'variable-2';
|
||||
}
|
||||
return 'variable';
|
||||
}
|
||||
// Should we still be looking for the end of a string?
|
||||
if (state.continueString) {
|
||||
// If so, go through the loop again
|
||||
stream.backUp(1);
|
||||
return tokenString(stream, state);
|
||||
}
|
||||
// Do we just have a function on our hands?
|
||||
// In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched
|
||||
if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) {
|
||||
stream.backUp(1);
|
||||
return 'def';
|
||||
}
|
||||
if (ch == "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
// Have we found a string?
|
||||
if (ch == "'" || ch == '"') {
|
||||
// Store the type (single or double)
|
||||
state.pending = ch;
|
||||
// Perform the looping function to find the end
|
||||
return tokenString(stream, state);
|
||||
}
|
||||
if (ch == '(' || ch == ')') {
|
||||
return 'bracket';
|
||||
}
|
||||
if (ch.match(/[0-9]/)) {
|
||||
return 'number';
|
||||
}
|
||||
stream.eatWhile(/[\w-]/);
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
startState: function () {
|
||||
var state = {};
|
||||
state.inDefinition = false;
|
||||
state.inInclude = false;
|
||||
state.continueString = false;
|
||||
state.pending = false;
|
||||
return state;
|
||||
},
|
||||
token: function (stream, state) {
|
||||
if (stream.eatSpace()) return null;
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-cmake", "cmake");
|
||||
|
||||
});
|
||||
129
public/plugins/codemirror-5.17.0/mode/cmake/index.html
Normal file
129
public/plugins/codemirror-5.17.0/mode/cmake/index.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CMake mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="cmake.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CMake</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CMake mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# vim: syntax=cmake
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
# default to Release build for GCC builds
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||
"Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
endif()
|
||||
message(STATUS "cmake version ${CMAKE_VERSION}")
|
||||
if(POLICY CMP0025)
|
||||
cmake_policy(SET CMP0025 OLD) # report Apple's Clang as just Clang
|
||||
endif()
|
||||
if(POLICY CMP0042)
|
||||
cmake_policy(SET CMP0042 NEW) # MACOSX_RPATH
|
||||
endif()
|
||||
|
||||
project (x265)
|
||||
cmake_minimum_required (VERSION 2.8.8) # OBJECT libraries require 2.8.8
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckSymbolExists)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
# X265_BUILD must be incremented each time the public API is changed
|
||||
set(X265_BUILD 48)
|
||||
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
|
||||
"${PROJECT_BINARY_DIR}/x265.def")
|
||||
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
|
||||
"${PROJECT_BINARY_DIR}/x265_config.h")
|
||||
|
||||
SET(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" "${CMAKE_MODULE_PATH}")
|
||||
|
||||
# System architecture detection
|
||||
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSPROC)
|
||||
set(X86_ALIASES x86 i386 i686 x86_64 amd64)
|
||||
list(FIND X86_ALIASES "${SYSPROC}" X86MATCH)
|
||||
if("${SYSPROC}" STREQUAL "" OR X86MATCH GREATER "-1")
|
||||
message(STATUS "Detected x86 target processor")
|
||||
set(X86 1)
|
||||
add_definitions(-DX265_ARCH_X86=1)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" MATCHES 8)
|
||||
set(X64 1)
|
||||
add_definitions(-DX86_64=1)
|
||||
endif()
|
||||
elseif(${SYSPROC} STREQUAL "armv6l")
|
||||
message(STATUS "Detected ARM target processor")
|
||||
set(ARM 1)
|
||||
add_definitions(-DX265_ARCH_ARM=1 -DHAVE_ARMV6=1)
|
||||
else()
|
||||
message(STATUS "CMAKE_SYSTEM_PROCESSOR value `${CMAKE_SYSTEM_PROCESSOR}` is unknown")
|
||||
message(STATUS "Please add this value near ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}")
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
list(APPEND PLATFORM_LIBS pthread)
|
||||
find_library(LIBRT rt)
|
||||
if(LIBRT)
|
||||
list(APPEND PLATFORM_LIBS rt)
|
||||
endif()
|
||||
find_package(Numa)
|
||||
if(NUMA_FOUND)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${NUMA_LIBRARY})
|
||||
check_symbol_exists(numa_node_of_cpu numa.h NUMA_V2)
|
||||
if(NUMA_V2)
|
||||
add_definitions(-DHAVE_LIBNUMA)
|
||||
message(STATUS "libnuma found, building with support for NUMA nodes")
|
||||
list(APPEND PLATFORM_LIBS ${NUMA_LIBRARY})
|
||||
link_directories(${NUMA_LIBRARY_DIR})
|
||||
include_directories(${NUMA_INCLUDE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
mark_as_advanced(LIBRT NUMA_FOUND)
|
||||
endif(UNIX)
|
||||
|
||||
if(X64 AND NOT WIN32)
|
||||
option(ENABLE_PIC "Enable Position Independent Code" ON)
|
||||
else()
|
||||
option(ENABLE_PIC "Enable Position Independent Code" OFF)
|
||||
endif(X64 AND NOT WIN32)
|
||||
|
||||
# Compiler detection
|
||||
if(CMAKE_GENERATOR STREQUAL "Xcode")
|
||||
set(XCODE 1)
|
||||
endif()
|
||||
if (APPLE)
|
||||
add_definitions(-DMACOS)
|
||||
endif()
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-cmake",
|
||||
matchBrackets: true,
|
||||
indentUnit: 4
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-cmake</code>.</p>
|
||||
|
||||
</article>
|
||||
255
public/plugins/codemirror-5.17.0/mode/cobol/cobol.js
Normal file
255
public/plugins/codemirror-5.17.0/mode/cobol/cobol.js
Normal file
@@ -0,0 +1,255 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Author: Gautam Mehta
|
||||
* Branched from CodeMirror's Scheme mode
|
||||
*/
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("cobol", function () {
|
||||
var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
|
||||
ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header",
|
||||
COBOLLINENUM = "def", PERIOD = "link";
|
||||
function makeKeywords(str) {
|
||||
var obj = {}, words = str.split(" ");
|
||||
for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
|
||||
return obj;
|
||||
}
|
||||
var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES ");
|
||||
var keywords = makeKeywords(
|
||||
"ACCEPT ACCESS ACQUIRE ADD ADDRESS " +
|
||||
"ADVANCING AFTER ALIAS ALL ALPHABET " +
|
||||
"ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " +
|
||||
"ALSO ALTER ALTERNATE AND ANY " +
|
||||
"ARE AREA AREAS ARITHMETIC ASCENDING " +
|
||||
"ASSIGN AT ATTRIBUTE AUTHOR AUTO " +
|
||||
"AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " +
|
||||
"B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " +
|
||||
"BEFORE BELL BINARY BIT BITS " +
|
||||
"BLANK BLINK BLOCK BOOLEAN BOTTOM " +
|
||||
"BY CALL CANCEL CD CF " +
|
||||
"CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " +
|
||||
"CLOSE COBOL CODE CODE-SET COL " +
|
||||
"COLLATING COLUMN COMMA COMMIT COMMITMENT " +
|
||||
"COMMON COMMUNICATION COMP COMP-0 COMP-1 " +
|
||||
"COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " +
|
||||
"COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " +
|
||||
"COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " +
|
||||
"COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " +
|
||||
"CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " +
|
||||
"CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " +
|
||||
"CONVERTING COPY CORR CORRESPONDING COUNT " +
|
||||
"CRT CRT-UNDER CURRENCY CURRENT CURSOR " +
|
||||
"DATA DATE DATE-COMPILED DATE-WRITTEN DAY " +
|
||||
"DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " +
|
||||
"DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " +
|
||||
"DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " +
|
||||
"DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " +
|
||||
"DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " +
|
||||
"DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " +
|
||||
"DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " +
|
||||
"DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " +
|
||||
"DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " +
|
||||
"DOWN DROP DUPLICATE DUPLICATES DYNAMIC " +
|
||||
"EBCDIC EGI EJECT ELSE EMI " +
|
||||
"EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " +
|
||||
"END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " +
|
||||
"END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " +
|
||||
"END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " +
|
||||
"END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " +
|
||||
"END-UNSTRING END-WRITE END-XML ENTER ENTRY " +
|
||||
"ENVIRONMENT EOP EQUAL EQUALS ERASE " +
|
||||
"ERROR ESI EVALUATE EVERY EXCEEDS " +
|
||||
"EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " +
|
||||
"EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " +
|
||||
"FILE-STREAM FILES FILLER FINAL FIND " +
|
||||
"FINISH FIRST FOOTING FOR FOREGROUND-COLOR " +
|
||||
"FOREGROUND-COLOUR FORMAT FREE FROM FULL " +
|
||||
"FUNCTION GENERATE GET GIVING GLOBAL " +
|
||||
"GO GOBACK GREATER GROUP HEADING " +
|
||||
"HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " +
|
||||
"ID IDENTIFICATION IF IN INDEX " +
|
||||
"INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " +
|
||||
"INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " +
|
||||
"INDIC INDICATE INDICATOR INDICATORS INITIAL " +
|
||||
"INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " +
|
||||
"INSTALLATION INTO INVALID INVOKE IS " +
|
||||
"JUST JUSTIFIED KANJI KEEP KEY " +
|
||||
"LABEL LAST LD LEADING LEFT " +
|
||||
"LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " +
|
||||
"LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " +
|
||||
"LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " +
|
||||
"LOCALE LOCALLY LOCK " +
|
||||
"MEMBER MEMORY MERGE MESSAGE METACLASS " +
|
||||
"MODE MODIFIED MODIFY MODULES MOVE " +
|
||||
"MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " +
|
||||
"NEXT NO NO-ECHO NONE NOT " +
|
||||
"NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " +
|
||||
"NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " +
|
||||
"OF OFF OMITTED ON ONLY " +
|
||||
"OPEN OPTIONAL OR ORDER ORGANIZATION " +
|
||||
"OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " +
|
||||
"PADDING PAGE PAGE-COUNTER PARSE PERFORM " +
|
||||
"PF PH PIC PICTURE PLUS " +
|
||||
"POINTER POSITION POSITIVE PREFIX PRESENT " +
|
||||
"PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " +
|
||||
"PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " +
|
||||
"PROMPT PROTECTED PURGE QUEUE QUOTE " +
|
||||
"QUOTES RANDOM RD READ READY " +
|
||||
"REALM RECEIVE RECONNECT RECORD RECORD-NAME " +
|
||||
"RECORDS RECURSIVE REDEFINES REEL REFERENCE " +
|
||||
"REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " +
|
||||
"REMAINDER REMOVAL RENAMES REPEATED REPLACE " +
|
||||
"REPLACING REPORT REPORTING REPORTS REPOSITORY " +
|
||||
"REQUIRED RERUN RESERVE RESET RETAINING " +
|
||||
"RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " +
|
||||
"REVERSED REWIND REWRITE RF RH " +
|
||||
"RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " +
|
||||
"RUN SAME SCREEN SD SEARCH " +
|
||||
"SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " +
|
||||
"SELECT SEND SENTENCE SEPARATE SEQUENCE " +
|
||||
"SEQUENTIAL SET SHARED SIGN SIZE " +
|
||||
"SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " +
|
||||
"SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " +
|
||||
"SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " +
|
||||
"START STARTING STATUS STOP STORE " +
|
||||
"STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " +
|
||||
"SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " +
|
||||
"SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " +
|
||||
"TABLE TALLYING TAPE TENANT TERMINAL " +
|
||||
"TERMINATE TEST TEXT THAN THEN " +
|
||||
"THROUGH THRU TIME TIMES TITLE " +
|
||||
"TO TOP TRAILING TRAILING-SIGN TRANSACTION " +
|
||||
"TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " +
|
||||
"UNSTRING UNTIL UP UPDATE UPON " +
|
||||
"USAGE USAGE-MODE USE USING VALID " +
|
||||
"VALIDATE VALUE VALUES VARYING VLR " +
|
||||
"WAIT WHEN WHEN-COMPILED WITH WITHIN " +
|
||||
"WORDS WORKING-STORAGE WRITE XML XML-CODE " +
|
||||
"XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " );
|
||||
|
||||
var builtins = makeKeywords("- * ** / + < <= = > >= ");
|
||||
var tests = {
|
||||
digit: /\d/,
|
||||
digit_or_colon: /[\d:]/,
|
||||
hex: /[0-9a-f]/i,
|
||||
sign: /[+-]/,
|
||||
exponent: /e/i,
|
||||
keyword_char: /[^\s\(\[\;\)\]]/,
|
||||
symbol: /[\w*+\-]/
|
||||
};
|
||||
function isNumber(ch, stream){
|
||||
// hex
|
||||
if ( ch === '0' && stream.eat(/x/i) ) {
|
||||
stream.eatWhile(tests.hex);
|
||||
return true;
|
||||
}
|
||||
// leading sign
|
||||
if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) {
|
||||
stream.eat(tests.sign);
|
||||
ch = stream.next();
|
||||
}
|
||||
if ( tests.digit.test(ch) ) {
|
||||
stream.eat(ch);
|
||||
stream.eatWhile(tests.digit);
|
||||
if ( '.' == stream.peek()) {
|
||||
stream.eat('.');
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
if ( stream.eat(tests.exponent) ) {
|
||||
stream.eat(tests.sign);
|
||||
stream.eatWhile(tests.digit);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
indentStack: null,
|
||||
indentation: 0,
|
||||
mode: false
|
||||
};
|
||||
},
|
||||
token: function (stream, state) {
|
||||
if (state.indentStack == null && stream.sol()) {
|
||||
// update indentation, but only if indentStack is empty
|
||||
state.indentation = 6 ; //stream.indentation();
|
||||
}
|
||||
// skip spaces
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
var returnType = null;
|
||||
switch(state.mode){
|
||||
case "string": // multi-line string parsing mode
|
||||
var next = false;
|
||||
while ((next = stream.next()) != null) {
|
||||
if (next == "\"" || next == "\'") {
|
||||
state.mode = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
returnType = STRING; // continue on in string mode
|
||||
break;
|
||||
default: // default parsing mode
|
||||
var ch = stream.next();
|
||||
var col = stream.column();
|
||||
if (col >= 0 && col <= 5) {
|
||||
returnType = COBOLLINENUM;
|
||||
} else if (col >= 72 && col <= 79) {
|
||||
stream.skipToEnd();
|
||||
returnType = MODTAG;
|
||||
} else if (ch == "*" && col == 6) { // comment
|
||||
stream.skipToEnd(); // rest of the line is a comment
|
||||
returnType = COMMENT;
|
||||
} else if (ch == "\"" || ch == "\'") {
|
||||
state.mode = "string";
|
||||
returnType = STRING;
|
||||
} else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) {
|
||||
returnType = ATOM;
|
||||
} else if (ch == ".") {
|
||||
returnType = PERIOD;
|
||||
} else if (isNumber(ch,stream)){
|
||||
returnType = NUMBER;
|
||||
} else {
|
||||
if (stream.current().match(tests.symbol)) {
|
||||
while (col < 71) {
|
||||
if (stream.eat(tests.symbol) === undefined) {
|
||||
break;
|
||||
} else {
|
||||
col++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = KEYWORD;
|
||||
} else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = BUILTIN;
|
||||
} else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) {
|
||||
returnType = ATOM;
|
||||
} else returnType = null;
|
||||
}
|
||||
}
|
||||
return returnType;
|
||||
},
|
||||
indent: function (state) {
|
||||
if (state.indentStack == null) return state.indentation;
|
||||
return state.indentStack.indent;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-cobol", "cobol");
|
||||
|
||||
});
|
||||
210
public/plugins/codemirror-5.17.0/mode/cobol/index.html
Normal file
210
public/plugins/codemirror-5.17.0/mode/cobol/index.html
Normal file
@@ -0,0 +1,210 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: COBOL mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<link rel="stylesheet" href="../../theme/neat.css">
|
||||
<link rel="stylesheet" href="../../theme/elegant.css">
|
||||
<link rel="stylesheet" href="../../theme/erlang-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/night.css">
|
||||
<link rel="stylesheet" href="../../theme/monokai.css">
|
||||
<link rel="stylesheet" href="../../theme/cobalt.css">
|
||||
<link rel="stylesheet" href="../../theme/eclipse.css">
|
||||
<link rel="stylesheet" href="../../theme/rubyblue.css">
|
||||
<link rel="stylesheet" href="../../theme/lesser-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/xq-dark.css">
|
||||
<link rel="stylesheet" href="../../theme/xq-light.css">
|
||||
<link rel="stylesheet" href="../../theme/ambiance.css">
|
||||
<link rel="stylesheet" href="../../theme/blackboard.css">
|
||||
<link rel="stylesheet" href="../../theme/vibrant-ink.css">
|
||||
<link rel="stylesheet" href="../../theme/solarized.css">
|
||||
<link rel="stylesheet" href="../../theme/twilight.css">
|
||||
<link rel="stylesheet" href="../../theme/midnight.css">
|
||||
<link rel="stylesheet" href="../../addon/dialog/dialog.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="cobol.js"></script>
|
||||
<script src="../../addon/selection/active-line.js"></script>
|
||||
<script src="../../addon/search/search.js"></script>
|
||||
<script src="../../addon/dialog/dialog.js"></script>
|
||||
<script src="../../addon/search/searchcursor.js"></script>
|
||||
<style>
|
||||
.CodeMirror {
|
||||
border: 1px solid #eee;
|
||||
font-size : 20px;
|
||||
height : auto !important;
|
||||
}
|
||||
.CodeMirror-activeline-background {background: #555555 !important;}
|
||||
</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">COBOL</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>COBOL mode</h2>
|
||||
|
||||
<p> Select Theme <select onchange="selectTheme()" id="selectTheme">
|
||||
<option>default</option>
|
||||
<option>ambiance</option>
|
||||
<option>blackboard</option>
|
||||
<option>cobalt</option>
|
||||
<option>eclipse</option>
|
||||
<option>elegant</option>
|
||||
<option>erlang-dark</option>
|
||||
<option>lesser-dark</option>
|
||||
<option>midnight</option>
|
||||
<option>monokai</option>
|
||||
<option>neat</option>
|
||||
<option>night</option>
|
||||
<option>rubyblue</option>
|
||||
<option>solarized dark</option>
|
||||
<option>solarized light</option>
|
||||
<option selected>twilight</option>
|
||||
<option>vibrant-ink</option>
|
||||
<option>xq-dark</option>
|
||||
<option>xq-light</option>
|
||||
</select> Select Font Size <select onchange="selectFontsize()" id="selectFontSize">
|
||||
<option value="13px">13px</option>
|
||||
<option value="14px">14px</option>
|
||||
<option value="16px">16px</option>
|
||||
<option value="18px">18px</option>
|
||||
<option value="20px" selected="selected">20px</option>
|
||||
<option value="24px">24px</option>
|
||||
<option value="26px">26px</option>
|
||||
<option value="28px">28px</option>
|
||||
<option value="30px">30px</option>
|
||||
<option value="32px">32px</option>
|
||||
<option value="34px">34px</option>
|
||||
<option value="36px">36px</option>
|
||||
</select>
|
||||
<label for="checkBoxReadOnly">Read-only</label>
|
||||
<input type="checkbox" id="checkBoxReadOnly" onchange="selectReadOnly()">
|
||||
<label for="id_tabToIndentSpace">Insert Spaces on Tab</label>
|
||||
<input type="checkbox" id="id_tabToIndentSpace" onchange="tabToIndentSpace()">
|
||||
</p>
|
||||
<textarea id="code" name="code">
|
||||
---------1---------2---------3---------4---------5---------6---------7---------8
|
||||
12345678911234567892123456789312345678941234567895123456789612345678971234567898
|
||||
000010 IDENTIFICATION DIVISION. MODTGHERE
|
||||
000020 PROGRAM-ID. SAMPLE.
|
||||
000030 AUTHOR. TEST SAM.
|
||||
000040 DATE-WRITTEN. 5 February 2013
|
||||
000041
|
||||
000042* A sample program just to show the form.
|
||||
000043* The program copies its input to the output,
|
||||
000044* and counts the number of records.
|
||||
000045* At the end this number is printed.
|
||||
000046
|
||||
000050 ENVIRONMENT DIVISION.
|
||||
000060 INPUT-OUTPUT SECTION.
|
||||
000070 FILE-CONTROL.
|
||||
000080 SELECT STUDENT-FILE ASSIGN TO SYSIN
|
||||
000090 ORGANIZATION IS LINE SEQUENTIAL.
|
||||
000100 SELECT PRINT-FILE ASSIGN TO SYSOUT
|
||||
000110 ORGANIZATION IS LINE SEQUENTIAL.
|
||||
000120
|
||||
000130 DATA DIVISION.
|
||||
000140 FILE SECTION.
|
||||
000150 FD STUDENT-FILE
|
||||
000160 RECORD CONTAINS 43 CHARACTERS
|
||||
000170 DATA RECORD IS STUDENT-IN.
|
||||
000180 01 STUDENT-IN PIC X(43).
|
||||
000190
|
||||
000200 FD PRINT-FILE
|
||||
000210 RECORD CONTAINS 80 CHARACTERS
|
||||
000220 DATA RECORD IS PRINT-LINE.
|
||||
000230 01 PRINT-LINE PIC X(80).
|
||||
000240
|
||||
000250 WORKING-STORAGE SECTION.
|
||||
000260 01 DATA-REMAINS-SWITCH PIC X(2) VALUE SPACES.
|
||||
000261 01 RECORDS-WRITTEN PIC 99.
|
||||
000270
|
||||
000280 01 DETAIL-LINE.
|
||||
000290 05 FILLER PIC X(7) VALUE SPACES.
|
||||
000300 05 RECORD-IMAGE PIC X(43).
|
||||
000310 05 FILLER PIC X(30) VALUE SPACES.
|
||||
000311
|
||||
000312 01 SUMMARY-LINE.
|
||||
000313 05 FILLER PIC X(7) VALUE SPACES.
|
||||
000314 05 TOTAL-READ PIC 99.
|
||||
000315 05 FILLER PIC X VALUE SPACE.
|
||||
000316 05 FILLER PIC X(17)
|
||||
000317 VALUE 'Records were read'.
|
||||
000318 05 FILLER PIC X(53) VALUE SPACES.
|
||||
000319
|
||||
000320 PROCEDURE DIVISION.
|
||||
000321
|
||||
000330 PREPARE-SENIOR-REPORT.
|
||||
000340 OPEN INPUT STUDENT-FILE
|
||||
000350 OUTPUT PRINT-FILE.
|
||||
000351 MOVE ZERO TO RECORDS-WRITTEN.
|
||||
000360 READ STUDENT-FILE
|
||||
000370 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
|
||||
000380 END-READ.
|
||||
000390 PERFORM PROCESS-RECORDS
|
||||
000410 UNTIL DATA-REMAINS-SWITCH = 'NO'.
|
||||
000411 PERFORM PRINT-SUMMARY.
|
||||
000420 CLOSE STUDENT-FILE
|
||||
000430 PRINT-FILE.
|
||||
000440 STOP RUN.
|
||||
000450
|
||||
000460 PROCESS-RECORDS.
|
||||
000470 MOVE STUDENT-IN TO RECORD-IMAGE.
|
||||
000480 MOVE DETAIL-LINE TO PRINT-LINE.
|
||||
000490 WRITE PRINT-LINE.
|
||||
000500 ADD 1 TO RECORDS-WRITTEN.
|
||||
000510 READ STUDENT-FILE
|
||||
000520 AT END MOVE 'NO' TO DATA-REMAINS-SWITCH
|
||||
000530 END-READ.
|
||||
000540
|
||||
000550 PRINT-SUMMARY.
|
||||
000560 MOVE RECORDS-WRITTEN TO TOTAL-READ.
|
||||
000570 MOVE SUMMARY-LINE TO PRINT-LINE.
|
||||
000571 WRITE PRINT-LINE.
|
||||
000572
|
||||
000580
|
||||
</textarea>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
lineNumbers: true,
|
||||
matchBrackets: true,
|
||||
mode: "text/x-cobol",
|
||||
theme : "twilight",
|
||||
styleActiveLine: true,
|
||||
showCursorWhenSelecting : true,
|
||||
});
|
||||
function selectTheme() {
|
||||
var themeInput = document.getElementById("selectTheme");
|
||||
var theme = themeInput.options[themeInput.selectedIndex].innerHTML;
|
||||
editor.setOption("theme", theme);
|
||||
}
|
||||
function selectFontsize() {
|
||||
var fontSizeInput = document.getElementById("selectFontSize");
|
||||
var fontSize = fontSizeInput.options[fontSizeInput.selectedIndex].innerHTML;
|
||||
editor.getWrapperElement().style.fontSize = fontSize;
|
||||
editor.refresh();
|
||||
}
|
||||
function selectReadOnly() {
|
||||
editor.setOption("readOnly", document.getElementById("checkBoxReadOnly").checked);
|
||||
}
|
||||
function tabToIndentSpace() {
|
||||
if (document.getElementById("id_tabToIndentSpace").checked) {
|
||||
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
|
||||
} else {
|
||||
editor.setOption("extraKeys", {Tab: function(cm) { cm.replaceSelection(" ", "end"); }});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</article>
|
||||
@@ -0,0 +1,355 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
/**
|
||||
* Link to the project's GitHub page:
|
||||
* https://github.com/pickhardt/coffeescript-codemirror-mode
|
||||
*/
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("coffeescript", function(conf, parserConf) {
|
||||
var ERRORCLASS = "error";
|
||||
|
||||
function wordRegexp(words) {
|
||||
return new RegExp("^((" + words.join(")|(") + "))\\b");
|
||||
}
|
||||
|
||||
var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/;
|
||||
var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/;
|
||||
var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/;
|
||||
var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/;
|
||||
|
||||
var wordOperators = wordRegexp(["and", "or", "not",
|
||||
"is", "isnt", "in",
|
||||
"instanceof", "typeof"]);
|
||||
var indentKeywords = ["for", "while", "loop", "if", "unless", "else",
|
||||
"switch", "try", "catch", "finally", "class"];
|
||||
var commonKeywords = ["break", "by", "continue", "debugger", "delete",
|
||||
"do", "in", "of", "new", "return", "then",
|
||||
"this", "@", "throw", "when", "until", "extends"];
|
||||
|
||||
var keywords = wordRegexp(indentKeywords.concat(commonKeywords));
|
||||
|
||||
indentKeywords = wordRegexp(indentKeywords);
|
||||
|
||||
|
||||
var stringPrefixes = /^('{3}|\"{3}|['\"])/;
|
||||
var regexPrefixes = /^(\/{3}|\/)/;
|
||||
var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"];
|
||||
var constants = wordRegexp(commonConstants);
|
||||
|
||||
// Tokenizers
|
||||
function tokenBase(stream, state) {
|
||||
// Handle scope changes
|
||||
if (stream.sol()) {
|
||||
if (state.scope.align === null) state.scope.align = false;
|
||||
var scopeOffset = state.scope.offset;
|
||||
if (stream.eatSpace()) {
|
||||
var lineOffset = stream.indentation();
|
||||
if (lineOffset > scopeOffset && state.scope.type == "coffee") {
|
||||
return "indent";
|
||||
} else if (lineOffset < scopeOffset) {
|
||||
return "dedent";
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
if (scopeOffset > 0) {
|
||||
dedent(stream, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var ch = stream.peek();
|
||||
|
||||
// Handle docco title comment (single line)
|
||||
if (stream.match("####")) {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Handle multi line comments
|
||||
if (stream.match("###")) {
|
||||
state.tokenize = longComment;
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
|
||||
// Single line comment
|
||||
if (ch === "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Handle number literals
|
||||
if (stream.match(/^-?[0-9\.]/, false)) {
|
||||
var floatLiteral = false;
|
||||
// Floats
|
||||
if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
if (stream.match(/^-?\d+\.\d*/)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
if (stream.match(/^-?\.\d+/)) {
|
||||
floatLiteral = true;
|
||||
}
|
||||
|
||||
if (floatLiteral) {
|
||||
// prevent from getting extra . on 1..
|
||||
if (stream.peek() == "."){
|
||||
stream.backUp(1);
|
||||
}
|
||||
return "number";
|
||||
}
|
||||
// Integers
|
||||
var intLiteral = false;
|
||||
// Hex
|
||||
if (stream.match(/^-?0x[0-9a-f]+/i)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
// Decimal
|
||||
if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
// Zero by itself with no other piece of number.
|
||||
if (stream.match(/^-?0(?![\dx])/i)) {
|
||||
intLiteral = true;
|
||||
}
|
||||
if (intLiteral) {
|
||||
return "number";
|
||||
}
|
||||
}
|
||||
|
||||
// Handle strings
|
||||
if (stream.match(stringPrefixes)) {
|
||||
state.tokenize = tokenFactory(stream.current(), false, "string");
|
||||
return state.tokenize(stream, state);
|
||||
}
|
||||
// Handle regex literals
|
||||
if (stream.match(regexPrefixes)) {
|
||||
if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division
|
||||
state.tokenize = tokenFactory(stream.current(), true, "string-2");
|
||||
return state.tokenize(stream, state);
|
||||
} else {
|
||||
stream.backUp(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Handle operators and delimiters
|
||||
if (stream.match(operators) || stream.match(wordOperators)) {
|
||||
return "operator";
|
||||
}
|
||||
if (stream.match(delimiters)) {
|
||||
return "punctuation";
|
||||
}
|
||||
|
||||
if (stream.match(constants)) {
|
||||
return "atom";
|
||||
}
|
||||
|
||||
if (stream.match(atProp) || state.prop && stream.match(identifiers)) {
|
||||
return "property";
|
||||
}
|
||||
|
||||
if (stream.match(keywords)) {
|
||||
return "keyword";
|
||||
}
|
||||
|
||||
if (stream.match(identifiers)) {
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// Handle non-detected items
|
||||
stream.next();
|
||||
return ERRORCLASS;
|
||||
}
|
||||
|
||||
function tokenFactory(delimiter, singleline, outclass) {
|
||||
return function(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
stream.eatWhile(/[^'"\/\\]/);
|
||||
if (stream.eat("\\")) {
|
||||
stream.next();
|
||||
if (singleline && stream.eol()) {
|
||||
return outclass;
|
||||
}
|
||||
} else if (stream.match(delimiter)) {
|
||||
state.tokenize = tokenBase;
|
||||
return outclass;
|
||||
} else {
|
||||
stream.eat(/['"\/]/);
|
||||
}
|
||||
}
|
||||
if (singleline) {
|
||||
if (parserConf.singleLineStringErrors) {
|
||||
outclass = ERRORCLASS;
|
||||
} else {
|
||||
state.tokenize = tokenBase;
|
||||
}
|
||||
}
|
||||
return outclass;
|
||||
};
|
||||
}
|
||||
|
||||
function longComment(stream, state) {
|
||||
while (!stream.eol()) {
|
||||
stream.eatWhile(/[^#]/);
|
||||
if (stream.match("###")) {
|
||||
state.tokenize = tokenBase;
|
||||
break;
|
||||
}
|
||||
stream.eatWhile("#");
|
||||
}
|
||||
return "comment";
|
||||
}
|
||||
|
||||
function indent(stream, state, type) {
|
||||
type = type || "coffee";
|
||||
var offset = 0, align = false, alignOffset = null;
|
||||
for (var scope = state.scope; scope; scope = scope.prev) {
|
||||
if (scope.type === "coffee" || scope.type == "}") {
|
||||
offset = scope.offset + conf.indentUnit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type !== "coffee") {
|
||||
align = null;
|
||||
alignOffset = stream.column() + stream.current().length;
|
||||
} else if (state.scope.align) {
|
||||
state.scope.align = false;
|
||||
}
|
||||
state.scope = {
|
||||
offset: offset,
|
||||
type: type,
|
||||
prev: state.scope,
|
||||
align: align,
|
||||
alignOffset: alignOffset
|
||||
};
|
||||
}
|
||||
|
||||
function dedent(stream, state) {
|
||||
if (!state.scope.prev) return;
|
||||
if (state.scope.type === "coffee") {
|
||||
var _indent = stream.indentation();
|
||||
var matched = false;
|
||||
for (var scope = state.scope; scope; scope = scope.prev) {
|
||||
if (_indent === scope.offset) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
return true;
|
||||
}
|
||||
while (state.scope.prev && state.scope.offset !== _indent) {
|
||||
state.scope = state.scope.prev;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
state.scope = state.scope.prev;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function tokenLexer(stream, state) {
|
||||
var style = state.tokenize(stream, state);
|
||||
var current = stream.current();
|
||||
|
||||
// Handle scope changes.
|
||||
if (current === "return") {
|
||||
state.dedent = true;
|
||||
}
|
||||
if (((current === "->" || current === "=>") && stream.eol())
|
||||
|| style === "indent") {
|
||||
indent(stream, state);
|
||||
}
|
||||
var delimiter_index = "[({".indexOf(current);
|
||||
if (delimiter_index !== -1) {
|
||||
indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1));
|
||||
}
|
||||
if (indentKeywords.exec(current)){
|
||||
indent(stream, state);
|
||||
}
|
||||
if (current == "then"){
|
||||
dedent(stream, state);
|
||||
}
|
||||
|
||||
|
||||
if (style === "dedent") {
|
||||
if (dedent(stream, state)) {
|
||||
return ERRORCLASS;
|
||||
}
|
||||
}
|
||||
delimiter_index = "])}".indexOf(current);
|
||||
if (delimiter_index !== -1) {
|
||||
while (state.scope.type == "coffee" && state.scope.prev)
|
||||
state.scope = state.scope.prev;
|
||||
if (state.scope.type == current)
|
||||
state.scope = state.scope.prev;
|
||||
}
|
||||
if (state.dedent && stream.eol()) {
|
||||
if (state.scope.type == "coffee" && state.scope.prev)
|
||||
state.scope = state.scope.prev;
|
||||
state.dedent = false;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
var external = {
|
||||
startState: function(basecolumn) {
|
||||
return {
|
||||
tokenize: tokenBase,
|
||||
scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false},
|
||||
prop: false,
|
||||
dedent: 0
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
var fillAlign = state.scope.align === null && state.scope;
|
||||
if (fillAlign && stream.sol()) fillAlign.align = false;
|
||||
|
||||
var style = tokenLexer(stream, state);
|
||||
if (style && style != "comment") {
|
||||
if (fillAlign) fillAlign.align = true;
|
||||
state.prop = style == "punctuation" && stream.current() == "."
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function(state, text) {
|
||||
if (state.tokenize != tokenBase) return 0;
|
||||
var scope = state.scope;
|
||||
var closer = text && "])}".indexOf(text.charAt(0)) > -1;
|
||||
if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev;
|
||||
var closes = closer && scope.type === text.charAt(0);
|
||||
if (scope.align)
|
||||
return scope.alignOffset - (closes ? 1 : 0);
|
||||
else
|
||||
return (closes ? scope.prev : scope).offset;
|
||||
},
|
||||
|
||||
lineComment: "#",
|
||||
fold: "indent"
|
||||
};
|
||||
return external;
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-coffeescript", "coffeescript");
|
||||
CodeMirror.defineMIME("text/coffeescript", "coffeescript");
|
||||
|
||||
});
|
||||
740
public/plugins/codemirror-5.17.0/mode/coffeescript/index.html
Normal file
740
public/plugins/codemirror-5.17.0/mode/coffeescript/index.html
Normal file
@@ -0,0 +1,740 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: CoffeeScript mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="coffeescript.js"></script>
|
||||
<style>.CodeMirror {border-top: 1px solid silver; border-bottom: 1px solid silver;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">CoffeeScript</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>CoffeeScript mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# CoffeeScript mode for CodeMirror
|
||||
# Copyright (c) 2011 Jeff Pickhardt, released under
|
||||
# the MIT License.
|
||||
#
|
||||
# Modified from the Python CodeMirror mode, which also is
|
||||
# under the MIT License Copyright (c) 2010 Timothy Farrell.
|
||||
#
|
||||
# The following script, Underscore.coffee, is used to
|
||||
# demonstrate CoffeeScript mode for CodeMirror.
|
||||
#
|
||||
# To download CoffeeScript mode for CodeMirror, go to:
|
||||
# https://github.com/pickhardt/coffeescript-codemirror-mode
|
||||
|
||||
# **Underscore.coffee
|
||||
# (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.**
|
||||
# Underscore is freely distributable under the terms of the
|
||||
# [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
||||
# Portions of Underscore are inspired by or borrowed from
|
||||
# [Prototype.js](http://prototypejs.org/api), Oliver Steele's
|
||||
# [Functional](http://osteele.com), and John Resig's
|
||||
# [Micro-Templating](http://ejohn.org).
|
||||
# For all details and documentation:
|
||||
# http://documentcloud.github.com/underscore/
|
||||
|
||||
|
||||
# Baseline setup
|
||||
# --------------
|
||||
|
||||
# Establish the root object, `window` in the browser, or `global` on the server.
|
||||
root = this
|
||||
|
||||
|
||||
# Save the previous value of the `_` variable.
|
||||
previousUnderscore = root._
|
||||
|
||||
### Multiline
|
||||
comment
|
||||
###
|
||||
|
||||
# Establish the object that gets thrown to break out of a loop iteration.
|
||||
# `StopIteration` is SOP on Mozilla.
|
||||
breaker = if typeof(StopIteration) is 'undefined' then '__break__' else StopIteration
|
||||
|
||||
|
||||
#### Docco style single line comment (title)
|
||||
|
||||
|
||||
# Helper function to escape **RegExp** contents, because JS doesn't have one.
|
||||
escapeRegExp = (string) -> string.replace(/([.*+?^${}()|[\]\/\\])/g, '\\$1')
|
||||
|
||||
|
||||
# Save bytes in the minified (but not gzipped) version:
|
||||
ArrayProto = Array.prototype
|
||||
ObjProto = Object.prototype
|
||||
|
||||
|
||||
# Create quick reference variables for speed access to core prototypes.
|
||||
slice = ArrayProto.slice
|
||||
unshift = ArrayProto.unshift
|
||||
toString = ObjProto.toString
|
||||
hasOwnProperty = ObjProto.hasOwnProperty
|
||||
propertyIsEnumerable = ObjProto.propertyIsEnumerable
|
||||
|
||||
|
||||
# All **ECMA5** native implementations we hope to use are declared here.
|
||||
nativeForEach = ArrayProto.forEach
|
||||
nativeMap = ArrayProto.map
|
||||
nativeReduce = ArrayProto.reduce
|
||||
nativeReduceRight = ArrayProto.reduceRight
|
||||
nativeFilter = ArrayProto.filter
|
||||
nativeEvery = ArrayProto.every
|
||||
nativeSome = ArrayProto.some
|
||||
nativeIndexOf = ArrayProto.indexOf
|
||||
nativeLastIndexOf = ArrayProto.lastIndexOf
|
||||
nativeIsArray = Array.isArray
|
||||
nativeKeys = Object.keys
|
||||
|
||||
|
||||
# Create a safe reference to the Underscore object for use below.
|
||||
_ = (obj) -> new wrapper(obj)
|
||||
|
||||
|
||||
# Export the Underscore object for **CommonJS**.
|
||||
if typeof(exports) != 'undefined' then exports._ = _
|
||||
|
||||
|
||||
# Export Underscore to global scope.
|
||||
root._ = _
|
||||
|
||||
|
||||
# Current version.
|
||||
_.VERSION = '1.1.0'
|
||||
|
||||
|
||||
# Collection Functions
|
||||
# --------------------
|
||||
|
||||
# The cornerstone, an **each** implementation.
|
||||
# Handles objects implementing **forEach**, arrays, and raw objects.
|
||||
_.each = (obj, iterator, context) ->
|
||||
try
|
||||
if nativeForEach and obj.forEach is nativeForEach
|
||||
obj.forEach iterator, context
|
||||
else if _.isNumber obj.length
|
||||
iterator.call context, obj[i], i, obj for i in [0...obj.length]
|
||||
else
|
||||
iterator.call context, val, key, obj for own key, val of obj
|
||||
catch e
|
||||
throw e if e isnt breaker
|
||||
obj
|
||||
|
||||
|
||||
# Return the results of applying the iterator to each element. Use JavaScript
|
||||
# 1.6's version of **map**, if possible.
|
||||
_.map = (obj, iterator, context) ->
|
||||
return obj.map(iterator, context) if nativeMap and obj.map is nativeMap
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# **Reduce** builds up a single result from a list of values. Also known as
|
||||
# **inject**, or **foldl**. Uses JavaScript 1.8's version of **reduce**, if possible.
|
||||
_.reduce = (obj, iterator, memo, context) ->
|
||||
if nativeReduce and obj.reduce is nativeReduce
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduce iterator, memo
|
||||
_.each obj, (value, index, list) ->
|
||||
memo = iterator.call context, memo, value, index, list
|
||||
memo
|
||||
|
||||
|
||||
# The right-associative version of **reduce**, also known as **foldr**. Uses
|
||||
# JavaScript 1.8's version of **reduceRight**, if available.
|
||||
_.reduceRight = (obj, iterator, memo, context) ->
|
||||
if nativeReduceRight and obj.reduceRight is nativeReduceRight
|
||||
iterator = _.bind iterator, context if context
|
||||
return obj.reduceRight iterator, memo
|
||||
reversed = _.clone(_.toArray(obj)).reverse()
|
||||
_.reduce reversed, iterator, memo, context
|
||||
|
||||
|
||||
# Return the first value which passes a truth test.
|
||||
_.detect = (obj, iterator, context) ->
|
||||
result = null
|
||||
_.each obj, (value, index, list) ->
|
||||
if iterator.call context, value, index, list
|
||||
result = value
|
||||
_.breakLoop()
|
||||
result
|
||||
|
||||
|
||||
# Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
# **filter**, if it exists.
|
||||
_.filter = (obj, iterator, context) ->
|
||||
return obj.filter iterator, context if nativeFilter and obj.filter is nativeFilter
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Return all the elements for which a truth test fails.
|
||||
_.reject = (obj, iterator, context) ->
|
||||
results = []
|
||||
_.each obj, (value, index, list) ->
|
||||
results.push value if not iterator.call context, value, index, list
|
||||
results
|
||||
|
||||
|
||||
# Determine whether all of the elements match a truth test. Delegate to
|
||||
# JavaScript 1.6's **every**, if it is present.
|
||||
_.every = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
|
||||
result = true
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() unless (result = result and iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if at least one element in the object matches a truth test. Use
|
||||
# JavaScript 1.6's **some**, if it exists.
|
||||
_.some = (obj, iterator, context) ->
|
||||
iterator ||= _.identity
|
||||
return obj.some iterator, context if nativeSome and obj.some is nativeSome
|
||||
result = false
|
||||
_.each obj, (value, index, list) ->
|
||||
_.breakLoop() if (result = iterator.call(context, value, index, list))
|
||||
result
|
||||
|
||||
|
||||
# Determine if a given value is included in the array or object,
|
||||
# based on `===`.
|
||||
_.include = (obj, target) ->
|
||||
return _.indexOf(obj, target) isnt -1 if nativeIndexOf and obj.indexOf is nativeIndexOf
|
||||
return true for own key, val of obj when val is target
|
||||
false
|
||||
|
||||
|
||||
# Invoke a method with arguments on every item in a collection.
|
||||
_.invoke = (obj, method) ->
|
||||
args = _.rest arguments, 2
|
||||
(if method then val[method] else val).apply(val, args) for val in obj
|
||||
|
||||
|
||||
# Convenience version of a common use case of **map**: fetching a property.
|
||||
_.pluck = (obj, key) ->
|
||||
_.map(obj, (val) -> val[key])
|
||||
|
||||
|
||||
# Return the maximum item or (item-based computation).
|
||||
_.max = (obj, iterator, context) ->
|
||||
return Math.max.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: -Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed >= result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Return the minimum element (or element-based computation).
|
||||
_.min = (obj, iterator, context) ->
|
||||
return Math.min.apply(Math, obj) if not iterator and _.isArray(obj)
|
||||
result = computed: Infinity
|
||||
_.each obj, (value, index, list) ->
|
||||
computed = if iterator then iterator.call(context, value, index, list) else value
|
||||
computed < result.computed and (result = {value: value, computed: computed})
|
||||
result.value
|
||||
|
||||
|
||||
# Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = (obj, iterator, context) ->
|
||||
_.pluck(((_.map obj, (value, index, list) ->
|
||||
{value: value, criteria: iterator.call(context, value, index, list)}
|
||||
).sort((left, right) ->
|
||||
a = left.criteria; b = right.criteria
|
||||
if a < b then -1 else if a > b then 1 else 0
|
||||
)), 'value')
|
||||
|
||||
|
||||
# Use a comparator function to figure out at what index an object should
|
||||
# be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = (array, obj, iterator) ->
|
||||
iterator ||= _.identity
|
||||
low = 0
|
||||
high = array.length
|
||||
while low < high
|
||||
mid = (low + high) >> 1
|
||||
if iterator(array[mid]) < iterator(obj) then low = mid + 1 else high = mid
|
||||
low
|
||||
|
||||
|
||||
# Convert anything iterable into a real, live array.
|
||||
_.toArray = (iterable) ->
|
||||
return [] if (!iterable)
|
||||
return iterable.toArray() if (iterable.toArray)
|
||||
return iterable if (_.isArray(iterable))
|
||||
return slice.call(iterable) if (_.isArguments(iterable))
|
||||
_.values(iterable)
|
||||
|
||||
|
||||
# Return the number of elements in an object.
|
||||
_.size = (obj) -> _.toArray(obj).length
|
||||
|
||||
|
||||
# Array Functions
|
||||
# ---------------
|
||||
|
||||
# Get the first element of an array. Passing `n` will return the first N
|
||||
# values in the array. Aliased as **head**. The `guard` check allows it to work
|
||||
# with **map**.
|
||||
_.first = (array, n, guard) ->
|
||||
if n and not guard then slice.call(array, 0, n) else array[0]
|
||||
|
||||
|
||||
# Returns everything but the first entry of the array. Aliased as **tail**.
|
||||
# Especially useful on the arguments object. Passing an `index` will return
|
||||
# the rest of the values in the array from that index onward. The `guard`
|
||||
# check allows it to work with **map**.
|
||||
_.rest = (array, index, guard) ->
|
||||
slice.call(array, if _.isUndefined(index) or guard then 1 else index)
|
||||
|
||||
|
||||
# Get the last element of an array.
|
||||
_.last = (array) -> array[array.length - 1]
|
||||
|
||||
|
||||
# Trim out all falsy values from an array.
|
||||
_.compact = (array) -> item for item in array when item
|
||||
|
||||
|
||||
# Return a completely flattened version of an array.
|
||||
_.flatten = (array) ->
|
||||
_.reduce array, (memo, value) ->
|
||||
return memo.concat(_.flatten(value)) if _.isArray value
|
||||
memo.push value
|
||||
memo
|
||||
, []
|
||||
|
||||
|
||||
# Return a version of the array that does not contain the specified value(s).
|
||||
_.without = (array) ->
|
||||
values = _.rest arguments
|
||||
val for val in _.toArray(array) when not _.include values, val
|
||||
|
||||
|
||||
# Produce a duplicate-free version of the array. If the array has already
|
||||
# been sorted, you have the option of using a faster algorithm.
|
||||
_.uniq = (array, isSorted) ->
|
||||
memo = []
|
||||
for el, i in _.toArray array
|
||||
memo.push el if i is 0 || (if isSorted is true then _.last(memo) isnt el else not _.include(memo, el))
|
||||
memo
|
||||
|
||||
|
||||
# Produce an array that contains every item shared between all the
|
||||
# passed-in arrays.
|
||||
_.intersect = (array) ->
|
||||
rest = _.rest arguments
|
||||
_.select _.uniq(array), (item) ->
|
||||
_.all rest, (other) ->
|
||||
_.indexOf(other, item) >= 0
|
||||
|
||||
|
||||
# Zip together multiple lists into a single array -- elements that share
|
||||
# an index go together.
|
||||
_.zip = ->
|
||||
length = _.max _.pluck arguments, 'length'
|
||||
results = new Array length
|
||||
for i in [0...length]
|
||||
results[i] = _.pluck arguments, String i
|
||||
results
|
||||
|
||||
|
||||
# If the browser doesn't supply us with **indexOf** (I'm looking at you, MSIE),
|
||||
# we need this function. Return the position of the first occurrence of an
|
||||
# item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf = (array, item) ->
|
||||
return array.indexOf item if nativeIndexOf and array.indexOf is nativeIndexOf
|
||||
i = 0; l = array.length
|
||||
while l - i
|
||||
if array[i] is item then return i else i++
|
||||
-1
|
||||
|
||||
|
||||
# Provide JavaScript 1.6's **lastIndexOf**, delegating to the native function,
|
||||
# if possible.
|
||||
_.lastIndexOf = (array, item) ->
|
||||
return array.lastIndexOf(item) if nativeLastIndexOf and array.lastIndexOf is nativeLastIndexOf
|
||||
i = array.length
|
||||
while i
|
||||
if array[i] is item then return i else i--
|
||||
-1
|
||||
|
||||
|
||||
# Generate an integer Array containing an arithmetic progression. A port of
|
||||
# [the native Python **range** function](http://docs.python.org/library/functions.html#range).
|
||||
_.range = (start, stop, step) ->
|
||||
a = arguments
|
||||
solo = a.length <= 1
|
||||
i = start = if solo then 0 else a[0]
|
||||
stop = if solo then a[0] else a[1]
|
||||
step = a[2] or 1
|
||||
len = Math.ceil((stop - start) / step)
|
||||
return [] if len <= 0
|
||||
range = new Array len
|
||||
idx = 0
|
||||
loop
|
||||
return range if (if step > 0 then i - stop else stop - i) >= 0
|
||||
range[idx] = i
|
||||
idx++
|
||||
i+= step
|
||||
|
||||
|
||||
# Function Functions
|
||||
# ------------------
|
||||
|
||||
# Create a function bound to a given object (assigning `this`, and arguments,
|
||||
# optionally). Binding with arguments is also known as **curry**.
|
||||
_.bind = (func, obj) ->
|
||||
args = _.rest arguments, 2
|
||||
-> func.apply obj or root, args.concat arguments
|
||||
|
||||
|
||||
# Bind all of an object's methods to that object. Useful for ensuring that
|
||||
# all callbacks defined on an object belong to it.
|
||||
_.bindAll = (obj) ->
|
||||
funcs = if arguments.length > 1 then _.rest(arguments) else _.functions(obj)
|
||||
_.each funcs, (f) -> obj[f] = _.bind obj[f], obj
|
||||
obj
|
||||
|
||||
|
||||
# Delays a function for the given number of milliseconds, and then calls
|
||||
# it with the arguments supplied.
|
||||
_.delay = (func, wait) ->
|
||||
args = _.rest arguments, 2
|
||||
setTimeout((-> func.apply(func, args)), wait)
|
||||
|
||||
|
||||
# Memoize an expensive function by storing its results.
|
||||
_.memoize = (func, hasher) ->
|
||||
memo = {}
|
||||
hasher or= _.identity
|
||||
->
|
||||
key = hasher.apply this, arguments
|
||||
return memo[key] if key of memo
|
||||
memo[key] = func.apply this, arguments
|
||||
|
||||
|
||||
# Defers a function, scheduling it to run after the current call stack has
|
||||
# cleared.
|
||||
_.defer = (func) ->
|
||||
_.delay.apply _, [func, 1].concat _.rest arguments
|
||||
|
||||
|
||||
# Returns the first function passed as an argument to the second,
|
||||
# allowing you to adjust arguments, run code before and after, and
|
||||
# conditionally execute the original function.
|
||||
_.wrap = (func, wrapper) ->
|
||||
-> wrapper.apply wrapper, [func].concat arguments
|
||||
|
||||
|
||||
# Returns a function that is the composition of a list of functions, each
|
||||
# consuming the return value of the function that follows.
|
||||
_.compose = ->
|
||||
funcs = arguments
|
||||
->
|
||||
args = arguments
|
||||
for i in [funcs.length - 1..0] by -1
|
||||
args = [funcs[i].apply(this, args)]
|
||||
args[0]
|
||||
|
||||
|
||||
# Object Functions
|
||||
# ----------------
|
||||
|
||||
# Retrieve the names of an object's properties.
|
||||
_.keys = nativeKeys or (obj) ->
|
||||
return _.range 0, obj.length if _.isArray(obj)
|
||||
key for key, val of obj
|
||||
|
||||
|
||||
# Retrieve the values of an object's properties.
|
||||
_.values = (obj) ->
|
||||
_.map obj, _.identity
|
||||
|
||||
|
||||
# Return a sorted list of the function names available in Underscore.
|
||||
_.functions = (obj) ->
|
||||
_.filter(_.keys(obj), (key) -> _.isFunction(obj[key])).sort()
|
||||
|
||||
|
||||
# Extend a given object with all of the properties in a source object.
|
||||
_.extend = (obj) ->
|
||||
for source in _.rest(arguments)
|
||||
obj[key] = val for key, val of source
|
||||
obj
|
||||
|
||||
|
||||
# Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = (obj) ->
|
||||
return obj.slice 0 if _.isArray obj
|
||||
_.extend {}, obj
|
||||
|
||||
|
||||
# Invokes interceptor with the obj, and then returns obj.
|
||||
# The primary purpose of this method is to "tap into" a method chain,
|
||||
# in order to perform operations on intermediate results within
|
||||
the chain.
|
||||
_.tap = (obj, interceptor) ->
|
||||
interceptor obj
|
||||
obj
|
||||
|
||||
|
||||
# Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = (a, b) ->
|
||||
# Check object identity.
|
||||
return true if a is b
|
||||
# Different types?
|
||||
atype = typeof(a); btype = typeof(b)
|
||||
return false if atype isnt btype
|
||||
# Basic equality test (watch out for coercions).
|
||||
return true if `a == b`
|
||||
# One is falsy and the other truthy.
|
||||
return false if (!a and b) or (a and !b)
|
||||
# One of them implements an `isEqual()`?
|
||||
return a.isEqual(b) if a.isEqual
|
||||
# Check dates' integer values.
|
||||
return a.getTime() is b.getTime() if _.isDate(a) and _.isDate(b)
|
||||
# Both are NaN?
|
||||
return false if _.isNaN(a) and _.isNaN(b)
|
||||
# Compare regular expressions.
|
||||
if _.isRegExp(a) and _.isRegExp(b)
|
||||
return a.source is b.source and
|
||||
a.global is b.global and
|
||||
a.ignoreCase is b.ignoreCase and
|
||||
a.multiline is b.multiline
|
||||
# If a is not an object by this point, we can't handle it.
|
||||
return false if atype isnt 'object'
|
||||
# Check for different array lengths before comparing contents.
|
||||
return false if a.length and (a.length isnt b.length)
|
||||
# Nothing else worked, deep compare the contents.
|
||||
aKeys = _.keys(a); bKeys = _.keys(b)
|
||||
# Different object sizes?
|
||||
return false if aKeys.length isnt bKeys.length
|
||||
# Recursive comparison of contents.
|
||||
return false for key, val of a when !(key of b) or !_.isEqual(val, b[key])
|
||||
true
|
||||
|
||||
|
||||
# Is a given array or object empty?
|
||||
_.isEmpty = (obj) ->
|
||||
return obj.length is 0 if _.isArray(obj) or _.isString(obj)
|
||||
return false for own key of obj
|
||||
true
|
||||
|
||||
|
||||
# Is a given value a DOM element?
|
||||
_.isElement = (obj) -> obj and obj.nodeType is 1
|
||||
|
||||
|
||||
# Is a given value an array?
|
||||
_.isArray = nativeIsArray or (obj) -> !!(obj and obj.concat and obj.unshift and not obj.callee)
|
||||
|
||||
|
||||
# Is a given variable an arguments object?
|
||||
_.isArguments = (obj) -> obj and obj.callee
|
||||
|
||||
|
||||
# Is the given value a function?
|
||||
_.isFunction = (obj) -> !!(obj and obj.constructor and obj.call and obj.apply)
|
||||
|
||||
|
||||
# Is the given value a string?
|
||||
_.isString = (obj) -> !!(obj is '' or (obj and obj.charCodeAt and obj.substr))
|
||||
|
||||
|
||||
# Is a given value a number?
|
||||
_.isNumber = (obj) -> (obj is +obj) or toString.call(obj) is '[object Number]'
|
||||
|
||||
|
||||
# Is a given value a boolean?
|
||||
_.isBoolean = (obj) -> obj is true or obj is false
|
||||
|
||||
|
||||
# Is a given value a Date?
|
||||
_.isDate = (obj) -> !!(obj and obj.getTimezoneOffset and obj.setUTCFullYear)
|
||||
|
||||
|
||||
# Is the given value a regular expression?
|
||||
_.isRegExp = (obj) -> !!(obj and obj.exec and (obj.ignoreCase or obj.ignoreCase is false))
|
||||
|
||||
|
||||
# Is the given value NaN -- this one is interesting. `NaN != NaN`, and
|
||||
# `isNaN(undefined) == true`, so we make sure it's a number first.
|
||||
_.isNaN = (obj) -> _.isNumber(obj) and window.isNaN(obj)
|
||||
|
||||
|
||||
# Is a given value equal to null?
|
||||
_.isNull = (obj) -> obj is null
|
||||
|
||||
|
||||
# Is a given variable undefined?
|
||||
_.isUndefined = (obj) -> typeof obj is 'undefined'
|
||||
|
||||
|
||||
# Utility Functions
|
||||
# -----------------
|
||||
|
||||
# Run Underscore.js in noConflict mode, returning the `_` variable to its
|
||||
# previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = ->
|
||||
root._ = previousUnderscore
|
||||
this
|
||||
|
||||
|
||||
# Keep the identity function around for default iterators.
|
||||
_.identity = (value) -> value
|
||||
|
||||
|
||||
# Run a function `n` times.
|
||||
_.times = (n, iterator, context) ->
|
||||
iterator.call context, i for i in [0...n]
|
||||
|
||||
|
||||
# Break out of the middle of an iteration.
|
||||
_.breakLoop = -> throw breaker
|
||||
|
||||
|
||||
# Add your own custom functions to the Underscore object, ensuring that
|
||||
# they're correctly added to the OOP wrapper as well.
|
||||
_.mixin = (obj) ->
|
||||
for name in _.functions(obj)
|
||||
addToWrapper name, _[name] = obj[name]
|
||||
|
||||
|
||||
# Generate a unique integer id (unique within the entire client session).
|
||||
# Useful for temporary DOM ids.
|
||||
idCounter = 0
|
||||
_.uniqueId = (prefix) ->
|
||||
(prefix or '') + idCounter++
|
||||
|
||||
|
||||
# By default, Underscore uses **ERB**-style template delimiters, change the
|
||||
# following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
start: '<%'
|
||||
end: '%>'
|
||||
interpolate: /<%=(.+?)%>/g
|
||||
}
|
||||
|
||||
|
||||
# JavaScript templating a-la **ERB**, pilfered from John Resig's
|
||||
# *Secrets of the JavaScript Ninja*, page 83.
|
||||
# Single-quote fix from Rick Strahl.
|
||||
# With alterations for arbitrary delimiters, and to preserve whitespace.
|
||||
_.template = (str, data) ->
|
||||
c = _.templateSettings
|
||||
endMatch = new RegExp("'(?=[^"+c.end.substr(0, 1)+"]*"+escapeRegExp(c.end)+")","g")
|
||||
fn = new Function 'obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj||{}){p.push(\'' +
|
||||
str.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
.replace(endMatch,"<22><><EFBFBD>")
|
||||
.split("'").join("\\'")
|
||||
.split("<22><><EFBFBD>").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
.split(c.start).join("');")
|
||||
.split(c.end).join("p.push('") +
|
||||
"');}return p.join('');"
|
||||
if data then fn(data) else fn
|
||||
|
||||
|
||||
# Aliases
|
||||
# -------
|
||||
|
||||
_.forEach = _.each
|
||||
_.foldl = _.inject = _.reduce
|
||||
_.foldr = _.reduceRight
|
||||
_.select = _.filter
|
||||
_.all = _.every
|
||||
_.any = _.some
|
||||
_.contains = _.include
|
||||
_.head = _.first
|
||||
_.tail = _.rest
|
||||
_.methods = _.functions
|
||||
|
||||
|
||||
# Setup the OOP Wrapper
|
||||
# ---------------------
|
||||
|
||||
# If Underscore is called as a function, it returns a wrapped object that
|
||||
# can be used OO-style. This wrapper holds altered versions of all the
|
||||
# underscore functions. Wrapped objects may be chained.
|
||||
wrapper = (obj) ->
|
||||
this._wrapped = obj
|
||||
this
|
||||
|
||||
|
||||
# Helper function to continue chaining intermediate results.
|
||||
result = (obj, chain) ->
|
||||
if chain then _(obj).chain() else obj
|
||||
|
||||
|
||||
# A method to easily add functions to the OOP wrapper.
|
||||
addToWrapper = (name, func) ->
|
||||
wrapper.prototype[name] = ->
|
||||
args = _.toArray arguments
|
||||
unshift.call args, this._wrapped
|
||||
result func.apply(_, args), this._chain
|
||||
|
||||
|
||||
# Add all ofthe Underscore functions to the wrapper object.
|
||||
_.mixin _
|
||||
|
||||
|
||||
# Add all mutator Array functions to the wrapper.
|
||||
_.each ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
method.apply(this._wrapped, arguments)
|
||||
result(this._wrapped, this._chain)
|
||||
|
||||
|
||||
# Add all accessor Array functions to the wrapper.
|
||||
_.each ['concat', 'join', 'slice'], (name) ->
|
||||
method = Array.prototype[name]
|
||||
wrapper.prototype[name] = ->
|
||||
result(method.apply(this._wrapped, arguments), this._chain)
|
||||
|
||||
|
||||
# Start chaining a wrapped Underscore object.
|
||||
wrapper::chain = ->
|
||||
this._chain = true
|
||||
this
|
||||
|
||||
|
||||
# Extracts the result from a wrapped and chained object.
|
||||
wrapper::value = -> this._wrapped
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-coffeescript</code>.</p>
|
||||
|
||||
<p>The CoffeeScript mode was written by Jeff Pickhardt.</p>
|
||||
|
||||
</article>
|
||||
123
public/plugins/codemirror-5.17.0/mode/commonlisp/commonlisp.js
Normal file
123
public/plugins/codemirror-5.17.0/mode/commonlisp/commonlisp.js
Normal file
@@ -0,0 +1,123 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("commonlisp", function (config) {
|
||||
var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/;
|
||||
var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/;
|
||||
var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/;
|
||||
var symbol = /[^\s'`,@()\[\]";]/;
|
||||
var type;
|
||||
|
||||
function readSym(stream) {
|
||||
var ch;
|
||||
while (ch = stream.next()) {
|
||||
if (ch == "\\") stream.next();
|
||||
else if (!symbol.test(ch)) { stream.backUp(1); break; }
|
||||
}
|
||||
return stream.current();
|
||||
}
|
||||
|
||||
function base(stream, state) {
|
||||
if (stream.eatSpace()) {type = "ws"; return null;}
|
||||
if (stream.match(numLiteral)) return "number";
|
||||
var ch = stream.next();
|
||||
if (ch == "\\") ch = stream.next();
|
||||
|
||||
if (ch == '"') return (state.tokenize = inString)(stream, state);
|
||||
else if (ch == "(") { type = "open"; return "bracket"; }
|
||||
else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; }
|
||||
else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; }
|
||||
else if (/['`,@]/.test(ch)) return null;
|
||||
else if (ch == "|") {
|
||||
if (stream.skipTo("|")) { stream.next(); return "symbol"; }
|
||||
else { stream.skipToEnd(); return "error"; }
|
||||
} else if (ch == "#") {
|
||||
var ch = stream.next();
|
||||
if (ch == "[") { type = "open"; return "bracket"; }
|
||||
else if (/[+\-=\.']/.test(ch)) return null;
|
||||
else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null;
|
||||
else if (ch == "|") return (state.tokenize = inComment)(stream, state);
|
||||
else if (ch == ":") { readSym(stream); return "meta"; }
|
||||
else return "error";
|
||||
} else {
|
||||
var name = readSym(stream);
|
||||
if (name == ".") return null;
|
||||
type = "symbol";
|
||||
if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom";
|
||||
if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword";
|
||||
if (name.charAt(0) == "&") return "variable-2";
|
||||
return "variable";
|
||||
}
|
||||
}
|
||||
|
||||
function inString(stream, state) {
|
||||
var escaped = false, next;
|
||||
while (next = stream.next()) {
|
||||
if (next == '"' && !escaped) { state.tokenize = base; break; }
|
||||
escaped = !escaped && next == "\\";
|
||||
}
|
||||
return "string";
|
||||
}
|
||||
|
||||
function inComment(stream, state) {
|
||||
var next, last;
|
||||
while (next = stream.next()) {
|
||||
if (next == "#" && last == "|") { state.tokenize = base; break; }
|
||||
last = next;
|
||||
}
|
||||
type = "ws";
|
||||
return "comment";
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
if (stream.sol() && typeof state.ctx.indentTo != "number")
|
||||
state.ctx.indentTo = state.ctx.start + 1;
|
||||
|
||||
type = null;
|
||||
var style = state.tokenize(stream, state);
|
||||
if (type != "ws") {
|
||||
if (state.ctx.indentTo == null) {
|
||||
if (type == "symbol" && assumeBody.test(stream.current()))
|
||||
state.ctx.indentTo = state.ctx.start + config.indentUnit;
|
||||
else
|
||||
state.ctx.indentTo = "next";
|
||||
} else if (state.ctx.indentTo == "next") {
|
||||
state.ctx.indentTo = stream.column();
|
||||
}
|
||||
state.lastType = type;
|
||||
}
|
||||
if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null};
|
||||
else if (type == "close") state.ctx = state.ctx.prev || state.ctx;
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function (state, _textAfter) {
|
||||
var i = state.ctx.indentTo;
|
||||
return typeof i == "number" ? i : state.ctx.start + 1;
|
||||
},
|
||||
|
||||
closeBrackets: {pairs: "()[]{}\"\""},
|
||||
lineComment: ";;",
|
||||
blockCommentStart: "#|",
|
||||
blockCommentEnd: "|#"
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-common-lisp", "commonlisp");
|
||||
|
||||
});
|
||||
177
public/plugins/codemirror-5.17.0/mode/commonlisp/index.html
Normal file
177
public/plugins/codemirror-5.17.0/mode/commonlisp/index.html
Normal file
@@ -0,0 +1,177 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Common Lisp mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="commonlisp.js"></script>
|
||||
<style>.CodeMirror {background: #f8f8f8;}</style>
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Common Lisp</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Common Lisp mode</h2>
|
||||
<form><textarea id="code" name="code">(in-package :cl-postgres)
|
||||
|
||||
;; These are used to synthesize reader and writer names for integer
|
||||
;; reading/writing functions when the amount of bytes and the
|
||||
;; signedness is known. Both the macro that creates the functions and
|
||||
;; some macros that use them create names this way.
|
||||
(eval-when (:compile-toplevel :load-toplevel :execute)
|
||||
(defun integer-reader-name (bytes signed)
|
||||
(intern (with-standard-io-syntax
|
||||
(format nil "~a~a~a~a" '#:read- (if signed "" '#:u) '#:int bytes))))
|
||||
(defun integer-writer-name (bytes signed)
|
||||
(intern (with-standard-io-syntax
|
||||
(format nil "~a~a~a~a" '#:write- (if signed "" '#:u) '#:int bytes)))))
|
||||
|
||||
(defmacro integer-reader (bytes)
|
||||
"Create a function to read integers from a binary stream."
|
||||
(let ((bits (* bytes 8)))
|
||||
(labels ((return-form (signed)
|
||||
(if signed
|
||||
`(if (logbitp ,(1- bits) result)
|
||||
(dpb result (byte ,(1- bits) 0) -1)
|
||||
result)
|
||||
`result))
|
||||
(generate-reader (signed)
|
||||
`(defun ,(integer-reader-name bytes signed) (socket)
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
,(if (= bytes 1)
|
||||
`(let ((result (the (unsigned-byte 8) (read-byte socket))))
|
||||
(declare (type (unsigned-byte 8) result))
|
||||
,(return-form signed))
|
||||
`(let ((result 0))
|
||||
(declare (type (unsigned-byte ,bits) result))
|
||||
,@(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(setf (ldb (byte 8 ,(* 8 byte)) result)
|
||||
(the (unsigned-byte 8) (read-byte socket))))
|
||||
,(return-form signed))))))
|
||||
`(progn
|
||||
;; This causes weird errors on SBCL in some circumstances. Disabled for now.
|
||||
;; (declaim (inline ,(integer-reader-name bytes t)
|
||||
;; ,(integer-reader-name bytes nil)))
|
||||
(declaim (ftype (function (t) (signed-byte ,bits))
|
||||
,(integer-reader-name bytes t)))
|
||||
,(generate-reader t)
|
||||
(declaim (ftype (function (t) (unsigned-byte ,bits))
|
||||
,(integer-reader-name bytes nil)))
|
||||
,(generate-reader nil)))))
|
||||
|
||||
(defmacro integer-writer (bytes)
|
||||
"Create a function to write integers to a binary stream."
|
||||
(let ((bits (* 8 bytes)))
|
||||
`(progn
|
||||
(declaim (inline ,(integer-writer-name bytes t)
|
||||
,(integer-writer-name bytes nil)))
|
||||
(defun ,(integer-writer-name bytes nil) (socket value)
|
||||
(declare (type stream socket)
|
||||
(type (unsigned-byte ,bits) value)
|
||||
#.*optimize*)
|
||||
,@(if (= bytes 1)
|
||||
`((write-byte value socket))
|
||||
(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
|
||||
socket)))
|
||||
(values))
|
||||
(defun ,(integer-writer-name bytes t) (socket value)
|
||||
(declare (type stream socket)
|
||||
(type (signed-byte ,bits) value)
|
||||
#.*optimize*)
|
||||
,@(if (= bytes 1)
|
||||
`((write-byte (ldb (byte 8 0) value) socket))
|
||||
(loop :for byte :from (1- bytes) :downto 0
|
||||
:collect `(write-byte (ldb (byte 8 ,(* byte 8)) value)
|
||||
socket)))
|
||||
(values)))))
|
||||
|
||||
;; All the instances of the above that we need.
|
||||
|
||||
(integer-reader 1)
|
||||
(integer-reader 2)
|
||||
(integer-reader 4)
|
||||
(integer-reader 8)
|
||||
|
||||
(integer-writer 1)
|
||||
(integer-writer 2)
|
||||
(integer-writer 4)
|
||||
|
||||
(defun write-bytes (socket bytes)
|
||||
"Write a byte-array to a stream."
|
||||
(declare (type stream socket)
|
||||
(type (simple-array (unsigned-byte 8)) bytes)
|
||||
#.*optimize*)
|
||||
(write-sequence bytes socket))
|
||||
|
||||
(defun write-str (socket string)
|
||||
"Write a null-terminated string to a stream \(encoding it when UTF-8
|
||||
support is enabled.)."
|
||||
(declare (type stream socket)
|
||||
(type string string)
|
||||
#.*optimize*)
|
||||
(enc-write-string string socket)
|
||||
(write-uint1 socket 0))
|
||||
|
||||
(declaim (ftype (function (t unsigned-byte)
|
||||
(simple-array (unsigned-byte 8) (*)))
|
||||
read-bytes))
|
||||
(defun read-bytes (socket length)
|
||||
"Read a byte array of the given length from a stream."
|
||||
(declare (type stream socket)
|
||||
(type fixnum length)
|
||||
#.*optimize*)
|
||||
(let ((result (make-array length :element-type '(unsigned-byte 8))))
|
||||
(read-sequence result socket)
|
||||
result))
|
||||
|
||||
(declaim (ftype (function (t) string) read-str))
|
||||
(defun read-str (socket)
|
||||
"Read a null-terminated string from a stream. Takes care of encoding
|
||||
when UTF-8 support is enabled."
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
(enc-read-string socket :null-terminated t))
|
||||
|
||||
(defun skip-bytes (socket length)
|
||||
"Skip a given number of bytes in a binary stream."
|
||||
(declare (type stream socket)
|
||||
(type (unsigned-byte 32) length)
|
||||
#.*optimize*)
|
||||
(dotimes (i length)
|
||||
(read-byte socket)))
|
||||
|
||||
(defun skip-str (socket)
|
||||
"Skip a null-terminated string."
|
||||
(declare (type stream socket)
|
||||
#.*optimize*)
|
||||
(loop :for char :of-type fixnum = (read-byte socket)
|
||||
:until (zerop char)))
|
||||
|
||||
(defun ensure-socket-is-closed (socket &key abort)
|
||||
(when (open-stream-p socket)
|
||||
(handler-case
|
||||
(close socket :abort abort)
|
||||
(error (error)
|
||||
(warn "Ignoring the error which happened while trying to close PostgreSQL socket: ~A" error)))))
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {lineNumbers: true});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-common-lisp</code>.</p>
|
||||
|
||||
</article>
|
||||
391
public/plugins/codemirror-5.17.0/mode/crystal/crystal.js
Normal file
391
public/plugins/codemirror-5.17.0/mode/crystal/crystal.js
Normal file
@@ -0,0 +1,391 @@
|
||||
// CodeMirror, copyright (c) by Marijn Haverbeke and others
|
||||
// Distributed under an MIT license: http://codemirror.net/LICENSE
|
||||
|
||||
(function(mod) {
|
||||
if (typeof exports == "object" && typeof module == "object") // CommonJS
|
||||
mod(require("../../lib/codemirror"));
|
||||
else if (typeof define == "function" && define.amd) // AMD
|
||||
define(["../../lib/codemirror"], mod);
|
||||
else // Plain browser env
|
||||
mod(CodeMirror);
|
||||
})(function(CodeMirror) {
|
||||
"use strict";
|
||||
|
||||
CodeMirror.defineMode("crystal", function(config) {
|
||||
function wordRegExp(words, end) {
|
||||
return new RegExp((end ? "" : "^") + "(?:" + words.join("|") + ")" + (end ? "$" : "\\b"));
|
||||
}
|
||||
|
||||
function chain(tokenize, stream, state) {
|
||||
state.tokenize.push(tokenize);
|
||||
return tokenize(stream, state);
|
||||
}
|
||||
|
||||
var operators = /^(?:[-+/%|&^]|\*\*?|[<>]{2})/;
|
||||
var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/;
|
||||
var indexingOperators = /^(?:\[\][?=]?)/;
|
||||
var anotherOperators = /^(?:\.(?:\.{2})?|->|[?:])/;
|
||||
var idents = /^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;
|
||||
var types = /^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/;
|
||||
var keywords = wordRegExp([
|
||||
"abstract", "alias", "as", "asm", "begin", "break", "case", "class", "def", "do",
|
||||
"else", "elsif", "end", "ensure", "enum", "extend", "for", "fun", "if", "ifdef",
|
||||
"include", "instance_sizeof", "lib", "macro", "module", "next", "of", "out", "pointerof",
|
||||
"private", "protected", "rescue", "return", "require", "sizeof", "struct",
|
||||
"super", "then", "type", "typeof", "union", "unless", "until", "when", "while", "with",
|
||||
"yield", "__DIR__", "__FILE__", "__LINE__"
|
||||
]);
|
||||
var atomWords = wordRegExp(["true", "false", "nil", "self"]);
|
||||
var indentKeywordsArray = [
|
||||
"def", "fun", "macro",
|
||||
"class", "module", "struct", "lib", "enum", "union",
|
||||
"if", "unless", "case", "while", "until", "begin", "then",
|
||||
"do",
|
||||
"for", "ifdef"
|
||||
];
|
||||
var indentKeywords = wordRegExp(indentKeywordsArray);
|
||||
var dedentKeywordsArray = [
|
||||
"end",
|
||||
"else", "elsif",
|
||||
"rescue", "ensure"
|
||||
];
|
||||
var dedentKeywords = wordRegExp(dedentKeywordsArray);
|
||||
var dedentPunctualsArray = ["\\)", "\\}", "\\]"];
|
||||
var dedentPunctuals = new RegExp("^(?:" + dedentPunctualsArray.join("|") + ")$");
|
||||
var nextTokenizer = {
|
||||
"def": tokenFollowIdent, "fun": tokenFollowIdent, "macro": tokenMacroDef,
|
||||
"class": tokenFollowType, "module": tokenFollowType, "struct": tokenFollowType,
|
||||
"lib": tokenFollowType, "enum": tokenFollowType, "union": tokenFollowType
|
||||
};
|
||||
var matching = {"[": "]", "{": "}", "(": ")", "<": ">"};
|
||||
|
||||
function tokenBase(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Macros
|
||||
if (state.lastToken != "\\" && stream.match("{%", false)) {
|
||||
return chain(tokenMacro("%", "%"), stream, state);
|
||||
}
|
||||
|
||||
if (state.lastToken != "\\" && stream.match("{{", false)) {
|
||||
return chain(tokenMacro("{", "}"), stream, state);
|
||||
}
|
||||
|
||||
// Comments
|
||||
if (stream.peek() == "#") {
|
||||
stream.skipToEnd();
|
||||
return "comment";
|
||||
}
|
||||
|
||||
// Variables and keywords
|
||||
var matched;
|
||||
if (stream.match(idents)) {
|
||||
stream.eat(/[?!]/);
|
||||
|
||||
matched = stream.current();
|
||||
if (stream.eat(":")) {
|
||||
return "atom";
|
||||
} else if (state.lastToken == ".") {
|
||||
return "property";
|
||||
} else if (keywords.test(matched)) {
|
||||
if (state.lastToken != "abstract" && indentKeywords.test(matched)) {
|
||||
if (!(matched == "fun" && state.blocks.indexOf("lib") >= 0)) {
|
||||
state.blocks.push(matched);
|
||||
state.currentIndent += 1;
|
||||
}
|
||||
} else if (dedentKeywords.test(matched)) {
|
||||
state.blocks.pop();
|
||||
state.currentIndent -= 1;
|
||||
}
|
||||
|
||||
if (nextTokenizer.hasOwnProperty(matched)) {
|
||||
state.tokenize.push(nextTokenizer[matched]);
|
||||
}
|
||||
|
||||
return "keyword";
|
||||
} else if (atomWords.test(matched)) {
|
||||
return "atom";
|
||||
}
|
||||
|
||||
return "variable";
|
||||
}
|
||||
|
||||
// Class variables and instance variables
|
||||
// or attributes
|
||||
if (stream.eat("@")) {
|
||||
if (stream.peek() == "[") {
|
||||
return chain(tokenNest("[", "]", "meta"), stream, state);
|
||||
}
|
||||
|
||||
stream.eat("@");
|
||||
stream.match(idents) || stream.match(types);
|
||||
return "variable-2";
|
||||
}
|
||||
|
||||
// Global variables
|
||||
if (stream.eat("$")) {
|
||||
stream.eat(/[0-9]+|\?/) || stream.match(idents) || stream.match(types);
|
||||
return "variable-3";
|
||||
}
|
||||
|
||||
// Constants and types
|
||||
if (stream.match(types)) {
|
||||
return "tag";
|
||||
}
|
||||
|
||||
// Symbols or ':' operator
|
||||
if (stream.eat(":")) {
|
||||
if (stream.eat("\"")) {
|
||||
return chain(tokenQuote("\"", "atom", false), stream, state);
|
||||
} else if (stream.match(idents) || stream.match(types) ||
|
||||
stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) {
|
||||
return "atom";
|
||||
}
|
||||
stream.eat(":");
|
||||
return "operator";
|
||||
}
|
||||
|
||||
// Strings
|
||||
if (stream.eat("\"")) {
|
||||
return chain(tokenQuote("\"", "string", true), stream, state);
|
||||
}
|
||||
|
||||
// Strings or regexps or macro variables or '%' operator
|
||||
if (stream.peek() == "%") {
|
||||
var style = "string";
|
||||
var embed = true;
|
||||
var delim;
|
||||
|
||||
if (stream.match("%r")) {
|
||||
// Regexps
|
||||
style = "string-2";
|
||||
delim = stream.next();
|
||||
} else if (stream.match("%w")) {
|
||||
embed = false;
|
||||
delim = stream.next();
|
||||
} else {
|
||||
if(delim = stream.match(/^%([^\w\s=])/)) {
|
||||
delim = delim[1];
|
||||
} else if (stream.match(/^%[a-zA-Z0-9_\u009F-\uFFFF]*/)) {
|
||||
// Macro variables
|
||||
return "meta";
|
||||
} else {
|
||||
// '%' operator
|
||||
return "operator";
|
||||
}
|
||||
}
|
||||
|
||||
if (matching.hasOwnProperty(delim)) {
|
||||
delim = matching[delim];
|
||||
}
|
||||
return chain(tokenQuote(delim, style, embed), stream, state);
|
||||
}
|
||||
|
||||
// Characters
|
||||
if (stream.eat("'")) {
|
||||
stream.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/);
|
||||
stream.eat("'");
|
||||
return "atom";
|
||||
}
|
||||
|
||||
// Numbers
|
||||
if (stream.eat("0")) {
|
||||
if (stream.eat("x")) {
|
||||
stream.match(/^[0-9a-fA-F]+/);
|
||||
} else if (stream.eat("o")) {
|
||||
stream.match(/^[0-7]+/);
|
||||
} else if (stream.eat("b")) {
|
||||
stream.match(/^[01]+/);
|
||||
}
|
||||
return "number";
|
||||
}
|
||||
|
||||
if (stream.eat(/\d/)) {
|
||||
stream.match(/^\d*(?:\.\d+)?(?:[eE][+-]?\d+)?/);
|
||||
return "number";
|
||||
}
|
||||
|
||||
// Operators
|
||||
if (stream.match(operators)) {
|
||||
stream.eat("="); // Operators can follow assign symbol.
|
||||
return "operator";
|
||||
}
|
||||
|
||||
if (stream.match(conditionalOperators) || stream.match(anotherOperators)) {
|
||||
return "operator";
|
||||
}
|
||||
|
||||
// Parens and braces
|
||||
if (matched = stream.match(/[({[]/, false)) {
|
||||
matched = matched[0];
|
||||
return chain(tokenNest(matched, matching[matched], null), stream, state);
|
||||
}
|
||||
|
||||
// Escapes
|
||||
if (stream.eat("\\")) {
|
||||
stream.next();
|
||||
return "meta";
|
||||
}
|
||||
|
||||
stream.next();
|
||||
return null;
|
||||
}
|
||||
|
||||
function tokenNest(begin, end, style, started) {
|
||||
return function (stream, state) {
|
||||
if (!started && stream.match(begin)) {
|
||||
state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true);
|
||||
state.currentIndent += 1;
|
||||
return style;
|
||||
}
|
||||
|
||||
var nextStyle = tokenBase(stream, state);
|
||||
if (stream.current() === end) {
|
||||
state.tokenize.pop();
|
||||
state.currentIndent -= 1;
|
||||
nextStyle = style;
|
||||
}
|
||||
|
||||
return nextStyle;
|
||||
};
|
||||
}
|
||||
|
||||
function tokenMacro(begin, end, started) {
|
||||
return function (stream, state) {
|
||||
if (!started && stream.match("{" + begin)) {
|
||||
state.currentIndent += 1;
|
||||
state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true);
|
||||
return "meta";
|
||||
}
|
||||
|
||||
if (stream.match(end + "}")) {
|
||||
state.currentIndent -= 1;
|
||||
state.tokenize.pop();
|
||||
return "meta";
|
||||
}
|
||||
|
||||
return tokenBase(stream, state);
|
||||
};
|
||||
}
|
||||
|
||||
function tokenMacroDef(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var matched;
|
||||
if (matched = stream.match(idents)) {
|
||||
if (matched == "def") {
|
||||
return "keyword";
|
||||
}
|
||||
stream.eat(/[?!]/);
|
||||
}
|
||||
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenFollowIdent(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (stream.match(idents)) {
|
||||
stream.eat(/[!?]/);
|
||||
} else {
|
||||
stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators);
|
||||
}
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenFollowType(stream, state) {
|
||||
if (stream.eatSpace()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stream.match(types);
|
||||
state.tokenize.pop();
|
||||
return "def";
|
||||
}
|
||||
|
||||
function tokenQuote(end, style, embed) {
|
||||
return function (stream, state) {
|
||||
var escaped = false;
|
||||
|
||||
while (stream.peek()) {
|
||||
if (!escaped) {
|
||||
if (stream.match("{%", false)) {
|
||||
state.tokenize.push(tokenMacro("%", "%"));
|
||||
return style;
|
||||
}
|
||||
|
||||
if (stream.match("{{", false)) {
|
||||
state.tokenize.push(tokenMacro("{", "}"));
|
||||
return style;
|
||||
}
|
||||
|
||||
if (embed && stream.match("#{", false)) {
|
||||
state.tokenize.push(tokenNest("#{", "}", "meta"));
|
||||
return style;
|
||||
}
|
||||
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch == end) {
|
||||
state.tokenize.pop();
|
||||
return style;
|
||||
}
|
||||
|
||||
escaped = ch == "\\";
|
||||
} else {
|
||||
stream.next();
|
||||
escaped = false;
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function () {
|
||||
return {
|
||||
tokenize: [tokenBase],
|
||||
currentIndent: 0,
|
||||
lastToken: null,
|
||||
blocks: []
|
||||
};
|
||||
},
|
||||
|
||||
token: function (stream, state) {
|
||||
var style = state.tokenize[state.tokenize.length - 1](stream, state);
|
||||
var token = stream.current();
|
||||
|
||||
if (style && style != "comment") {
|
||||
state.lastToken = token;
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
indent: function (state, textAfter) {
|
||||
textAfter = textAfter.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g, "");
|
||||
|
||||
if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) {
|
||||
return config.indentUnit * (state.currentIndent - 1);
|
||||
}
|
||||
|
||||
return config.indentUnit * state.currentIndent;
|
||||
},
|
||||
|
||||
fold: "indent",
|
||||
electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true),
|
||||
lineComment: '#'
|
||||
};
|
||||
});
|
||||
|
||||
CodeMirror.defineMIME("text/x-crystal", "crystal");
|
||||
});
|
||||
119
public/plugins/codemirror-5.17.0/mode/crystal/index.html
Normal file
119
public/plugins/codemirror-5.17.0/mode/crystal/index.html
Normal file
@@ -0,0 +1,119 @@
|
||||
<!doctype html>
|
||||
|
||||
<title>CodeMirror: Crystal mode</title>
|
||||
<meta charset="utf-8"/>
|
||||
<link rel=stylesheet href="../../doc/docs.css">
|
||||
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/matchbrackets.js"></script>
|
||||
<script src="crystal.js"></script>
|
||||
<style>
|
||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
||||
.cm-s-default span.cm-arrow { color: red; }
|
||||
</style>
|
||||
|
||||
<div id=nav>
|
||||
<a href="http://codemirror.net"><h1>CodeMirror</h1><img id=logo src="../../doc/logo.png"></a>
|
||||
|
||||
<ul>
|
||||
<li><a href="../../index.html">Home</a>
|
||||
<li><a href="../../doc/manual.html">Manual</a>
|
||||
<li><a href="https://github.com/codemirror/codemirror">Code</a>
|
||||
</ul>
|
||||
<ul>
|
||||
<li><a href="../index.html">Language modes</a>
|
||||
<li><a class=active href="#">Crystal</a>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<h2>Crystal mode</h2>
|
||||
<form><textarea id="code" name="code">
|
||||
# Features of Crystal
|
||||
# - Ruby-inspired syntax.
|
||||
# - Statically type-checked but without having to specify the type of variables or method arguments.
|
||||
# - Be able to call C code by writing bindings to it in Crystal.
|
||||
# - Have compile-time evaluation and generation of code, to avoid boilerplate code.
|
||||
# - Compile to efficient native code.
|
||||
|
||||
# A very basic HTTP server
|
||||
require "http/server"
|
||||
|
||||
server = HTTP::Server.new(8080) do |request|
|
||||
HTTP::Response.ok "text/plain", "Hello world, got #{request.path}!"
|
||||
end
|
||||
|
||||
puts "Listening on http://0.0.0.0:8080"
|
||||
server.listen
|
||||
|
||||
module Foo
|
||||
def initialize(@foo); end
|
||||
|
||||
abstract def abstract_method : String
|
||||
|
||||
@[AlwaysInline]
|
||||
def with_foofoo
|
||||
with Foo.new(self) yield
|
||||
end
|
||||
|
||||
struct Foo
|
||||
def initialize(@foo); end
|
||||
|
||||
def hello_world
|
||||
@foo.abstract_method
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Bar
|
||||
include Foo
|
||||
|
||||
@@foobar = 12345
|
||||
|
||||
def initialize(@bar)
|
||||
super(@bar.not_nil! + 100)
|
||||
end
|
||||
|
||||
macro alias_method(name, method)
|
||||
def {{ name }}(*args)
|
||||
{{ method }}(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def a_method
|
||||
"Hello, World"
|
||||
end
|
||||
|
||||
alias_method abstract_method, a_method
|
||||
|
||||
macro def show_instance_vars : Nil
|
||||
{% for var in @type.instance_vars %}
|
||||
puts "@{{ var }} = #{ @{{ var }} }"
|
||||
{% end %}
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
class Baz < Bar; end
|
||||
|
||||
lib LibC
|
||||
fun c_puts = "puts"(str : Char*) : Int
|
||||
end
|
||||
|
||||
$baz = Baz.new(100)
|
||||
$baz.show_instance_vars
|
||||
$baz.with_foofoo do
|
||||
LibC.c_puts hello_world
|
||||
end
|
||||
</textarea></form>
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: "text/x-crystal",
|
||||
matchBrackets: true,
|
||||
indentUnit: 2
|
||||
});
|
||||
</script>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-crystal</code>.</p>
|
||||
</article>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user